diff --git a/.gitignore b/.gitignore index 249423a..37f9da0 100644 --- a/.gitignore +++ b/.gitignore @@ -76,9 +76,9 @@ ehthumbs.db [Aa]ssets/Plugins/Android/*.aar # 忽略Packages目录,但保留manifest -[Pp]ackages/* -![Pp]ackages/manifest.json -![Pp]ackages/packages-lock.json +# [Pp]ackages/* +# ![Pp]ackages/manifest.json +# ![Pp]ackages/packages-lock.json # Timeline [Aa]ssets/**/[Tt]imeline/ diff --git a/Packages/com.bywaystudios.gameframework/Editor.meta b/Packages/com.bywaystudios.gameframework/Editor.meta new file mode 100644 index 0000000..ceb638a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2aa138f4f4780094290a8c340776447a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector.meta new file mode 100644 index 0000000..06b4dd1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4a3909aead6c5da4d94aba08883f0562 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/BaseComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/BaseComponentInspector.cs new file mode 100644 index 0000000..65d3792 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/BaseComponentInspector.cs @@ -0,0 +1,319 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(BaseComponent))] + internal sealed class BaseComponentInspector : GameFrameworkInspector + { + private const string NoneOptionName = ""; + private static readonly float[] GameSpeed = new float[] { 0f, 0.01f, 0.1f, 0.25f, 0.5f, 1f, 1.5f, 2f, 4f, 8f }; + private static readonly string[] GameSpeedForDisplay = new string[] { "0x", "0.01x", "0.1x", "0.25x", "0.5x", "1x", "1.5x", "2x", "4x", "8x" }; + + private SerializedProperty m_EditorResourceMode = null; + private SerializedProperty m_EditorLanguage = null; + private SerializedProperty m_TextHelperTypeName = null; + private SerializedProperty m_VersionHelperTypeName = null; + private SerializedProperty m_LogHelperTypeName = null; + private SerializedProperty m_CompressionHelperTypeName = null; + private SerializedProperty m_JsonHelperTypeName = null; + private SerializedProperty m_FrameRate = null; + private SerializedProperty m_GameSpeed = null; + private SerializedProperty m_RunInBackground = null; + private SerializedProperty m_NeverSleep = null; + + private string[] m_TextHelperTypeNames = null; + private int m_TextHelperTypeNameIndex = 0; + private string[] m_VersionHelperTypeNames = null; + private int m_VersionHelperTypeNameIndex = 0; + private string[] m_LogHelperTypeNames = null; + private int m_LogHelperTypeNameIndex = 0; + private string[] m_CompressionHelperTypeNames = null; + private int m_CompressionHelperTypeNameIndex = 0; + private string[] m_JsonHelperTypeNames = null; + private int m_JsonHelperTypeNameIndex = 0; + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + BaseComponent t = (BaseComponent)target; + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + m_EditorResourceMode.boolValue = EditorGUILayout.BeginToggleGroup("Editor Resource Mode", m_EditorResourceMode.boolValue); + { + EditorGUILayout.HelpBox("Editor resource mode option is only for editor mode. Game Framework will use editor resource files, which you should validate first.", MessageType.Warning); + EditorGUILayout.PropertyField(m_EditorLanguage); + EditorGUILayout.HelpBox("Editor language option is only use for localization test in editor mode.", MessageType.Info); + } + EditorGUILayout.EndToggleGroup(); + + EditorGUILayout.BeginVertical("box"); + { + EditorGUILayout.LabelField("Global Helpers", EditorStyles.boldLabel); + + int textHelperSelectedIndex = EditorGUILayout.Popup("Text Helper", m_TextHelperTypeNameIndex, m_TextHelperTypeNames); + if (textHelperSelectedIndex != m_TextHelperTypeNameIndex) + { + m_TextHelperTypeNameIndex = textHelperSelectedIndex; + m_TextHelperTypeName.stringValue = textHelperSelectedIndex <= 0 ? null : m_TextHelperTypeNames[textHelperSelectedIndex]; + } + + int versionHelperSelectedIndex = EditorGUILayout.Popup("Version Helper", m_VersionHelperTypeNameIndex, m_VersionHelperTypeNames); + if (versionHelperSelectedIndex != m_VersionHelperTypeNameIndex) + { + m_VersionHelperTypeNameIndex = versionHelperSelectedIndex; + m_VersionHelperTypeName.stringValue = versionHelperSelectedIndex <= 0 ? null : m_VersionHelperTypeNames[versionHelperSelectedIndex]; + } + + int logHelperSelectedIndex = EditorGUILayout.Popup("Log Helper", m_LogHelperTypeNameIndex, m_LogHelperTypeNames); + if (logHelperSelectedIndex != m_LogHelperTypeNameIndex) + { + m_LogHelperTypeNameIndex = logHelperSelectedIndex; + m_LogHelperTypeName.stringValue = logHelperSelectedIndex <= 0 ? null : m_LogHelperTypeNames[logHelperSelectedIndex]; + } + + int compressionHelperSelectedIndex = EditorGUILayout.Popup("Compression Helper", m_CompressionHelperTypeNameIndex, m_CompressionHelperTypeNames); + if (compressionHelperSelectedIndex != m_CompressionHelperTypeNameIndex) + { + m_CompressionHelperTypeNameIndex = compressionHelperSelectedIndex; + m_CompressionHelperTypeName.stringValue = compressionHelperSelectedIndex <= 0 ? null : m_CompressionHelperTypeNames[compressionHelperSelectedIndex]; + } + + int jsonHelperSelectedIndex = EditorGUILayout.Popup("JSON Helper", m_JsonHelperTypeNameIndex, m_JsonHelperTypeNames); + if (jsonHelperSelectedIndex != m_JsonHelperTypeNameIndex) + { + m_JsonHelperTypeNameIndex = jsonHelperSelectedIndex; + m_JsonHelperTypeName.stringValue = jsonHelperSelectedIndex <= 0 ? null : m_JsonHelperTypeNames[jsonHelperSelectedIndex]; + } + } + EditorGUILayout.EndVertical(); + } + EditorGUI.EndDisabledGroup(); + + int frameRate = EditorGUILayout.IntSlider("Frame Rate", m_FrameRate.intValue, 1, 120); + if (frameRate != m_FrameRate.intValue) + { + if (EditorApplication.isPlaying) + { + t.FrameRate = frameRate; + } + else + { + m_FrameRate.intValue = frameRate; + } + } + + EditorGUILayout.BeginVertical("box"); + { + float gameSpeed = EditorGUILayout.Slider("Game Speed", m_GameSpeed.floatValue, 0f, 8f); + int selectedGameSpeed = GUILayout.SelectionGrid(GetSelectedGameSpeed(gameSpeed), GameSpeedForDisplay, 5); + if (selectedGameSpeed >= 0) + { + gameSpeed = GetGameSpeed(selectedGameSpeed); + } + + if (gameSpeed != m_GameSpeed.floatValue) + { + if (EditorApplication.isPlaying) + { + t.GameSpeed = gameSpeed; + } + else + { + m_GameSpeed.floatValue = gameSpeed; + } + } + } + EditorGUILayout.EndVertical(); + + bool runInBackground = EditorGUILayout.Toggle("Run in Background", m_RunInBackground.boolValue); + if (runInBackground != m_RunInBackground.boolValue) + { + if (EditorApplication.isPlaying) + { + t.RunInBackground = runInBackground; + } + else + { + m_RunInBackground.boolValue = runInBackground; + } + } + + bool neverSleep = EditorGUILayout.Toggle("Never Sleep", m_NeverSleep.boolValue); + if (neverSleep != m_NeverSleep.boolValue) + { + if (EditorApplication.isPlaying) + { + t.NeverSleep = neverSleep; + } + else + { + m_NeverSleep.boolValue = neverSleep; + } + } + + serializedObject.ApplyModifiedProperties(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_EditorResourceMode = serializedObject.FindProperty("m_EditorResourceMode"); + m_EditorLanguage = serializedObject.FindProperty("m_EditorLanguage"); + m_TextHelperTypeName = serializedObject.FindProperty("m_TextHelperTypeName"); + m_VersionHelperTypeName = serializedObject.FindProperty("m_VersionHelperTypeName"); + m_LogHelperTypeName = serializedObject.FindProperty("m_LogHelperTypeName"); + m_CompressionHelperTypeName = serializedObject.FindProperty("m_CompressionHelperTypeName"); + m_JsonHelperTypeName = serializedObject.FindProperty("m_JsonHelperTypeName"); + m_FrameRate = serializedObject.FindProperty("m_FrameRate"); + m_GameSpeed = serializedObject.FindProperty("m_GameSpeed"); + m_RunInBackground = serializedObject.FindProperty("m_RunInBackground"); + m_NeverSleep = serializedObject.FindProperty("m_NeverSleep"); + + RefreshTypeNames(); + } + + private void RefreshTypeNames() + { + List textHelperTypeNames = new List + { + NoneOptionName + }; + + textHelperTypeNames.AddRange(Type.GetRuntimeTypeNames(typeof(Utility.Text.ITextHelper))); + m_TextHelperTypeNames = textHelperTypeNames.ToArray(); + m_TextHelperTypeNameIndex = 0; + if (!string.IsNullOrEmpty(m_TextHelperTypeName.stringValue)) + { + m_TextHelperTypeNameIndex = textHelperTypeNames.IndexOf(m_TextHelperTypeName.stringValue); + if (m_TextHelperTypeNameIndex <= 0) + { + m_TextHelperTypeNameIndex = 0; + m_TextHelperTypeName.stringValue = null; + } + } + + List versionHelperTypeNames = new List + { + NoneOptionName + }; + + versionHelperTypeNames.AddRange(Type.GetRuntimeTypeNames(typeof(Version.IVersionHelper))); + m_VersionHelperTypeNames = versionHelperTypeNames.ToArray(); + m_VersionHelperTypeNameIndex = 0; + if (!string.IsNullOrEmpty(m_VersionHelperTypeName.stringValue)) + { + m_VersionHelperTypeNameIndex = versionHelperTypeNames.IndexOf(m_VersionHelperTypeName.stringValue); + if (m_VersionHelperTypeNameIndex <= 0) + { + m_VersionHelperTypeNameIndex = 0; + m_VersionHelperTypeName.stringValue = null; + } + } + + List logHelperTypeNames = new List + { + NoneOptionName + }; + + logHelperTypeNames.AddRange(Type.GetRuntimeTypeNames(typeof(GameFrameworkLog.ILogHelper))); + m_LogHelperTypeNames = logHelperTypeNames.ToArray(); + m_LogHelperTypeNameIndex = 0; + if (!string.IsNullOrEmpty(m_LogHelperTypeName.stringValue)) + { + m_LogHelperTypeNameIndex = logHelperTypeNames.IndexOf(m_LogHelperTypeName.stringValue); + if (m_LogHelperTypeNameIndex <= 0) + { + m_LogHelperTypeNameIndex = 0; + m_LogHelperTypeName.stringValue = null; + } + } + + List compressionHelperTypeNames = new List + { + NoneOptionName + }; + + compressionHelperTypeNames.AddRange(Type.GetRuntimeTypeNames(typeof(Utility.Compression.ICompressionHelper))); + m_CompressionHelperTypeNames = compressionHelperTypeNames.ToArray(); + m_CompressionHelperTypeNameIndex = 0; + if (!string.IsNullOrEmpty(m_CompressionHelperTypeName.stringValue)) + { + m_CompressionHelperTypeNameIndex = compressionHelperTypeNames.IndexOf(m_CompressionHelperTypeName.stringValue); + if (m_CompressionHelperTypeNameIndex <= 0) + { + m_CompressionHelperTypeNameIndex = 0; + m_CompressionHelperTypeName.stringValue = null; + } + } + + List jsonHelperTypeNames = new List + { + NoneOptionName + }; + + jsonHelperTypeNames.AddRange(Type.GetRuntimeTypeNames(typeof(Utility.Json.IJsonHelper))); + m_JsonHelperTypeNames = jsonHelperTypeNames.ToArray(); + m_JsonHelperTypeNameIndex = 0; + if (!string.IsNullOrEmpty(m_JsonHelperTypeName.stringValue)) + { + m_JsonHelperTypeNameIndex = jsonHelperTypeNames.IndexOf(m_JsonHelperTypeName.stringValue); + if (m_JsonHelperTypeNameIndex <= 0) + { + m_JsonHelperTypeNameIndex = 0; + m_JsonHelperTypeName.stringValue = null; + } + } + + serializedObject.ApplyModifiedProperties(); + } + + private float GetGameSpeed(int selectedGameSpeed) + { + if (selectedGameSpeed < 0) + { + return GameSpeed[0]; + } + + if (selectedGameSpeed >= GameSpeed.Length) + { + return GameSpeed[GameSpeed.Length - 1]; + } + + return GameSpeed[selectedGameSpeed]; + } + + private int GetSelectedGameSpeed(float gameSpeed) + { + for (int i = 0; i < GameSpeed.Length; i++) + { + if (gameSpeed == GameSpeed[i]) + { + return i; + } + } + + return -1; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/BaseComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/BaseComponentInspector.cs.meta new file mode 100644 index 0000000..4d4704f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/BaseComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 55195676d06c1cd418e6f3201eae7176 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/ConfigComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ConfigComponentInspector.cs new file mode 100644 index 0000000..5773113 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ConfigComponentInspector.cs @@ -0,0 +1,74 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(ConfigComponent))] + internal sealed class ConfigComponentInspector : GameFrameworkInspector + { + private SerializedProperty m_EnableLoadConfigUpdateEvent = null; + private SerializedProperty m_EnableLoadConfigDependencyAssetEvent = null; + private SerializedProperty m_CachedBytesSize = null; + + private HelperInfo m_ConfigHelperInfo = new HelperInfo("Config"); + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + ConfigComponent t = (ConfigComponent)target; + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + EditorGUILayout.PropertyField(m_EnableLoadConfigUpdateEvent); + EditorGUILayout.PropertyField(m_EnableLoadConfigDependencyAssetEvent); + m_ConfigHelperInfo.Draw(); + EditorGUILayout.PropertyField(m_CachedBytesSize); + } + EditorGUI.EndDisabledGroup(); + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Config Count", t.Count.ToString()); + EditorGUILayout.LabelField("Cached Bytes Size", t.CachedBytesSize.ToString()); + } + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_EnableLoadConfigUpdateEvent = serializedObject.FindProperty("m_EnableLoadConfigUpdateEvent"); + m_EnableLoadConfigDependencyAssetEvent = serializedObject.FindProperty("m_EnableLoadConfigDependencyAssetEvent"); + m_CachedBytesSize = serializedObject.FindProperty("m_CachedBytesSize"); + + m_ConfigHelperInfo.Init(serializedObject); + + RefreshTypeNames(); + } + + private void RefreshTypeNames() + { + m_ConfigHelperInfo.Refresh(); + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/ConfigComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ConfigComponentInspector.cs.meta new file mode 100644 index 0000000..5f39ce0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ConfigComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4e450812c22c29141a8930ae4c8b7fe6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/DataNodeComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DataNodeComponentInspector.cs new file mode 100644 index 0000000..e05775a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DataNodeComponentInspector.cs @@ -0,0 +1,51 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.DataNode; +using UnityEditor; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(DataNodeComponent))] + internal sealed class DataNodeComponentInspector : GameFrameworkInspector + { + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + if (!EditorApplication.isPlaying) + { + EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info); + return; + } + + DataNodeComponent t = (DataNodeComponent)target; + + if (IsPrefabInHierarchy(t.gameObject)) + { + DrawDataNode(t.Root); + } + + Repaint(); + } + + private void OnEnable() + { + } + + private void DrawDataNode(IDataNode dataNode) + { + EditorGUILayout.LabelField(dataNode.FullName, dataNode.ToDataString()); + IDataNode[] child = dataNode.GetAllChild(); + foreach (IDataNode c in child) + { + DrawDataNode(c); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/DataNodeComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DataNodeComponentInspector.cs.meta new file mode 100644 index 0000000..8fd492c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DataNodeComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4ce0d352bae82974e86bfe9010a4bdfd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/DataTableComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DataTableComponentInspector.cs new file mode 100644 index 0000000..baf74af --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DataTableComponentInspector.cs @@ -0,0 +1,87 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.DataTable; +using UnityEditor; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(DataTableComponent))] + internal sealed class DataTableComponentInspector : GameFrameworkInspector + { + private SerializedProperty m_EnableLoadDataTableUpdateEvent = null; + private SerializedProperty m_EnableLoadDataTableDependencyAssetEvent = null; + private SerializedProperty m_CachedBytesSize = null; + + private HelperInfo m_DataTableHelperInfo = new HelperInfo("DataTable"); + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + DataTableComponent t = (DataTableComponent)target; + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + EditorGUILayout.PropertyField(m_EnableLoadDataTableUpdateEvent); + EditorGUILayout.PropertyField(m_EnableLoadDataTableDependencyAssetEvent); + m_DataTableHelperInfo.Draw(); + EditorGUILayout.PropertyField(m_CachedBytesSize); + } + EditorGUI.EndDisabledGroup(); + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Data Table Count", t.Count.ToString()); + EditorGUILayout.LabelField("Cached Bytes Size", t.CachedBytesSize.ToString()); + + DataTableBase[] dataTables = t.GetAllDataTables(); + foreach (DataTableBase dataTable in dataTables) + { + DrawDataTable(dataTable); + } + } + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_EnableLoadDataTableUpdateEvent = serializedObject.FindProperty("m_EnableLoadDataTableUpdateEvent"); + m_EnableLoadDataTableDependencyAssetEvent = serializedObject.FindProperty("m_EnableLoadDataTableDependencyAssetEvent"); + m_CachedBytesSize = serializedObject.FindProperty("m_CachedBytesSize"); + + m_DataTableHelperInfo.Init(serializedObject); + + RefreshTypeNames(); + } + + private void DrawDataTable(DataTableBase dataTable) + { + EditorGUILayout.LabelField(dataTable.FullName, Utility.Text.Format("{0} Rows", dataTable.Count)); + } + + private void RefreshTypeNames() + { + m_DataTableHelperInfo.Refresh(); + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/DataTableComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DataTableComponentInspector.cs.meta new file mode 100644 index 0000000..e53932d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DataTableComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 75e2902c828fd8a4cb81e6d743351074 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/DebuggerComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DebuggerComponentInspector.cs new file mode 100644 index 0000000..b3cb54d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DebuggerComponentInspector.cs @@ -0,0 +1,68 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(DebuggerComponent))] + internal sealed class DebuggerComponentInspector : GameFrameworkInspector + { + private SerializedProperty m_Skin = null; + private SerializedProperty m_ActiveWindow = null; + private SerializedProperty m_ShowFullWindow = null; + private SerializedProperty m_ConsoleWindow = null; + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + DebuggerComponent t = (DebuggerComponent)target; + + EditorGUILayout.PropertyField(m_Skin); + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + bool activeWindow = EditorGUILayout.Toggle("Active Window", t.ActiveWindow); + if (activeWindow != t.ActiveWindow) + { + t.ActiveWindow = activeWindow; + } + } + else + { + EditorGUILayout.PropertyField(m_ActiveWindow); + } + + EditorGUILayout.PropertyField(m_ShowFullWindow); + + if (EditorApplication.isPlaying) + { + if (GUILayout.Button("Reset Layout")) + { + t.ResetLayout(); + } + } + + EditorGUILayout.PropertyField(m_ConsoleWindow, true); + + serializedObject.ApplyModifiedProperties(); + } + + private void OnEnable() + { + m_Skin = serializedObject.FindProperty("m_Skin"); + m_ActiveWindow = serializedObject.FindProperty("m_ActiveWindow"); + m_ShowFullWindow = serializedObject.FindProperty("m_ShowFullWindow"); + m_ConsoleWindow = serializedObject.FindProperty("m_ConsoleWindow"); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/DebuggerComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DebuggerComponentInspector.cs.meta new file mode 100644 index 0000000..dfec8f9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DebuggerComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 482ae76a43c942249953b4c30ec4859b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/DownloadComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DownloadComponentInspector.cs new file mode 100644 index 0000000..0eb16b4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DownloadComponentInspector.cs @@ -0,0 +1,156 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.IO; +using System.Text; +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(DownloadComponent))] + internal sealed class DownloadComponentInspector : GameFrameworkInspector + { + private SerializedProperty m_InstanceRoot = null; + private SerializedProperty m_DownloadAgentHelperCount = null; + private SerializedProperty m_Timeout = null; + private SerializedProperty m_FlushSize = null; + + private HelperInfo m_DownloadAgentHelperInfo = new HelperInfo("DownloadAgent"); + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + DownloadComponent t = (DownloadComponent)target; + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + EditorGUILayout.PropertyField(m_InstanceRoot); + m_DownloadAgentHelperInfo.Draw(); + m_DownloadAgentHelperCount.intValue = EditorGUILayout.IntSlider("Download Agent Helper Count", m_DownloadAgentHelperCount.intValue, 1, 16); + } + EditorGUI.EndDisabledGroup(); + + float timeout = EditorGUILayout.Slider("Timeout", m_Timeout.floatValue, 0f, 120f); + if (timeout != m_Timeout.floatValue) + { + if (EditorApplication.isPlaying) + { + t.Timeout = timeout; + } + else + { + m_Timeout.floatValue = timeout; + } + } + + int flushSize = EditorGUILayout.DelayedIntField("Flush Size", m_FlushSize.intValue); + if (flushSize != m_FlushSize.intValue) + { + if (EditorApplication.isPlaying) + { + t.FlushSize = flushSize; + } + else + { + m_FlushSize.intValue = flushSize; + } + } + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Paused", t.Paused.ToString()); + EditorGUILayout.LabelField("Total Agent Count", t.TotalAgentCount.ToString()); + EditorGUILayout.LabelField("Free Agent Count", t.FreeAgentCount.ToString()); + EditorGUILayout.LabelField("Working Agent Count", t.WorkingAgentCount.ToString()); + EditorGUILayout.LabelField("Waiting Agent Count", t.WaitingTaskCount.ToString()); + EditorGUILayout.LabelField("Current Speed", t.CurrentSpeed.ToString()); + EditorGUILayout.BeginVertical("box"); + { + TaskInfo[] downloadInfos = t.GetAllDownloadInfos(); + if (downloadInfos.Length > 0) + { + foreach (TaskInfo downloadInfo in downloadInfos) + { + DrawDownloadInfo(downloadInfo); + } + + if (GUILayout.Button("Export CSV Data")) + { + string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, "Download Task Data.csv", string.Empty); + if (!string.IsNullOrEmpty(exportFileName)) + { + try + { + int index = 0; + string[] data = new string[downloadInfos.Length + 1]; + data[index++] = "Download Path,Serial Id,Tag,Priority,Status"; + foreach (TaskInfo downloadInfo in downloadInfos) + { + data[index++] = Utility.Text.Format("{0},{1},{2},{3},{4}", downloadInfo.Description, downloadInfo.SerialId, downloadInfo.Tag ?? string.Empty, downloadInfo.Priority, downloadInfo.Status); + } + + File.WriteAllLines(exportFileName, data, Encoding.UTF8); + Debug.Log(Utility.Text.Format("Export download task CSV data to '{0}' success.", exportFileName)); + } + catch (Exception exception) + { + Debug.LogError(Utility.Text.Format("Export download task CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception)); + } + } + } + } + else + { + GUILayout.Label("Download Task is Empty ..."); + } + } + EditorGUILayout.EndVertical(); + } + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot"); + m_DownloadAgentHelperCount = serializedObject.FindProperty("m_DownloadAgentHelperCount"); + m_Timeout = serializedObject.FindProperty("m_Timeout"); + m_FlushSize = serializedObject.FindProperty("m_FlushSize"); + + m_DownloadAgentHelperInfo.Init(serializedObject); + + RefreshTypeNames(); + } + + private void DrawDownloadInfo(TaskInfo downloadInfo) + { + EditorGUILayout.LabelField(downloadInfo.Description, Utility.Text.Format("[SerialId]{0} [Tag]{1} [Priority]{2} [Status]{3}", downloadInfo.SerialId, downloadInfo.Tag ?? "", downloadInfo.Priority, downloadInfo.Status)); + } + + private void RefreshTypeNames() + { + m_DownloadAgentHelperInfo.Refresh(); + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/DownloadComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DownloadComponentInspector.cs.meta new file mode 100644 index 0000000..77c77c7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/DownloadComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0e008c434c24c414cbee0f9e5191702e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/EditorResourceComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/EditorResourceComponentInspector.cs new file mode 100644 index 0000000..9d3b3e2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/EditorResourceComponentInspector.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(EditorResourceComponent))] + internal sealed class EditorResourceComponentInspector : GameFrameworkInspector + { + private SerializedProperty m_EnableCachedAssets = null; + private SerializedProperty m_LoadAssetCountPerFrame = null; + private SerializedProperty m_MinLoadAssetRandomDelaySeconds = null; + private SerializedProperty m_MaxLoadAssetRandomDelaySeconds = null; + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + EditorResourceComponent t = (EditorResourceComponent)target; + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Load Waiting Asset Count", t.LoadWaitingAssetCount.ToString()); + } + + EditorGUILayout.PropertyField(m_EnableCachedAssets); + EditorGUILayout.PropertyField(m_LoadAssetCountPerFrame); + EditorGUILayout.PropertyField(m_MinLoadAssetRandomDelaySeconds); + EditorGUILayout.PropertyField(m_MaxLoadAssetRandomDelaySeconds); + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + private void OnEnable() + { + m_EnableCachedAssets = serializedObject.FindProperty("m_EnableCachedAssets"); + m_LoadAssetCountPerFrame = serializedObject.FindProperty("m_LoadAssetCountPerFrame"); + m_MinLoadAssetRandomDelaySeconds = serializedObject.FindProperty("m_MinLoadAssetRandomDelaySeconds"); + m_MaxLoadAssetRandomDelaySeconds = serializedObject.FindProperty("m_MaxLoadAssetRandomDelaySeconds"); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/EditorResourceComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/EditorResourceComponentInspector.cs.meta new file mode 100644 index 0000000..1fe3447 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/EditorResourceComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5e657cda935f6f7409a2486383dd3208 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/EntityComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/EntityComponentInspector.cs new file mode 100644 index 0000000..13427ae --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/EntityComponentInspector.cs @@ -0,0 +1,88 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Entity; +using UnityEditor; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(EntityComponent))] + internal sealed class EntityComponentInspector : GameFrameworkInspector + { + private SerializedProperty m_EnableShowEntityUpdateEvent = null; + private SerializedProperty m_EnableShowEntityDependencyAssetEvent = null; + private SerializedProperty m_InstanceRoot = null; + private SerializedProperty m_EntityGroups = null; + + private HelperInfo m_EntityHelperInfo = new HelperInfo("Entity"); + private HelperInfo m_EntityGroupHelperInfo = new HelperInfo("EntityGroup"); + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + EntityComponent t = (EntityComponent)target; + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + EditorGUILayout.PropertyField(m_EnableShowEntityUpdateEvent); + EditorGUILayout.PropertyField(m_EnableShowEntityDependencyAssetEvent); + EditorGUILayout.PropertyField(m_InstanceRoot); + m_EntityHelperInfo.Draw(); + m_EntityGroupHelperInfo.Draw(); + EditorGUILayout.PropertyField(m_EntityGroups, true); + } + EditorGUI.EndDisabledGroup(); + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Entity Group Count", t.EntityGroupCount.ToString()); + EditorGUILayout.LabelField("Entity Count (Total)", t.EntityCount.ToString()); + IEntityGroup[] entityGroups = t.GetAllEntityGroups(); + foreach (IEntityGroup entityGroup in entityGroups) + { + EditorGUILayout.LabelField(Utility.Text.Format("Entity Count ({0})", entityGroup.Name), entityGroup.EntityCount.ToString()); + } + } + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_EnableShowEntityUpdateEvent = serializedObject.FindProperty("m_EnableShowEntityUpdateEvent"); + m_EnableShowEntityDependencyAssetEvent = serializedObject.FindProperty("m_EnableShowEntityDependencyAssetEvent"); + m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot"); + m_EntityGroups = serializedObject.FindProperty("m_EntityGroups"); + + m_EntityHelperInfo.Init(serializedObject); + m_EntityGroupHelperInfo.Init(serializedObject); + + RefreshTypeNames(); + } + + private void RefreshTypeNames() + { + m_EntityHelperInfo.Refresh(); + m_EntityGroupHelperInfo.Refresh(); + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/EntityComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/EntityComponentInspector.cs.meta new file mode 100644 index 0000000..4fdfeb6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/EntityComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 692b0cef6071a1342b8cc4e6ab9a2fb1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/EventComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/EventComponentInspector.cs new file mode 100644 index 0000000..a085344 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/EventComponentInspector.cs @@ -0,0 +1,41 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(EventComponent))] + internal sealed class EventComponentInspector : GameFrameworkInspector + { + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + if (!EditorApplication.isPlaying) + { + EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info); + return; + } + + EventComponent t = (EventComponent)target; + + if (IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Event Handler Count", t.EventHandlerCount.ToString()); + EditorGUILayout.LabelField("Event Count", t.EventCount.ToString()); + } + + Repaint(); + } + + private void OnEnable() + { + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/EventComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/EventComponentInspector.cs.meta new file mode 100644 index 0000000..0d573e3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/EventComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb23c608d69039c4dab132437b577ba1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/FileSystemComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/FileSystemComponentInspector.cs new file mode 100644 index 0000000..649e4ee --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/FileSystemComponentInspector.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.FileSystem; +using UnityEditor; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(FileSystemComponent))] + internal sealed class FileSystemComponentInspector : GameFrameworkInspector + { + private HelperInfo m_FileSystemHelperInfo = new HelperInfo("FileSystem"); + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + FileSystemComponent t = (FileSystemComponent)target; + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + m_FileSystemHelperInfo.Draw(); + } + EditorGUI.EndDisabledGroup(); + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("File System Count", t.Count.ToString()); + + IFileSystem[] fileSystems = t.GetAllFileSystems(); + foreach (IFileSystem fileSystem in fileSystems) + { + DrawFileSystem(fileSystem); + } + } + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_FileSystemHelperInfo.Init(serializedObject); + + RefreshTypeNames(); + } + + private void RefreshTypeNames() + { + m_FileSystemHelperInfo.Refresh(); + serializedObject.ApplyModifiedProperties(); + } + + private void DrawFileSystem(IFileSystem fileSystem) + { + EditorGUILayout.LabelField(fileSystem.FullPath, Utility.Text.Format("{0}, {1} / {2} Files", fileSystem.Access, fileSystem.FileCount, fileSystem.MaxFileCount)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/FileSystemComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/FileSystemComponentInspector.cs.meta new file mode 100644 index 0000000..2080778 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/FileSystemComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc83fe4d1e4c1ae41bdd9881023a44a7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/FsmComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/FsmComponentInspector.cs new file mode 100644 index 0000000..91960db --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/FsmComponentInspector.cs @@ -0,0 +1,53 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Fsm; +using UnityEditor; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(FsmComponent))] + internal sealed class FsmComponentInspector : GameFrameworkInspector + { + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + if (!EditorApplication.isPlaying) + { + EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info); + return; + } + + FsmComponent t = (FsmComponent)target; + + if (IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("FSM Count", t.Count.ToString()); + + FsmBase[] fsms = t.GetAllFsms(); + foreach (FsmBase fsm in fsms) + { + DrawFsm(fsm); + } + } + + Repaint(); + } + + private void OnEnable() + { + } + + private void DrawFsm(FsmBase fsm) + { + EditorGUILayout.LabelField(fsm.FullName, fsm.IsRunning ? Utility.Text.Format("{0}, {1:F1} s", fsm.CurrentStateName, fsm.CurrentStateTime) : (fsm.IsDestroyed ? "Destroyed" : "Not Running")); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/FsmComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/FsmComponentInspector.cs.meta new file mode 100644 index 0000000..1d1389e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/FsmComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 581c356e8f25d484792c21435f5794aa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/GameFrameworkInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/GameFrameworkInspector.cs new file mode 100644 index 0000000..421fd7c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/GameFrameworkInspector.cs @@ -0,0 +1,64 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; + +namespace UnityGameFramework.Editor +{ + /// + /// 游戏框架 Inspector 抽象类。 + /// + public abstract class GameFrameworkInspector : UnityEditor.Editor + { + private bool m_IsCompiling = false; + + /// + /// 绘制事件。 + /// + public override void OnInspectorGUI() + { + if (m_IsCompiling && !EditorApplication.isCompiling) + { + m_IsCompiling = false; + OnCompileComplete(); + } + else if (!m_IsCompiling && EditorApplication.isCompiling) + { + m_IsCompiling = true; + OnCompileStart(); + } + } + + /// + /// 编译开始事件。 + /// + protected virtual void OnCompileStart() + { + } + + /// + /// 编译完成事件。 + /// + protected virtual void OnCompileComplete() + { + } + + protected bool IsPrefabInHierarchy(UnityEngine.Object obj) + { + if (obj == null) + { + return false; + } + +#if UNITY_2018_3_OR_NEWER + return PrefabUtility.GetPrefabAssetType(obj) != PrefabAssetType.Regular; +#else + return PrefabUtility.GetPrefabType(obj) != PrefabType.Prefab; +#endif + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/GameFrameworkInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/GameFrameworkInspector.cs.meta new file mode 100644 index 0000000..5052ceb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/GameFrameworkInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b5bb373d9bcd4bd45861670fa5208e05 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/LocalizationComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/LocalizationComponentInspector.cs new file mode 100644 index 0000000..3bacb67 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/LocalizationComponentInspector.cs @@ -0,0 +1,76 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(LocalizationComponent))] + internal sealed class LocalizationComponentInspector : GameFrameworkInspector + { + private SerializedProperty m_EnableLoadDictionaryUpdateEvent = null; + private SerializedProperty m_EnableLoadDictionaryDependencyAssetEvent = null; + private SerializedProperty m_CachedBytesSize = null; + + private HelperInfo m_LocalizationHelperInfo = new HelperInfo("Localization"); + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + LocalizationComponent t = (LocalizationComponent)target; + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + EditorGUILayout.PropertyField(m_EnableLoadDictionaryUpdateEvent); + EditorGUILayout.PropertyField(m_EnableLoadDictionaryDependencyAssetEvent); + m_LocalizationHelperInfo.Draw(); + EditorGUILayout.PropertyField(m_CachedBytesSize); + } + EditorGUI.EndDisabledGroup(); + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Language", t.Language.ToString()); + EditorGUILayout.LabelField("System Language", t.SystemLanguage.ToString()); + EditorGUILayout.LabelField("Dictionary Count", t.DictionaryCount.ToString()); + EditorGUILayout.LabelField("Cached Bytes Size", t.CachedBytesSize.ToString()); + } + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_EnableLoadDictionaryUpdateEvent = serializedObject.FindProperty("m_EnableLoadDictionaryUpdateEvent"); + m_EnableLoadDictionaryDependencyAssetEvent = serializedObject.FindProperty("m_EnableLoadDictionaryDependencyAssetEvent"); + m_CachedBytesSize = serializedObject.FindProperty("m_CachedBytesSize"); + + m_LocalizationHelperInfo.Init(serializedObject); + + RefreshTypeNames(); + } + + private void RefreshTypeNames() + { + m_LocalizationHelperInfo.Refresh(); + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/LocalizationComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/LocalizationComponentInspector.cs.meta new file mode 100644 index 0000000..0d4401a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/LocalizationComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e90ad13aae4116347b57e87e5d00c94d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/NetworkComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/NetworkComponentInspector.cs new file mode 100644 index 0000000..8b5c31a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/NetworkComponentInspector.cs @@ -0,0 +1,76 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Network; +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(NetworkComponent))] + internal sealed class NetworkComponentInspector : GameFrameworkInspector + { + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + if (!EditorApplication.isPlaying) + { + EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info); + return; + } + + NetworkComponent t = (NetworkComponent)target; + + if (IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Network Channel Count", t.NetworkChannelCount.ToString()); + + INetworkChannel[] networkChannels = t.GetAllNetworkChannels(); + foreach (INetworkChannel networkChannel in networkChannels) + { + DrawNetworkChannel(networkChannel); + } + } + + Repaint(); + } + + private void OnEnable() + { + } + + private void DrawNetworkChannel(INetworkChannel networkChannel) + { + EditorGUILayout.BeginVertical("box"); + { + EditorGUILayout.LabelField(networkChannel.Name, networkChannel.Connected ? "Connected" : "Disconnected"); + EditorGUILayout.LabelField("Service Type", networkChannel.ServiceType.ToString()); + EditorGUILayout.LabelField("Address Family", networkChannel.AddressFamily.ToString()); + EditorGUILayout.LabelField("Local Address", networkChannel.Connected ? networkChannel.Socket.LocalEndPoint.ToString() : "Unavailable"); + EditorGUILayout.LabelField("Remote Address", networkChannel.Connected ? networkChannel.Socket.RemoteEndPoint.ToString() : "Unavailable"); + EditorGUILayout.LabelField("Send Packet", Utility.Text.Format("{0} / {1}", networkChannel.SendPacketCount, networkChannel.SentPacketCount)); + EditorGUILayout.LabelField("Receive Packet", Utility.Text.Format("{0} / {1}", networkChannel.ReceivePacketCount, networkChannel.ReceivedPacketCount)); + EditorGUILayout.LabelField("Miss Heart Beat Count", networkChannel.MissHeartBeatCount.ToString()); + EditorGUILayout.LabelField("Heart Beat", Utility.Text.Format("{0:F2} / {1:F2}", networkChannel.HeartBeatElapseSeconds, networkChannel.HeartBeatInterval)); + EditorGUI.BeginDisabledGroup(!networkChannel.Connected); + { + if (GUILayout.Button("Disconnect")) + { + networkChannel.Close(); + } + } + EditorGUI.EndDisabledGroup(); + } + EditorGUILayout.EndVertical(); + + EditorGUILayout.Separator(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/NetworkComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/NetworkComponentInspector.cs.meta new file mode 100644 index 0000000..1e13b26 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/NetworkComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7cbb7330261939244ac0b87d6798313a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/ObjectPoolComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ObjectPoolComponentInspector.cs new file mode 100644 index 0000000..8628c1f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ObjectPoolComponentInspector.cs @@ -0,0 +1,138 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.ObjectPool; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(ObjectPoolComponent))] + internal sealed class ObjectPoolComponentInspector : GameFrameworkInspector + { + private readonly HashSet m_OpenedItems = new HashSet(); + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + if (!EditorApplication.isPlaying) + { + EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info); + return; + } + + ObjectPoolComponent t = (ObjectPoolComponent)target; + + if (IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Object Pool Count", t.Count.ToString()); + + ObjectPoolBase[] objectPools = t.GetAllObjectPools(true); + foreach (ObjectPoolBase objectPool in objectPools) + { + DrawObjectPool(objectPool); + } + } + + Repaint(); + } + + private void OnEnable() + { + } + + private void DrawObjectPool(ObjectPoolBase objectPool) + { + bool lastState = m_OpenedItems.Contains(objectPool.FullName); + bool currentState = EditorGUILayout.Foldout(lastState, objectPool.FullName); + if (currentState != lastState) + { + if (currentState) + { + m_OpenedItems.Add(objectPool.FullName); + } + else + { + m_OpenedItems.Remove(objectPool.FullName); + } + } + + if (currentState) + { + EditorGUILayout.BeginVertical("box"); + { + EditorGUILayout.LabelField("Name", objectPool.Name); + EditorGUILayout.LabelField("Type", objectPool.ObjectType.FullName); + EditorGUILayout.LabelField("Auto Release Interval", objectPool.AutoReleaseInterval.ToString()); + EditorGUILayout.LabelField("Capacity", objectPool.Capacity.ToString()); + EditorGUILayout.LabelField("Used Count", objectPool.Count.ToString()); + EditorGUILayout.LabelField("Can Release Count", objectPool.CanReleaseCount.ToString()); + EditorGUILayout.LabelField("Expire Time", objectPool.ExpireTime.ToString()); + EditorGUILayout.LabelField("Priority", objectPool.Priority.ToString()); + ObjectInfo[] objectInfos = objectPool.GetAllObjectInfos(); + if (objectInfos.Length > 0) + { + EditorGUILayout.LabelField("Name", objectPool.AllowMultiSpawn ? "Locked\tCount\tFlag\tPriority\tLast Use Time" : "Locked\tIn Use\tFlag\tPriority\tLast Use Time"); + foreach (ObjectInfo objectInfo in objectInfos) + { + EditorGUILayout.LabelField(string.IsNullOrEmpty(objectInfo.Name) ? "" : objectInfo.Name, objectPool.AllowMultiSpawn ? Utility.Text.Format("{0}\t{1}\t{2}\t{3}\t{4:yyyy-MM-dd HH:mm:ss}", objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime()) : Utility.Text.Format("{0}\t{1}\t{2}\t{3}\t{4:yyyy-MM-dd HH:mm:ss}", objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime())); + } + + if (GUILayout.Button("Release")) + { + objectPool.Release(); + } + + if (GUILayout.Button("Release All Unused")) + { + objectPool.ReleaseAllUnused(); + } + + if (GUILayout.Button("Export CSV Data")) + { + string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, Utility.Text.Format("Object Pool Data - {0}.csv", objectPool.Name), string.Empty); + if (!string.IsNullOrEmpty(exportFileName)) + { + try + { + int index = 0; + string[] data = new string[objectInfos.Length + 1]; + data[index++] = Utility.Text.Format("Name,Locked,{0},Custom Can Release Flag,Priority,Last Use Time", objectPool.AllowMultiSpawn ? "Count" : "In Use"); + foreach (ObjectInfo objectInfo in objectInfos) + { + data[index++] = objectPool.AllowMultiSpawn ? Utility.Text.Format("{0},{1},{2},{3},{4},{5:yyyy-MM-dd HH:mm:ss}", objectInfo.Name, objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime()) : Utility.Text.Format("{0},{1},{2},{3},{4},{5:yyyy-MM-dd HH:mm:ss}", objectInfo.Name, objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime()); + } + + File.WriteAllLines(exportFileName, data, Encoding.UTF8); + Debug.Log(Utility.Text.Format("Export object pool CSV data to '{0}' success.", exportFileName)); + } + catch (Exception exception) + { + Debug.LogError(Utility.Text.Format("Export object pool CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception)); + } + } + } + } + else + { + GUILayout.Label("Object Pool is Empty ..."); + } + } + EditorGUILayout.EndVertical(); + + EditorGUILayout.Separator(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/ObjectPoolComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ObjectPoolComponentInspector.cs.meta new file mode 100644 index 0000000..26a3673 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ObjectPoolComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eb0d4111d9ba0ad469b2361c7731666a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/ProcedureComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ProcedureComponentInspector.cs new file mode 100644 index 0000000..664c1d9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ProcedureComponentInspector.cs @@ -0,0 +1,172 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Procedure; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(ProcedureComponent))] + internal sealed class ProcedureComponentInspector : GameFrameworkInspector + { + private SerializedProperty m_AvailableProcedureTypeNames = null; + private SerializedProperty m_EntranceProcedureTypeName = null; + + private string[] m_ProcedureTypeNames = null; + private List m_CurrentAvailableProcedureTypeNames = null; + private int m_EntranceProcedureIndex = -1; + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + ProcedureComponent t = (ProcedureComponent)target; + + if (string.IsNullOrEmpty(m_EntranceProcedureTypeName.stringValue)) + { + EditorGUILayout.HelpBox("Entrance procedure is invalid.", MessageType.Error); + } + else if (EditorApplication.isPlaying) + { + EditorGUILayout.LabelField("Current Procedure", t.CurrentProcedure == null ? "None" : t.CurrentProcedure.GetType().ToString()); + } + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + GUILayout.Label("Available Procedures", EditorStyles.boldLabel); + if (m_ProcedureTypeNames.Length > 0) + { + EditorGUILayout.BeginVertical("box"); + { + foreach (string procedureTypeName in m_ProcedureTypeNames) + { + bool selected = m_CurrentAvailableProcedureTypeNames.Contains(procedureTypeName); + if (selected != EditorGUILayout.ToggleLeft(procedureTypeName, selected)) + { + if (!selected) + { + m_CurrentAvailableProcedureTypeNames.Add(procedureTypeName); + WriteAvailableProcedureTypeNames(); + } + else if (procedureTypeName != m_EntranceProcedureTypeName.stringValue) + { + m_CurrentAvailableProcedureTypeNames.Remove(procedureTypeName); + WriteAvailableProcedureTypeNames(); + } + } + } + } + EditorGUILayout.EndVertical(); + } + else + { + EditorGUILayout.HelpBox("There is no available procedure.", MessageType.Warning); + } + + if (m_CurrentAvailableProcedureTypeNames.Count > 0) + { + EditorGUILayout.Separator(); + + int selectedIndex = EditorGUILayout.Popup("Entrance Procedure", m_EntranceProcedureIndex, m_CurrentAvailableProcedureTypeNames.ToArray()); + if (selectedIndex != m_EntranceProcedureIndex) + { + m_EntranceProcedureIndex = selectedIndex; + m_EntranceProcedureTypeName.stringValue = m_CurrentAvailableProcedureTypeNames[selectedIndex]; + } + } + else + { + EditorGUILayout.HelpBox("Select available procedures first.", MessageType.Info); + } + } + EditorGUI.EndDisabledGroup(); + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_AvailableProcedureTypeNames = serializedObject.FindProperty("m_AvailableProcedureTypeNames"); + m_EntranceProcedureTypeName = serializedObject.FindProperty("m_EntranceProcedureTypeName"); + + RefreshTypeNames(); + } + + private void RefreshTypeNames() + { + m_ProcedureTypeNames = Type.GetRuntimeTypeNames(typeof(ProcedureBase)); + ReadAvailableProcedureTypeNames(); + int oldCount = m_CurrentAvailableProcedureTypeNames.Count; + m_CurrentAvailableProcedureTypeNames = m_CurrentAvailableProcedureTypeNames.Where(x => m_ProcedureTypeNames.Contains(x)).ToList(); + if (m_CurrentAvailableProcedureTypeNames.Count != oldCount) + { + WriteAvailableProcedureTypeNames(); + } + else if (!string.IsNullOrEmpty(m_EntranceProcedureTypeName.stringValue)) + { + m_EntranceProcedureIndex = m_CurrentAvailableProcedureTypeNames.IndexOf(m_EntranceProcedureTypeName.stringValue); + if (m_EntranceProcedureIndex < 0) + { + m_EntranceProcedureTypeName.stringValue = null; + } + } + + serializedObject.ApplyModifiedProperties(); + } + + private void ReadAvailableProcedureTypeNames() + { + m_CurrentAvailableProcedureTypeNames = new List(); + int count = m_AvailableProcedureTypeNames.arraySize; + for (int i = 0; i < count; i++) + { + m_CurrentAvailableProcedureTypeNames.Add(m_AvailableProcedureTypeNames.GetArrayElementAtIndex(i).stringValue); + } + } + + private void WriteAvailableProcedureTypeNames() + { + m_AvailableProcedureTypeNames.ClearArray(); + if (m_CurrentAvailableProcedureTypeNames == null) + { + return; + } + + m_CurrentAvailableProcedureTypeNames.Sort(); + int count = m_CurrentAvailableProcedureTypeNames.Count; + for (int i = 0; i < count; i++) + { + m_AvailableProcedureTypeNames.InsertArrayElementAtIndex(i); + m_AvailableProcedureTypeNames.GetArrayElementAtIndex(i).stringValue = m_CurrentAvailableProcedureTypeNames[i]; + } + + if (!string.IsNullOrEmpty(m_EntranceProcedureTypeName.stringValue)) + { + m_EntranceProcedureIndex = m_CurrentAvailableProcedureTypeNames.IndexOf(m_EntranceProcedureTypeName.stringValue); + if (m_EntranceProcedureIndex < 0) + { + m_EntranceProcedureTypeName.stringValue = null; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/ProcedureComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ProcedureComponentInspector.cs.meta new file mode 100644 index 0000000..c391625 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ProcedureComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 64d014b25074fd64b995dd8a458b6973 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/ReferencePoolComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ReferencePoolComponentInspector.cs new file mode 100644 index 0000000..c5dc3a1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ReferencePoolComponentInspector.cs @@ -0,0 +1,152 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(ReferencePoolComponent))] + internal sealed class ReferencePoolComponentInspector : GameFrameworkInspector + { + private readonly Dictionary> m_ReferencePoolInfos = new Dictionary>(StringComparer.Ordinal); + private readonly HashSet m_OpenedItems = new HashSet(); + + private SerializedProperty m_EnableStrictCheck = null; + + private bool m_ShowFullClassName = false; + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + ReferencePoolComponent t = (ReferencePoolComponent)target; + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + bool enableStrictCheck = EditorGUILayout.Toggle("Enable Strict Check", t.EnableStrictCheck); + if (enableStrictCheck != t.EnableStrictCheck) + { + t.EnableStrictCheck = enableStrictCheck; + } + + EditorGUILayout.LabelField("Reference Pool Count", ReferencePool.Count.ToString()); + m_ShowFullClassName = EditorGUILayout.Toggle("Show Full Class Name", m_ShowFullClassName); + m_ReferencePoolInfos.Clear(); + ReferencePoolInfo[] referencePoolInfos = ReferencePool.GetAllReferencePoolInfos(); + foreach (ReferencePoolInfo referencePoolInfo in referencePoolInfos) + { + string assemblyName = referencePoolInfo.Type.Assembly.GetName().Name; + List results = null; + if (!m_ReferencePoolInfos.TryGetValue(assemblyName, out results)) + { + results = new List(); + m_ReferencePoolInfos.Add(assemblyName, results); + } + + results.Add(referencePoolInfo); + } + + foreach (KeyValuePair> assemblyReferencePoolInfo in m_ReferencePoolInfos) + { + bool lastState = m_OpenedItems.Contains(assemblyReferencePoolInfo.Key); + bool currentState = EditorGUILayout.Foldout(lastState, assemblyReferencePoolInfo.Key); + if (currentState != lastState) + { + if (currentState) + { + m_OpenedItems.Add(assemblyReferencePoolInfo.Key); + } + else + { + m_OpenedItems.Remove(assemblyReferencePoolInfo.Key); + } + } + + if (currentState) + { + EditorGUILayout.BeginVertical("box"); + { + EditorGUILayout.LabelField(m_ShowFullClassName ? "Full Class Name" : "Class Name", "Unused\tUsing\tAcquire\tRelease\tAdd\tRemove"); + assemblyReferencePoolInfo.Value.Sort(Comparison); + foreach (ReferencePoolInfo referencePoolInfo in assemblyReferencePoolInfo.Value) + { + DrawReferencePoolInfo(referencePoolInfo); + } + + if (GUILayout.Button("Export CSV Data")) + { + string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, Utility.Text.Format("Reference Pool Data - {0}.csv", assemblyReferencePoolInfo.Key), string.Empty); + if (!string.IsNullOrEmpty(exportFileName)) + { + try + { + int index = 0; + string[] data = new string[assemblyReferencePoolInfo.Value.Count + 1]; + data[index++] = "Class Name,Full Class Name,Unused,Using,Acquire,Release,Add,Remove"; + foreach (ReferencePoolInfo referencePoolInfo in assemblyReferencePoolInfo.Value) + { + data[index++] = Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7}", referencePoolInfo.Type.Name, referencePoolInfo.Type.FullName, referencePoolInfo.UnusedReferenceCount, referencePoolInfo.UsingReferenceCount, referencePoolInfo.AcquireReferenceCount, referencePoolInfo.ReleaseReferenceCount, referencePoolInfo.AddReferenceCount, referencePoolInfo.RemoveReferenceCount); + } + + File.WriteAllLines(exportFileName, data, Encoding.UTF8); + Debug.Log(Utility.Text.Format("Export reference pool CSV data to '{0}' success.", exportFileName)); + } + catch (Exception exception) + { + Debug.LogError(Utility.Text.Format("Export reference pool CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception)); + } + } + } + } + EditorGUILayout.EndVertical(); + + EditorGUILayout.Separator(); + } + } + } + else + { + EditorGUILayout.PropertyField(m_EnableStrictCheck); + } + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + private void OnEnable() + { + m_EnableStrictCheck = serializedObject.FindProperty("m_EnableStrictCheck"); + } + + private void DrawReferencePoolInfo(ReferencePoolInfo referencePoolInfo) + { + EditorGUILayout.LabelField(m_ShowFullClassName ? referencePoolInfo.Type.FullName : referencePoolInfo.Type.Name, Utility.Text.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}", referencePoolInfo.UnusedReferenceCount, referencePoolInfo.UsingReferenceCount, referencePoolInfo.AcquireReferenceCount, referencePoolInfo.ReleaseReferenceCount, referencePoolInfo.AddReferenceCount, referencePoolInfo.RemoveReferenceCount)); + } + + private int Comparison(ReferencePoolInfo a, ReferencePoolInfo b) + { + if (m_ShowFullClassName) + { + return a.Type.FullName.CompareTo(b.Type.FullName); + } + else + { + return a.Type.Name.CompareTo(b.Type.Name); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/ReferencePoolComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ReferencePoolComponentInspector.cs.meta new file mode 100644 index 0000000..defecb2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ReferencePoolComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 705a7441224da3d4cbc6593bdc58f167 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/ResourceComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ResourceComponentInspector.cs new file mode 100644 index 0000000..9bcda9e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ResourceComponentInspector.cs @@ -0,0 +1,397 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.IO; +using System.Reflection; +using System.Text; +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(ResourceComponent))] + internal sealed class ResourceComponentInspector : GameFrameworkInspector + { + private static readonly string[] ResourceModeNames = new string[] { "Package", "Updatable", "Updatable While Playing" }; + + private SerializedProperty m_ResourceMode = null; + private SerializedProperty m_ReadWritePathType = null; + private SerializedProperty m_MinUnloadUnusedAssetsInterval = null; + private SerializedProperty m_MaxUnloadUnusedAssetsInterval = null; + private SerializedProperty m_AssetAutoReleaseInterval = null; + private SerializedProperty m_AssetCapacity = null; + private SerializedProperty m_AssetExpireTime = null; + private SerializedProperty m_AssetPriority = null; + private SerializedProperty m_ResourceAutoReleaseInterval = null; + private SerializedProperty m_ResourceCapacity = null; + private SerializedProperty m_ResourceExpireTime = null; + private SerializedProperty m_ResourcePriority = null; + private SerializedProperty m_UpdatePrefixUri = null; + private SerializedProperty m_GenerateReadWriteVersionListLength = null; + private SerializedProperty m_UpdateRetryCount = null; + private SerializedProperty m_InstanceRoot = null; + private SerializedProperty m_LoadResourceAgentHelperCount = null; + + private FieldInfo m_EditorResourceModeFieldInfo = null; + + private int m_ResourceModeIndex = 0; + private HelperInfo m_ResourceHelperInfo = new HelperInfo("Resource"); + private HelperInfo m_LoadResourceAgentHelperInfo = new HelperInfo("LoadResourceAgent"); + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + ResourceComponent t = (ResourceComponent)target; + + bool isEditorResourceMode = (bool)m_EditorResourceModeFieldInfo.GetValue(target); + + if (isEditorResourceMode) + { + EditorGUILayout.HelpBox("Editor resource mode is enabled. Some options are disabled.", MessageType.Warning); + } + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.EnumPopup("Resource Mode", t.ResourceMode); + } + else + { + int selectedIndex = EditorGUILayout.Popup("Resource Mode", m_ResourceModeIndex, ResourceModeNames); + if (selectedIndex != m_ResourceModeIndex) + { + m_ResourceModeIndex = selectedIndex; + m_ResourceMode.enumValueIndex = selectedIndex + 1; + } + } + + m_ReadWritePathType.enumValueIndex = (int)(ReadWritePathType)EditorGUILayout.EnumPopup("Read-Write Path Type", t.ReadWritePathType); + } + EditorGUI.EndDisabledGroup(); + + float minUnloadUnusedAssetsInterval = EditorGUILayout.Slider("Min Unload Unused Assets Interval", m_MinUnloadUnusedAssetsInterval.floatValue, 0f, 3600f); + if (minUnloadUnusedAssetsInterval != m_MinUnloadUnusedAssetsInterval.floatValue) + { + if (EditorApplication.isPlaying) + { + t.MinUnloadUnusedAssetsInterval = minUnloadUnusedAssetsInterval; + } + else + { + m_MinUnloadUnusedAssetsInterval.floatValue = minUnloadUnusedAssetsInterval; + } + } + + float maxUnloadUnusedAssetsInterval = EditorGUILayout.Slider("Max Unload Unused Assets Interval", m_MaxUnloadUnusedAssetsInterval.floatValue, 0f, 3600f); + if (maxUnloadUnusedAssetsInterval != m_MaxUnloadUnusedAssetsInterval.floatValue) + { + if (EditorApplication.isPlaying) + { + t.MaxUnloadUnusedAssetsInterval = maxUnloadUnusedAssetsInterval; + } + else + { + m_MaxUnloadUnusedAssetsInterval.floatValue = maxUnloadUnusedAssetsInterval; + } + } + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlaying && isEditorResourceMode); + { + float assetAutoReleaseInterval = EditorGUILayout.DelayedFloatField("Asset Auto Release Interval", m_AssetAutoReleaseInterval.floatValue); + if (assetAutoReleaseInterval != m_AssetAutoReleaseInterval.floatValue) + { + if (EditorApplication.isPlaying) + { + t.AssetAutoReleaseInterval = assetAutoReleaseInterval; + } + else + { + m_AssetAutoReleaseInterval.floatValue = assetAutoReleaseInterval; + } + } + + int assetCapacity = EditorGUILayout.DelayedIntField("Asset Capacity", m_AssetCapacity.intValue); + if (assetCapacity != m_AssetCapacity.intValue) + { + if (EditorApplication.isPlaying) + { + t.AssetCapacity = assetCapacity; + } + else + { + m_AssetCapacity.intValue = assetCapacity; + } + } + + float assetExpireTime = EditorGUILayout.DelayedFloatField("Asset Expire Time", m_AssetExpireTime.floatValue); + if (assetExpireTime != m_AssetExpireTime.floatValue) + { + if (EditorApplication.isPlaying) + { + t.AssetExpireTime = assetExpireTime; + } + else + { + m_AssetExpireTime.floatValue = assetExpireTime; + } + } + + int assetPriority = EditorGUILayout.DelayedIntField("Asset Priority", m_AssetPriority.intValue); + if (assetPriority != m_AssetPriority.intValue) + { + if (EditorApplication.isPlaying) + { + t.AssetPriority = assetPriority; + } + else + { + m_AssetPriority.intValue = assetPriority; + } + } + + float resourceAutoReleaseInterval = EditorGUILayout.DelayedFloatField("Resource Auto Release Interval", m_ResourceAutoReleaseInterval.floatValue); + if (resourceAutoReleaseInterval != m_ResourceAutoReleaseInterval.floatValue) + { + if (EditorApplication.isPlaying) + { + t.ResourceAutoReleaseInterval = resourceAutoReleaseInterval; + } + else + { + m_ResourceAutoReleaseInterval.floatValue = resourceAutoReleaseInterval; + } + } + + int resourceCapacity = EditorGUILayout.DelayedIntField("Resource Capacity", m_ResourceCapacity.intValue); + if (resourceCapacity != m_ResourceCapacity.intValue) + { + if (EditorApplication.isPlaying) + { + t.ResourceCapacity = resourceCapacity; + } + else + { + m_ResourceCapacity.intValue = resourceCapacity; + } + } + + float resourceExpireTime = EditorGUILayout.DelayedFloatField("Resource Expire Time", m_ResourceExpireTime.floatValue); + if (resourceExpireTime != m_ResourceExpireTime.floatValue) + { + if (EditorApplication.isPlaying) + { + t.ResourceExpireTime = resourceExpireTime; + } + else + { + m_ResourceExpireTime.floatValue = resourceExpireTime; + } + } + + int resourcePriority = EditorGUILayout.DelayedIntField("Resource Priority", m_ResourcePriority.intValue); + if (resourcePriority != m_ResourcePriority.intValue) + { + if (EditorApplication.isPlaying) + { + t.ResourcePriority = resourcePriority; + } + else + { + m_ResourcePriority.intValue = resourcePriority; + } + } + + if (m_ResourceModeIndex > 0) + { + string updatePrefixUri = EditorGUILayout.DelayedTextField("Update Prefix Uri", m_UpdatePrefixUri.stringValue); + if (updatePrefixUri != m_UpdatePrefixUri.stringValue) + { + if (EditorApplication.isPlaying) + { + t.UpdatePrefixUri = updatePrefixUri; + } + else + { + m_UpdatePrefixUri.stringValue = updatePrefixUri; + } + } + + int generateReadWriteVersionListLength = EditorGUILayout.DelayedIntField("Generate Read-Write Version List Length", m_GenerateReadWriteVersionListLength.intValue); + if (generateReadWriteVersionListLength != m_GenerateReadWriteVersionListLength.intValue) + { + if (EditorApplication.isPlaying) + { + t.GenerateReadWriteVersionListLength = generateReadWriteVersionListLength; + } + else + { + m_GenerateReadWriteVersionListLength.intValue = generateReadWriteVersionListLength; + } + } + + int updateRetryCount = EditorGUILayout.DelayedIntField("Update Retry Count", m_UpdateRetryCount.intValue); + if (updateRetryCount != m_UpdateRetryCount.intValue) + { + if (EditorApplication.isPlaying) + { + t.UpdateRetryCount = updateRetryCount; + } + else + { + m_UpdateRetryCount.intValue = updateRetryCount; + } + } + } + } + EditorGUI.EndDisabledGroup(); + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + EditorGUILayout.PropertyField(m_InstanceRoot); + + m_ResourceHelperInfo.Draw(); + m_LoadResourceAgentHelperInfo.Draw(); + m_LoadResourceAgentHelperCount.intValue = EditorGUILayout.IntSlider("Load Resource Agent Helper Count", m_LoadResourceAgentHelperCount.intValue, 1, 128); + } + EditorGUI.EndDisabledGroup(); + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Unload Unused Assets", Utility.Text.Format("{0:F2} / {1:F2}", t.LastUnloadUnusedAssetsOperationElapseSeconds, t.MaxUnloadUnusedAssetsInterval)); + EditorGUILayout.LabelField("Read-Only Path", t.ReadOnlyPath.ToString()); + EditorGUILayout.LabelField("Read-Write Path", t.ReadWritePath.ToString()); + EditorGUILayout.LabelField("Current Variant", t.CurrentVariant ?? ""); + EditorGUILayout.LabelField("Applicable Game Version", isEditorResourceMode ? "N/A" : t.ApplicableGameVersion ?? ""); + EditorGUILayout.LabelField("Internal Resource Version", isEditorResourceMode ? "N/A" : t.InternalResourceVersion.ToString()); + EditorGUILayout.LabelField("Asset Count", isEditorResourceMode ? "N/A" : t.AssetCount.ToString()); + EditorGUILayout.LabelField("Resource Count", isEditorResourceMode ? "N/A" : t.ResourceCount.ToString()); + EditorGUILayout.LabelField("Resource Group Count", isEditorResourceMode ? "N/A" : t.ResourceGroupCount.ToString()); + if (m_ResourceModeIndex > 0) + { + EditorGUILayout.LabelField("Applying Resource Pack Path", isEditorResourceMode ? "N/A" : t.ApplyingResourcePackPath ?? ""); + EditorGUILayout.LabelField("Apply Waiting Count", isEditorResourceMode ? "N/A" : t.ApplyWaitingCount.ToString()); + EditorGUILayout.LabelField("Updating Resource Group", isEditorResourceMode ? "N/A" : t.UpdatingResourceGroup != null ? t.UpdatingResourceGroup.Name : ""); + EditorGUILayout.LabelField("Update Waiting Count", isEditorResourceMode ? "N/A" : t.UpdateWaitingCount.ToString()); + EditorGUILayout.LabelField("Update Waiting While Playing Count", isEditorResourceMode ? "N/A" : t.UpdateWaitingWhilePlayingCount.ToString()); + EditorGUILayout.LabelField("Update Candidate Count", isEditorResourceMode ? "N/A" : t.UpdateCandidateCount.ToString()); + } + EditorGUILayout.LabelField("Load Total Agent Count", isEditorResourceMode ? "N/A" : t.LoadTotalAgentCount.ToString()); + EditorGUILayout.LabelField("Load Free Agent Count", isEditorResourceMode ? "N/A" : t.LoadFreeAgentCount.ToString()); + EditorGUILayout.LabelField("Load Working Agent Count", isEditorResourceMode ? "N/A" : t.LoadWorkingAgentCount.ToString()); + EditorGUILayout.LabelField("Load Waiting Task Count", isEditorResourceMode ? "N/A" : t.LoadWaitingTaskCount.ToString()); + if (!isEditorResourceMode) + { + EditorGUILayout.BeginVertical("box"); + { + TaskInfo[] loadAssetInfos = t.GetAllLoadAssetInfos(); + if (loadAssetInfos.Length > 0) + { + foreach (TaskInfo loadAssetInfo in loadAssetInfos) + { + DrawLoadAssetInfo(loadAssetInfo); + } + + if (GUILayout.Button("Export CSV Data")) + { + string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, "Load Asset Task Data.csv", string.Empty); + if (!string.IsNullOrEmpty(exportFileName)) + { + try + { + int index = 0; + string[] data = new string[loadAssetInfos.Length + 1]; + data[index++] = "Load Asset Name,Serial Id,Priority,Status"; + foreach (TaskInfo loadAssetInfo in loadAssetInfos) + { + data[index++] = Utility.Text.Format("{0},{1},{2},{3}", loadAssetInfo.Description, loadAssetInfo.SerialId, loadAssetInfo.Priority, loadAssetInfo.Status); + } + + File.WriteAllLines(exportFileName, data, Encoding.UTF8); + Debug.Log(Utility.Text.Format("Export load asset task CSV data to '{0}' success.", exportFileName)); + } + catch (Exception exception) + { + Debug.LogError(Utility.Text.Format("Export load asset task CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception)); + } + } + } + } + else + { + GUILayout.Label("Load Asset Task is Empty ..."); + } + } + EditorGUILayout.EndVertical(); + } + } + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_ResourceMode = serializedObject.FindProperty("m_ResourceMode"); + m_ReadWritePathType = serializedObject.FindProperty("m_ReadWritePathType"); + m_MinUnloadUnusedAssetsInterval = serializedObject.FindProperty("m_MinUnloadUnusedAssetsInterval"); + m_MaxUnloadUnusedAssetsInterval = serializedObject.FindProperty("m_MaxUnloadUnusedAssetsInterval"); + m_AssetAutoReleaseInterval = serializedObject.FindProperty("m_AssetAutoReleaseInterval"); + m_AssetCapacity = serializedObject.FindProperty("m_AssetCapacity"); + m_AssetExpireTime = serializedObject.FindProperty("m_AssetExpireTime"); + m_AssetPriority = serializedObject.FindProperty("m_AssetPriority"); + m_ResourceAutoReleaseInterval = serializedObject.FindProperty("m_ResourceAutoReleaseInterval"); + m_ResourceCapacity = serializedObject.FindProperty("m_ResourceCapacity"); + m_ResourceExpireTime = serializedObject.FindProperty("m_ResourceExpireTime"); + m_ResourcePriority = serializedObject.FindProperty("m_ResourcePriority"); + m_UpdatePrefixUri = serializedObject.FindProperty("m_UpdatePrefixUri"); + m_GenerateReadWriteVersionListLength = serializedObject.FindProperty("m_GenerateReadWriteVersionListLength"); + m_UpdateRetryCount = serializedObject.FindProperty("m_UpdateRetryCount"); + m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot"); + m_LoadResourceAgentHelperCount = serializedObject.FindProperty("m_LoadResourceAgentHelperCount"); + + m_EditorResourceModeFieldInfo = target.GetType().GetField("m_EditorResourceMode", BindingFlags.NonPublic | BindingFlags.Instance); + + m_ResourceHelperInfo.Init(serializedObject); + m_LoadResourceAgentHelperInfo.Init(serializedObject); + + RefreshModes(); + RefreshTypeNames(); + } + + private void DrawLoadAssetInfo(TaskInfo loadAssetInfo) + { + EditorGUILayout.LabelField(loadAssetInfo.Description, Utility.Text.Format("[SerialId]{0} [Priority]{1} [Status]{2}", loadAssetInfo.SerialId, loadAssetInfo.Priority, loadAssetInfo.Status)); + } + + private void RefreshModes() + { + m_ResourceModeIndex = m_ResourceMode.enumValueIndex > 0 ? m_ResourceMode.enumValueIndex - 1 : 0; + } + + private void RefreshTypeNames() + { + m_ResourceHelperInfo.Refresh(); + m_LoadResourceAgentHelperInfo.Refresh(); + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/ResourceComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ResourceComponentInspector.cs.meta new file mode 100644 index 0000000..f6bbc5c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/ResourceComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0ccae18b98b018e4baa1cb3063cece63 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/SceneComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/SceneComponentInspector.cs new file mode 100644 index 0000000..4d38bec --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/SceneComponentInspector.cs @@ -0,0 +1,75 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(SceneComponent))] + internal sealed class SceneComponentInspector : GameFrameworkInspector + { + private SerializedProperty m_EnableLoadSceneUpdateEvent = null; + private SerializedProperty m_EnableLoadSceneDependencyAssetEvent = null; + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + SceneComponent t = (SceneComponent)target; + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + EditorGUILayout.PropertyField(m_EnableLoadSceneUpdateEvent); + EditorGUILayout.PropertyField(m_EnableLoadSceneDependencyAssetEvent); + } + EditorGUI.EndDisabledGroup(); + + serializedObject.ApplyModifiedProperties(); + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Loaded Scene Asset Names", GetSceneNameString(t.GetLoadedSceneAssetNames())); + EditorGUILayout.LabelField("Loading Scene Asset Names", GetSceneNameString(t.GetLoadingSceneAssetNames())); + EditorGUILayout.LabelField("Unloading Scene Asset Names", GetSceneNameString(t.GetUnloadingSceneAssetNames())); + EditorGUILayout.ObjectField("Main Camera", t.MainCamera, typeof(Camera), true); + + Repaint(); + } + } + + private void OnEnable() + { + m_EnableLoadSceneUpdateEvent = serializedObject.FindProperty("m_EnableLoadSceneUpdateEvent"); + m_EnableLoadSceneDependencyAssetEvent = serializedObject.FindProperty("m_EnableLoadSceneDependencyAssetEvent"); + } + + private string GetSceneNameString(string[] sceneAssetNames) + { + if (sceneAssetNames == null || sceneAssetNames.Length <= 0) + { + return ""; + } + + string sceneNameString = string.Empty; + foreach (string sceneAssetName in sceneAssetNames) + { + if (!string.IsNullOrEmpty(sceneNameString)) + { + sceneNameString += ", "; + } + + sceneNameString += SceneComponent.GetSceneName(sceneAssetName); + } + + return sceneNameString; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/SceneComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/SceneComponentInspector.cs.meta new file mode 100644 index 0000000..fd15fb3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/SceneComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 91ac1b5e58b58c843bcdf37998e18bcd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/SettingComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/SettingComponentInspector.cs new file mode 100644 index 0000000..5d16bda --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/SettingComponentInspector.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(SettingComponent))] + internal sealed class SettingComponentInspector : GameFrameworkInspector + { + private HelperInfo m_SettingHelperInfo = new HelperInfo("Setting"); + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + SettingComponent t = (SettingComponent)target; + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + m_SettingHelperInfo.Draw(); + } + EditorGUI.EndDisabledGroup(); + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Setting Count", t.Count >= 0 ? t.Count.ToString() : ""); + if (t.Count > 0) + { + string[] settingNames = t.GetAllSettingNames(); + foreach (string settingName in settingNames) + { + EditorGUILayout.LabelField(settingName, t.GetString(settingName)); + } + } + } + + if (EditorApplication.isPlaying) + { + if (GUILayout.Button("Save Settings")) + { + t.Save(); + } + if (GUILayout.Button("Remove All Settings")) + { + t.RemoveAllSettings(); + } + } + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_SettingHelperInfo.Init(serializedObject); + + RefreshTypeNames(); + } + + private void RefreshTypeNames() + { + m_SettingHelperInfo.Refresh(); + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/SettingComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/SettingComponentInspector.cs.meta new file mode 100644 index 0000000..ad940eb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/SettingComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 079e17267e9ff8d489d7647323861ce8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/SoundComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/SoundComponentInspector.cs new file mode 100644 index 0000000..c83e50e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/SoundComponentInspector.cs @@ -0,0 +1,87 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(SoundComponent))] + internal sealed class SoundComponentInspector : GameFrameworkInspector + { + private SerializedProperty m_EnablePlaySoundUpdateEvent = null; + private SerializedProperty m_EnablePlaySoundDependencyAssetEvent = null; + private SerializedProperty m_InstanceRoot = null; + private SerializedProperty m_AudioMixer = null; + private SerializedProperty m_SoundGroups = null; + + private HelperInfo m_SoundHelperInfo = new HelperInfo("Sound"); + private HelperInfo m_SoundGroupHelperInfo = new HelperInfo("SoundGroup"); + private HelperInfo m_SoundAgentHelperInfo = new HelperInfo("SoundAgent"); + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + SoundComponent t = (SoundComponent)target; + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + EditorGUILayout.PropertyField(m_EnablePlaySoundUpdateEvent); + EditorGUILayout.PropertyField(m_EnablePlaySoundDependencyAssetEvent); + EditorGUILayout.PropertyField(m_InstanceRoot); + EditorGUILayout.PropertyField(m_AudioMixer); + m_SoundHelperInfo.Draw(); + m_SoundGroupHelperInfo.Draw(); + m_SoundAgentHelperInfo.Draw(); + EditorGUILayout.PropertyField(m_SoundGroups, true); + } + EditorGUI.EndDisabledGroup(); + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Sound Group Count", t.SoundGroupCount.ToString()); + } + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_EnablePlaySoundUpdateEvent = serializedObject.FindProperty("m_EnablePlaySoundUpdateEvent"); + m_EnablePlaySoundDependencyAssetEvent = serializedObject.FindProperty("m_EnablePlaySoundDependencyAssetEvent"); + m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot"); + m_AudioMixer = serializedObject.FindProperty("m_AudioMixer"); + m_SoundGroups = serializedObject.FindProperty("m_SoundGroups"); + + m_SoundHelperInfo.Init(serializedObject); + m_SoundGroupHelperInfo.Init(serializedObject); + m_SoundAgentHelperInfo.Init(serializedObject); + + RefreshTypeNames(); + } + + private void RefreshTypeNames() + { + m_SoundHelperInfo.Refresh(); + m_SoundGroupHelperInfo.Refresh(); + m_SoundAgentHelperInfo.Refresh(); + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/SoundComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/SoundComponentInspector.cs.meta new file mode 100644 index 0000000..e2bdf69 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/SoundComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cba40a4571929b14098014e7b931c2ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/UIComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/UIComponentInspector.cs new file mode 100644 index 0000000..0f700ca --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/UIComponentInspector.cs @@ -0,0 +1,154 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(UIComponent))] + internal sealed class UIComponentInspector : GameFrameworkInspector + { + private SerializedProperty m_EnableOpenUIFormSuccessEvent = null; + private SerializedProperty m_EnableOpenUIFormFailureEvent = null; + private SerializedProperty m_EnableOpenUIFormUpdateEvent = null; + private SerializedProperty m_EnableOpenUIFormDependencyAssetEvent = null; + private SerializedProperty m_EnableCloseUIFormCompleteEvent = null; + private SerializedProperty m_InstanceAutoReleaseInterval = null; + private SerializedProperty m_InstanceCapacity = null; + private SerializedProperty m_InstanceExpireTime = null; + private SerializedProperty m_InstancePriority = null; + private SerializedProperty m_InstanceRoot = null; + private SerializedProperty m_UIGroups = null; + + private HelperInfo m_UIFormHelperInfo = new HelperInfo("UIForm"); + private HelperInfo m_UIGroupHelperInfo = new HelperInfo("UIGroup"); + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + UIComponent t = (UIComponent)target; + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + EditorGUILayout.PropertyField(m_EnableOpenUIFormSuccessEvent); + EditorGUILayout.PropertyField(m_EnableOpenUIFormFailureEvent); + EditorGUILayout.PropertyField(m_EnableOpenUIFormUpdateEvent); + EditorGUILayout.PropertyField(m_EnableOpenUIFormDependencyAssetEvent); + EditorGUILayout.PropertyField(m_EnableCloseUIFormCompleteEvent); + } + EditorGUI.EndDisabledGroup(); + + float instanceAutoReleaseInterval = EditorGUILayout.DelayedFloatField("Instance Auto Release Interval", m_InstanceAutoReleaseInterval.floatValue); + if (instanceAutoReleaseInterval != m_InstanceAutoReleaseInterval.floatValue) + { + if (EditorApplication.isPlaying) + { + t.InstanceAutoReleaseInterval = instanceAutoReleaseInterval; + } + else + { + m_InstanceAutoReleaseInterval.floatValue = instanceAutoReleaseInterval; + } + } + + int instanceCapacity = EditorGUILayout.DelayedIntField("Instance Capacity", m_InstanceCapacity.intValue); + if (instanceCapacity != m_InstanceCapacity.intValue) + { + if (EditorApplication.isPlaying) + { + t.InstanceCapacity = instanceCapacity; + } + else + { + m_InstanceCapacity.intValue = instanceCapacity; + } + } + + float instanceExpireTime = EditorGUILayout.DelayedFloatField("Instance Expire Time", m_InstanceExpireTime.floatValue); + if (instanceExpireTime != m_InstanceExpireTime.floatValue) + { + if (EditorApplication.isPlaying) + { + t.InstanceExpireTime = instanceExpireTime; + } + else + { + m_InstanceExpireTime.floatValue = instanceExpireTime; + } + } + + int instancePriority = EditorGUILayout.DelayedIntField("Instance Priority", m_InstancePriority.intValue); + if (instancePriority != m_InstancePriority.intValue) + { + if (EditorApplication.isPlaying) + { + t.InstancePriority = instancePriority; + } + else + { + m_InstancePriority.intValue = instancePriority; + } + } + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + EditorGUILayout.PropertyField(m_InstanceRoot); + m_UIFormHelperInfo.Draw(); + m_UIGroupHelperInfo.Draw(); + EditorGUILayout.PropertyField(m_UIGroups, true); + } + EditorGUI.EndDisabledGroup(); + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("UI Group Count", t.UIGroupCount.ToString()); + } + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_EnableOpenUIFormSuccessEvent = serializedObject.FindProperty("m_EnableOpenUIFormSuccessEvent"); + m_EnableOpenUIFormFailureEvent = serializedObject.FindProperty("m_EnableOpenUIFormFailureEvent"); + m_EnableOpenUIFormUpdateEvent = serializedObject.FindProperty("m_EnableOpenUIFormUpdateEvent"); + m_EnableOpenUIFormDependencyAssetEvent = serializedObject.FindProperty("m_EnableOpenUIFormDependencyAssetEvent"); + m_EnableCloseUIFormCompleteEvent = serializedObject.FindProperty("m_EnableCloseUIFormCompleteEvent"); + m_InstanceAutoReleaseInterval = serializedObject.FindProperty("m_InstanceAutoReleaseInterval"); + m_InstanceCapacity = serializedObject.FindProperty("m_InstanceCapacity"); + m_InstanceExpireTime = serializedObject.FindProperty("m_InstanceExpireTime"); + m_InstancePriority = serializedObject.FindProperty("m_InstancePriority"); + m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot"); + m_UIGroups = serializedObject.FindProperty("m_UIGroups"); + + m_UIFormHelperInfo.Init(serializedObject); + m_UIGroupHelperInfo.Init(serializedObject); + + RefreshTypeNames(); + } + + private void RefreshTypeNames() + { + m_UIFormHelperInfo.Refresh(); + m_UIGroupHelperInfo.Refresh(); + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/UIComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/UIComponentInspector.cs.meta new file mode 100644 index 0000000..4e077c6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/UIComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6ae3c7028e65d19458efb14da7adf64b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/WebRequestComponentInspector.cs b/Packages/com.bywaystudios.gameframework/Editor/Inspector/WebRequestComponentInspector.cs new file mode 100644 index 0000000..e82ad8d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/WebRequestComponentInspector.cs @@ -0,0 +1,141 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.IO; +using System.Text; +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor +{ + [CustomEditor(typeof(WebRequestComponent))] + internal sealed class WebRequestComponentInspector : GameFrameworkInspector + { + private SerializedProperty m_InstanceRoot = null; + private SerializedProperty m_WebRequestAgentHelperCount = null; + private SerializedProperty m_Timeout = null; + + private HelperInfo m_WebRequestAgentHelperInfo = new HelperInfo("WebRequestAgent"); + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + serializedObject.Update(); + + WebRequestComponent t = (WebRequestComponent)target; + + EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); + { + EditorGUILayout.PropertyField(m_InstanceRoot); + + m_WebRequestAgentHelperInfo.Draw(); + + m_WebRequestAgentHelperCount.intValue = EditorGUILayout.IntSlider("Web Request Agent Helper Count", m_WebRequestAgentHelperCount.intValue, 1, 16); + } + EditorGUI.EndDisabledGroup(); + + float timeout = EditorGUILayout.Slider("Timeout", m_Timeout.floatValue, 0f, 120f); + if (timeout != m_Timeout.floatValue) + { + if (EditorApplication.isPlaying) + { + t.Timeout = timeout; + } + else + { + m_Timeout.floatValue = timeout; + } + } + + if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject)) + { + EditorGUILayout.LabelField("Total Agent Count", t.TotalAgentCount.ToString()); + EditorGUILayout.LabelField("Free Agent Count", t.FreeAgentCount.ToString()); + EditorGUILayout.LabelField("Working Agent Count", t.WorkingAgentCount.ToString()); + EditorGUILayout.LabelField("Waiting Agent Count", t.WaitingTaskCount.ToString()); + EditorGUILayout.BeginVertical("box"); + { + TaskInfo[] webRequestInfos = t.GetAllWebRequestInfos(); + if (webRequestInfos.Length > 0) + { + foreach (TaskInfo webRequestInfo in webRequestInfos) + { + DrawWebRequestInfo(webRequestInfo); + } + + if (GUILayout.Button("Export CSV Data")) + { + string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, "WebRequest Task Data.csv", string.Empty); + if (!string.IsNullOrEmpty(exportFileName)) + { + try + { + int index = 0; + string[] data = new string[webRequestInfos.Length + 1]; + data[index++] = "WebRequest Uri,Serial Id,Tag,Priority,Status"; + foreach (TaskInfo webRequestInfo in webRequestInfos) + { + data[index++] = Utility.Text.Format("{0},{1},{2},{3},{4}", webRequestInfo.Description, webRequestInfo.SerialId, webRequestInfo.Tag ?? string.Empty, webRequestInfo.Priority, webRequestInfo.Status); + } + + File.WriteAllLines(exportFileName, data, Encoding.UTF8); + Debug.Log(Utility.Text.Format("Export web request task CSV data to '{0}' success.", exportFileName)); + } + catch (Exception exception) + { + Debug.LogError(Utility.Text.Format("Export web request task CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception)); + } + } + } + } + else + { + GUILayout.Label("WebRequset Task is Empty ..."); + } + } + EditorGUILayout.EndVertical(); + } + + serializedObject.ApplyModifiedProperties(); + + Repaint(); + } + + protected override void OnCompileComplete() + { + base.OnCompileComplete(); + + RefreshTypeNames(); + } + + private void OnEnable() + { + m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot"); + m_WebRequestAgentHelperCount = serializedObject.FindProperty("m_WebRequestAgentHelperCount"); + m_Timeout = serializedObject.FindProperty("m_Timeout"); + + m_WebRequestAgentHelperInfo.Init(serializedObject); + + RefreshTypeNames(); + } + + private void DrawWebRequestInfo(TaskInfo webRequestInfo) + { + EditorGUILayout.LabelField(webRequestInfo.Description, Utility.Text.Format("[SerialId]{0} [Tag]{1} [Priority]{2} [Status]{3}", webRequestInfo.SerialId, webRequestInfo.Tag ?? "", webRequestInfo.Priority, webRequestInfo.Status)); + } + + private void RefreshTypeNames() + { + m_WebRequestAgentHelperInfo.Refresh(); + serializedObject.ApplyModifiedProperties(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Inspector/WebRequestComponentInspector.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Inspector/WebRequestComponentInspector.cs.meta new file mode 100644 index 0000000..20ee463 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Inspector/WebRequestComponentInspector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dbb0e62b54d44b74dab4b9a49e186d0f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc.meta b/Packages/com.bywaystudios.gameframework/Editor/Misc.meta new file mode 100644 index 0000000..5bb2b39 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 491d19006ebbf6248832da552a08c5be +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/BuildSettings.cs b/Packages/com.bywaystudios.gameframework/Editor/Misc/BuildSettings.cs new file mode 100644 index 0000000..9f05dea --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/BuildSettings.cs @@ -0,0 +1,133 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor +{ + /// + /// 构建配置相关的实用函数。 + /// + internal static class BuildSettings + { + private static readonly string s_ConfigurationPath = null; + private static readonly List s_DefaultSceneNames = new List(); + private static readonly List s_SearchScenePaths = new List(); + + static BuildSettings() + { + s_ConfigurationPath = Type.GetConfigurationPath() ?? Utility.Path.GetRegularPath(Path.Combine(Application.dataPath, "GameFramework/Configs/BuildSettings.xml")); + s_DefaultSceneNames.Clear(); + s_SearchScenePaths.Clear(); + + if (!File.Exists(s_ConfigurationPath)) + { + return; + } + + try + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load(s_ConfigurationPath); + XmlNode xmlRoot = xmlDocument.SelectSingleNode("UnityGameFramework"); + XmlNode xmlBuildSettings = xmlRoot.SelectSingleNode("BuildSettings"); + XmlNode xmlDefaultScenes = xmlBuildSettings.SelectSingleNode("DefaultScenes"); + XmlNode xmlSearchScenePaths = xmlBuildSettings.SelectSingleNode("SearchScenePaths"); + + XmlNodeList xmlNodeList = null; + XmlNode xmlNode = null; + + xmlNodeList = xmlDefaultScenes.ChildNodes; + for (int i = 0; i < xmlNodeList.Count; i++) + { + xmlNode = xmlNodeList.Item(i); + if (xmlNode.Name != "DefaultScene") + { + continue; + } + + string defaultSceneName = xmlNode.Attributes.GetNamedItem("Name").Value; + s_DefaultSceneNames.Add(defaultSceneName); + } + + xmlNodeList = xmlSearchScenePaths.ChildNodes; + for (int i = 0; i < xmlNodeList.Count; i++) + { + xmlNode = xmlNodeList.Item(i); + if (xmlNode.Name != "SearchScenePath") + { + continue; + } + + string searchScenePath = xmlNode.Attributes.GetNamedItem("Path").Value; + s_SearchScenePaths.Add(searchScenePath); + } + } + catch + { + } + } + + /// + /// 将构建场景设置为默认。 + /// + [MenuItem("Game Framework/Scenes in Build Settings/Default Scenes", false, 20)] + public static void DefaultScenes() + { + HashSet sceneNames = new HashSet(); + foreach (string sceneName in s_DefaultSceneNames) + { + sceneNames.Add(sceneName); + } + + List scenes = new List(); + foreach (string sceneName in sceneNames) + { + scenes.Add(new EditorBuildSettingsScene(sceneName, true)); + } + + EditorBuildSettings.scenes = scenes.ToArray(); + + Debug.Log("Set scenes of build settings to default scenes."); + } + + /// + /// 将构建场景设置为所有。 + /// + [MenuItem("Game Framework/Scenes in Build Settings/All Scenes", false, 21)] + public static void AllScenes() + { + HashSet sceneNames = new HashSet(); + foreach (string sceneName in s_DefaultSceneNames) + { + sceneNames.Add(sceneName); + } + + string[] sceneGuids = AssetDatabase.FindAssets("t:Scene", s_SearchScenePaths.ToArray()); + foreach (string sceneGuid in sceneGuids) + { + string sceneName = AssetDatabase.GUIDToAssetPath(sceneGuid); + sceneNames.Add(sceneName); + } + + List scenes = new List(); + foreach (string sceneName in sceneNames) + { + scenes.Add(new EditorBuildSettingsScene(sceneName, true)); + } + + EditorBuildSettings.scenes = scenes.ToArray(); + + Debug.Log("Set scenes of build settings to all scenes."); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/BuildSettings.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Misc/BuildSettings.cs.meta new file mode 100644 index 0000000..56fe5ea --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/BuildSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b487342e56dd1f649bf6f423bbddd3ea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/BuildSettingsConfigPathAttribute.cs b/Packages/com.bywaystudios.gameframework/Editor/Misc/BuildSettingsConfigPathAttribute.cs new file mode 100644 index 0000000..9da73ec --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/BuildSettingsConfigPathAttribute.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor +{ + /// + /// BuildSettings 配置路径属性。 + /// + public sealed class BuildSettingsConfigPathAttribute : ConfigPathAttribute + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/BuildSettingsConfigPathAttribute.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Misc/BuildSettingsConfigPathAttribute.cs.meta new file mode 100644 index 0000000..51c717d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/BuildSettingsConfigPathAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a40d8263d77546c4391f66bcd3865c5e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/ConfigPathAttribute.cs b/Packages/com.bywaystudios.gameframework/Editor/Misc/ConfigPathAttribute.cs new file mode 100644 index 0000000..1f2e26f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/ConfigPathAttribute.cs @@ -0,0 +1,18 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace UnityGameFramework.Editor +{ + /// + /// 配置路径属性。 + /// + public abstract class ConfigPathAttribute : Attribute + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/ConfigPathAttribute.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Misc/ConfigPathAttribute.cs.meta new file mode 100644 index 0000000..1e5d8a5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/ConfigPathAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0a44584e09310c440b42613540114652 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/Help.cs b/Packages/com.bywaystudios.gameframework/Editor/Misc/Help.cs new file mode 100644 index 0000000..89a6fbf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/Help.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor +{ + /// + /// 帮助相关的实用函数。 + /// + public static class Help + { + [MenuItem("Game Framework/Documentation", false, 90)] + public static void ShowDocumentation() + { + ShowHelp("https://gameframework.cn/document/"); + } + + [MenuItem("Game Framework/API Reference", false, 91)] + public static void ShowApiReference() + { + ShowHelp("https://gameframework.cn/api/"); + } + + private static void ShowHelp(string uri) + { + Application.OpenURL(uri); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/Help.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Misc/Help.cs.meta new file mode 100644 index 0000000..4d9ccec --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/Help.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4a04b26016cce1146887be6cbb81257a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/HelperInfo.cs b/Packages/com.bywaystudios.gameframework/Editor/Misc/HelperInfo.cs new file mode 100644 index 0000000..3200d69 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/HelperInfo.cs @@ -0,0 +1,97 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor +{ + internal sealed class HelperInfo where T : MonoBehaviour + { + private const string CustomOptionName = ""; + + private readonly string m_Name; + + private SerializedProperty m_HelperTypeName; + private SerializedProperty m_CustomHelper; + private string[] m_HelperTypeNames; + private int m_HelperTypeNameIndex; + + public HelperInfo(string name) + { + m_Name = name; + + m_HelperTypeName = null; + m_CustomHelper = null; + m_HelperTypeNames = null; + m_HelperTypeNameIndex = 0; + } + + public void Init(SerializedObject serializedObject) + { + m_HelperTypeName = serializedObject.FindProperty(Utility.Text.Format("m_{0}HelperTypeName", m_Name)); + m_CustomHelper = serializedObject.FindProperty(Utility.Text.Format("m_Custom{0}Helper", m_Name)); + } + + public void Draw() + { + string displayName = FieldNameForDisplay(m_Name); + int selectedIndex = EditorGUILayout.Popup(Utility.Text.Format("{0} Helper", displayName), m_HelperTypeNameIndex, m_HelperTypeNames); + if (selectedIndex != m_HelperTypeNameIndex) + { + m_HelperTypeNameIndex = selectedIndex; + m_HelperTypeName.stringValue = selectedIndex <= 0 ? null : m_HelperTypeNames[selectedIndex]; + } + + if (m_HelperTypeNameIndex <= 0) + { + EditorGUILayout.PropertyField(m_CustomHelper); + if (m_CustomHelper.objectReferenceValue == null) + { + EditorGUILayout.HelpBox(Utility.Text.Format("You must set Custom {0} Helper.", displayName), MessageType.Error); + } + } + } + + public void Refresh() + { + List helperTypeNameList = new List + { + CustomOptionName + }; + + helperTypeNameList.AddRange(Type.GetRuntimeTypeNames(typeof(T))); + m_HelperTypeNames = helperTypeNameList.ToArray(); + + m_HelperTypeNameIndex = 0; + if (!string.IsNullOrEmpty(m_HelperTypeName.stringValue)) + { + m_HelperTypeNameIndex = helperTypeNameList.IndexOf(m_HelperTypeName.stringValue); + if (m_HelperTypeNameIndex <= 0) + { + m_HelperTypeNameIndex = 0; + m_HelperTypeName.stringValue = null; + } + } + } + + private string FieldNameForDisplay(string fieldName) + { + if (string.IsNullOrEmpty(fieldName)) + { + return string.Empty; + } + + string str = Regex.Replace(fieldName, @"^m_", string.Empty); + str = Regex.Replace(str, @"((?<=[a-z])[A-Z]|[A-Z](?=[a-z]))", @" $1").TrimStart(); + return str; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/HelperInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Misc/HelperInfo.cs.meta new file mode 100644 index 0000000..0690695 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/HelperInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7ff85bf9d2c44a14d90f78221024499e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/LogRedirection.cs b/Packages/com.bywaystudios.gameframework/Editor/Misc/LogRedirection.cs new file mode 100644 index 0000000..5e0323f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/LogRedirection.cs @@ -0,0 +1,122 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +#if !UNITY_2019_1_OR_NEWER + +using System.IO; +using System.Reflection; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEditor.Callbacks; +using UnityEditorInternal; +using UnityEngine; + +namespace UnityGameFramework.Editor +{ + /// + /// 日志重定向相关的实用函数。 + /// + internal static class LogRedirection + { + private static readonly Regex LogRegex = new Regex(@" \(at (.+)\:(\d+)\)\r?\n"); + + [OnOpenAsset(0)] + private static bool OnOpenAsset(int instanceId, int line) + { + string selectedStackTrace = GetSelectedStackTrace(); + if (string.IsNullOrEmpty(selectedStackTrace)) + { + return false; + } + + if (!selectedStackTrace.Contains("UnityGameFramework.Runtime.DefaultLogHelper:Log")) + { + return false; + } + + Match match = LogRegex.Match(selectedStackTrace); + if (!match.Success) + { + return false; + } + + if (!match.Groups[1].Value.Contains("DefaultLogHelper.cs")) + { + return false; + } + + match = match.NextMatch(); + if (!match.Success) + { + return false; + } + + if (match.Groups[1].Value.Contains("GameFrameworkLog.cs")) + { + match = match.NextMatch(); + if (!match.Success) + { + return false; + } + } + + if (match.Groups[1].Value.Contains("Log.cs")) + { + match = match.NextMatch(); + if (!match.Success) + { + return false; + } + } + + InternalEditorUtility.OpenFileAtLineExternal(Path.Combine(Application.dataPath, match.Groups[1].Value.Substring(7)), int.Parse(match.Groups[2].Value)); + return true; + } + + private static string GetSelectedStackTrace() + { + Assembly editorWindowAssembly = typeof(EditorWindow).Assembly; + if (editorWindowAssembly == null) + { + return null; + } + + System.Type consoleWindowType = editorWindowAssembly.GetType("UnityEditor.ConsoleWindow"); + if (consoleWindowType == null) + { + return null; + } + + FieldInfo consoleWindowFieldInfo = consoleWindowType.GetField("ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic); + if (consoleWindowFieldInfo == null) + { + return null; + } + + EditorWindow consoleWindow = consoleWindowFieldInfo.GetValue(null) as EditorWindow; + if (consoleWindow == null) + { + return null; + } + + if (consoleWindow != EditorWindow.focusedWindow) + { + return null; + } + + FieldInfo activeTextFieldInfo = consoleWindowType.GetField("m_ActiveText", BindingFlags.Instance | BindingFlags.NonPublic); + if (activeTextFieldInfo == null) + { + return null; + } + + return (string)activeTextFieldInfo.GetValue(consoleWindow); + } + } +} + +#endif diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/LogRedirection.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Misc/LogRedirection.cs.meta new file mode 100644 index 0000000..4dd64f0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/LogRedirection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb8c486fbd51ec64fab3749895432f7d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/LogScriptingDefineSymbols.cs b/Packages/com.bywaystudios.gameframework/Editor/Misc/LogScriptingDefineSymbols.cs new file mode 100644 index 0000000..fd2d0fe --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/LogScriptingDefineSymbols.cs @@ -0,0 +1,179 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; + +namespace UnityGameFramework.Editor +{ + /// + /// 日志脚本宏定义。 + /// + public static class LogScriptingDefineSymbols + { + private const string EnableLogScriptingDefineSymbol = "ENABLE_LOG"; + private const string EnableDebugAndAboveLogScriptingDefineSymbol = "ENABLE_DEBUG_AND_ABOVE_LOG"; + private const string EnableInfoAndAboveLogScriptingDefineSymbol = "ENABLE_INFO_AND_ABOVE_LOG"; + private const string EnableWarningAndAboveLogScriptingDefineSymbol = "ENABLE_WARNING_AND_ABOVE_LOG"; + private const string EnableErrorAndAboveLogScriptingDefineSymbol = "ENABLE_ERROR_AND_ABOVE_LOG"; + private const string EnableFatalAndAboveLogScriptingDefineSymbol = "ENABLE_FATAL_AND_ABOVE_LOG"; + private const string EnableDebugLogScriptingDefineSymbol = "ENABLE_DEBUG_LOG"; + private const string EnableInfoLogScriptingDefineSymbol = "ENABLE_INFO_LOG"; + private const string EnableWarningLogScriptingDefineSymbol = "ENABLE_WARNING_LOG"; + private const string EnableErrorLogScriptingDefineSymbol = "ENABLE_ERROR_LOG"; + private const string EnableFatalLogScriptingDefineSymbol = "ENABLE_FATAL_LOG"; + + private static readonly string[] AboveLogScriptingDefineSymbols = new string[] + { + EnableDebugAndAboveLogScriptingDefineSymbol, + EnableInfoAndAboveLogScriptingDefineSymbol, + EnableWarningAndAboveLogScriptingDefineSymbol, + EnableErrorAndAboveLogScriptingDefineSymbol, + EnableFatalAndAboveLogScriptingDefineSymbol + }; + + private static readonly string[] SpecifyLogScriptingDefineSymbols = new string[] + { + EnableDebugLogScriptingDefineSymbol, + EnableInfoLogScriptingDefineSymbol, + EnableWarningLogScriptingDefineSymbol, + EnableErrorLogScriptingDefineSymbol, + EnableFatalLogScriptingDefineSymbol + }; + + /// + /// 禁用所有日志脚本宏定义。 + /// + [MenuItem("Game Framework/Log Scripting Define Symbols/Disable All Logs", false, 30)] + public static void DisableAllLogs() + { + ScriptingDefineSymbols.RemoveScriptingDefineSymbol(EnableLogScriptingDefineSymbol); + + foreach (string specifyLogScriptingDefineSymbol in SpecifyLogScriptingDefineSymbols) + { + ScriptingDefineSymbols.RemoveScriptingDefineSymbol(specifyLogScriptingDefineSymbol); + } + + foreach (string aboveLogScriptingDefineSymbol in AboveLogScriptingDefineSymbols) + { + ScriptingDefineSymbols.RemoveScriptingDefineSymbol(aboveLogScriptingDefineSymbol); + } + } + + /// + /// 开启所有日志脚本宏定义。 + /// + [MenuItem("Game Framework/Log Scripting Define Symbols/Enable All Logs", false, 31)] + public static void EnableAllLogs() + { + DisableAllLogs(); + ScriptingDefineSymbols.AddScriptingDefineSymbol(EnableLogScriptingDefineSymbol); + } + + /// + /// 开启调试及以上级别的日志脚本宏定义。 + /// + [MenuItem("Game Framework/Log Scripting Define Symbols/Enable Debug And Above Logs", false, 32)] + public static void EnableDebugAndAboveLogs() + { + SetAboveLogScriptingDefineSymbol(EnableDebugAndAboveLogScriptingDefineSymbol); + } + + /// + /// 开启信息及以上级别的日志脚本宏定义。 + /// + [MenuItem("Game Framework/Log Scripting Define Symbols/Enable Info And Above Logs", false, 33)] + public static void EnableInfoAndAboveLogs() + { + SetAboveLogScriptingDefineSymbol(EnableInfoAndAboveLogScriptingDefineSymbol); + } + + /// + /// 开启警告及以上级别的日志脚本宏定义。 + /// + [MenuItem("Game Framework/Log Scripting Define Symbols/Enable Warning And Above Logs", false, 34)] + public static void EnableWarningAndAboveLogs() + { + SetAboveLogScriptingDefineSymbol(EnableWarningAndAboveLogScriptingDefineSymbol); + } + + /// + /// 开启错误及以上级别的日志脚本宏定义。 + /// + [MenuItem("Game Framework/Log Scripting Define Symbols/Enable Error And Above Logs", false, 35)] + public static void EnableErrorAndAboveLogs() + { + SetAboveLogScriptingDefineSymbol(EnableErrorAndAboveLogScriptingDefineSymbol); + } + + /// + /// 开启严重错误及以上级别的日志脚本宏定义。 + /// + [MenuItem("Game Framework/Log Scripting Define Symbols/Enable Fatal And Above Logs", false, 36)] + public static void EnableFatalAndAboveLogs() + { + SetAboveLogScriptingDefineSymbol(EnableFatalAndAboveLogScriptingDefineSymbol); + } + + /// + /// 设置日志脚本宏定义。 + /// + /// 要设置的日志脚本宏定义。 + public static void SetAboveLogScriptingDefineSymbol(string aboveLogScriptingDefineSymbol) + { + if (string.IsNullOrEmpty(aboveLogScriptingDefineSymbol)) + { + return; + } + + foreach (string i in AboveLogScriptingDefineSymbols) + { + if (i == aboveLogScriptingDefineSymbol) + { + DisableAllLogs(); + ScriptingDefineSymbols.AddScriptingDefineSymbol(aboveLogScriptingDefineSymbol); + return; + } + } + } + + /// + /// 设置日志脚本宏定义。 + /// + /// 要设置的日志脚本宏定义。 + public static void SetSpecifyLogScriptingDefineSymbols(string[] specifyLogScriptingDefineSymbols) + { + if (specifyLogScriptingDefineSymbols == null || specifyLogScriptingDefineSymbols.Length <= 0) + { + return; + } + + bool removed = false; + foreach (string specifyLogScriptingDefineSymbol in specifyLogScriptingDefineSymbols) + { + if (string.IsNullOrEmpty(specifyLogScriptingDefineSymbol)) + { + continue; + } + + foreach (string i in SpecifyLogScriptingDefineSymbols) + { + if (i == specifyLogScriptingDefineSymbol) + { + if (!removed) + { + removed = true; + DisableAllLogs(); + } + + ScriptingDefineSymbols.AddScriptingDefineSymbol(specifyLogScriptingDefineSymbol); + break; + } + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/LogScriptingDefineSymbols.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Misc/LogScriptingDefineSymbols.cs.meta new file mode 100644 index 0000000..46c0c6c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/LogScriptingDefineSymbols.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0b5eed5f56efa7e4cb245bee9b064c21 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/OpenFolder.cs b/Packages/com.bywaystudios.gameframework/Editor/Misc/OpenFolder.cs new file mode 100644 index 0000000..78ce52b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/OpenFolder.cs @@ -0,0 +1,91 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System.Diagnostics; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor +{ + /// + /// 打开文件夹相关的实用函数。 + /// + public static class OpenFolder + { + /// + /// 打开 Data Path 文件夹。 + /// + [MenuItem("Game Framework/Open Folder/Data Path", false, 10)] + public static void OpenFolderDataPath() + { + Execute(Application.dataPath); + } + + /// + /// 打开 Persistent Data Path 文件夹。 + /// + [MenuItem("Game Framework/Open Folder/Persistent Data Path", false, 11)] + public static void OpenFolderPersistentDataPath() + { + Execute(Application.persistentDataPath); + } + + /// + /// 打开 Streaming Assets Path 文件夹。 + /// + [MenuItem("Game Framework/Open Folder/Streaming Assets Path", false, 12)] + public static void OpenFolderStreamingAssetsPath() + { + Execute(Application.streamingAssetsPath); + } + + /// + /// 打开 Temporary Cache Path 文件夹。 + /// + [MenuItem("Game Framework/Open Folder/Temporary Cache Path", false, 13)] + public static void OpenFolderTemporaryCachePath() + { + Execute(Application.temporaryCachePath); + } + +#if UNITY_2018_3_OR_NEWER + + /// + /// 打开 Console Log Path 文件夹。 + /// + [MenuItem("Game Framework/Open Folder/Console Log Path", false, 14)] + public static void OpenFolderConsoleLogPath() + { + Execute(System.IO.Path.GetDirectoryName(Application.consoleLogPath)); + } + +#endif + + /// + /// 打开指定路径的文件夹。 + /// + /// 要打开的文件夹的路径。 + public static void Execute(string folder) + { + folder = Utility.Text.Format("\"{0}\"", folder); + switch (Application.platform) + { + case RuntimePlatform.WindowsEditor: + Process.Start("Explorer.exe", folder.Replace('/', '\\')); + break; + + case RuntimePlatform.OSXEditor: + Process.Start("open", folder); + break; + + default: + throw new GameFrameworkException(Utility.Text.Format("Not support open folder on '{0}' platform.", Application.platform)); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/OpenFolder.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Misc/OpenFolder.cs.meta new file mode 100644 index 0000000..e948d83 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/OpenFolder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 62e84f6e8237ea540b348d07a13891c7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/ScriptingDefineSymbols.cs b/Packages/com.bywaystudios.gameframework/Editor/Misc/ScriptingDefineSymbols.cs new file mode 100644 index 0000000..5e05418 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/ScriptingDefineSymbols.cs @@ -0,0 +1,157 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; +using UnityEditor; + +namespace UnityGameFramework.Editor +{ + /// + /// 脚本宏定义。 + /// + public static class ScriptingDefineSymbols + { + private static readonly BuildTargetGroup[] BuildTargetGroups = new BuildTargetGroup[] + { + BuildTargetGroup.Standalone, + BuildTargetGroup.iOS, + BuildTargetGroup.Android, + BuildTargetGroup.WSA, + BuildTargetGroup.WebGL + }; + + /// + /// 检查指定平台是否存在指定的脚本宏定义。 + /// + /// 要检查脚本宏定义的平台。 + /// 要检查的脚本宏定义。 + /// 指定平台是否存在指定的脚本宏定义。 + public static bool HasScriptingDefineSymbol(BuildTargetGroup buildTargetGroup, string scriptingDefineSymbol) + { + if (string.IsNullOrEmpty(scriptingDefineSymbol)) + { + return false; + } + + string[] scriptingDefineSymbols = GetScriptingDefineSymbols(buildTargetGroup); + foreach (string i in scriptingDefineSymbols) + { + if (i == scriptingDefineSymbol) + { + return true; + } + } + + return false; + } + + /// + /// 为指定平台增加指定的脚本宏定义。 + /// + /// 要增加脚本宏定义的平台。 + /// 要增加的脚本宏定义。 + public static void AddScriptingDefineSymbol(BuildTargetGroup buildTargetGroup, string scriptingDefineSymbol) + { + if (string.IsNullOrEmpty(scriptingDefineSymbol)) + { + return; + } + + if (HasScriptingDefineSymbol(buildTargetGroup, scriptingDefineSymbol)) + { + return; + } + + List scriptingDefineSymbols = new List(GetScriptingDefineSymbols(buildTargetGroup)) + { + scriptingDefineSymbol + }; + + SetScriptingDefineSymbols(buildTargetGroup, scriptingDefineSymbols.ToArray()); + } + + /// + /// 为指定平台移除指定的脚本宏定义。 + /// + /// 要移除脚本宏定义的平台。 + /// 要移除的脚本宏定义。 + public static void RemoveScriptingDefineSymbol(BuildTargetGroup buildTargetGroup, string scriptingDefineSymbol) + { + if (string.IsNullOrEmpty(scriptingDefineSymbol)) + { + return; + } + + if (!HasScriptingDefineSymbol(buildTargetGroup, scriptingDefineSymbol)) + { + return; + } + + List scriptingDefineSymbols = new List(GetScriptingDefineSymbols(buildTargetGroup)); + while (scriptingDefineSymbols.Contains(scriptingDefineSymbol)) + { + scriptingDefineSymbols.Remove(scriptingDefineSymbol); + } + + SetScriptingDefineSymbols(buildTargetGroup, scriptingDefineSymbols.ToArray()); + } + + /// + /// 为所有平台增加指定的脚本宏定义。 + /// + /// 要增加的脚本宏定义。 + public static void AddScriptingDefineSymbol(string scriptingDefineSymbol) + { + if (string.IsNullOrEmpty(scriptingDefineSymbol)) + { + return; + } + + foreach (BuildTargetGroup buildTargetGroup in BuildTargetGroups) + { + AddScriptingDefineSymbol(buildTargetGroup, scriptingDefineSymbol); + } + } + + /// + /// 为所有平台移除指定的脚本宏定义。 + /// + /// 要移除的脚本宏定义。 + public static void RemoveScriptingDefineSymbol(string scriptingDefineSymbol) + { + if (string.IsNullOrEmpty(scriptingDefineSymbol)) + { + return; + } + + foreach (BuildTargetGroup buildTargetGroup in BuildTargetGroups) + { + RemoveScriptingDefineSymbol(buildTargetGroup, scriptingDefineSymbol); + } + } + + /// + /// 获取指定平台的脚本宏定义。 + /// + /// 要获取脚本宏定义的平台。 + /// 平台的脚本宏定义。 + public static string[] GetScriptingDefineSymbols(BuildTargetGroup buildTargetGroup) + { + return PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup).Split(';'); + } + + /// + /// 设置指定平台的脚本宏定义。 + /// + /// 要设置脚本宏定义的平台。 + /// 要设置的脚本宏定义。 + public static void SetScriptingDefineSymbols(BuildTargetGroup buildTargetGroup, string[] scriptingDefineSymbols) + { + PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, string.Join(";", scriptingDefineSymbols)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/ScriptingDefineSymbols.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Misc/ScriptingDefineSymbols.cs.meta new file mode 100644 index 0000000..a7eca4a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/ScriptingDefineSymbols.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 99eaa7f830bac2c469f9aab52406b8ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/Type.cs b/Packages/com.bywaystudios.gameframework/Editor/Misc/Type.cs new file mode 100644 index 0000000..1cb34d1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/Type.cs @@ -0,0 +1,127 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System.Collections.Generic; +using System.Reflection; + +namespace UnityGameFramework.Editor +{ + /// + /// 类型相关的实用函数。 + /// + internal static class Type + { + private static readonly string[] RuntimeAssemblyNames = + { +#if UNITY_2017_3_OR_NEWER + "UnityGameFramework.Runtime", +#endif + "Assembly-CSharp", + }; + + private static readonly string[] RuntimeOrEditorAssemblyNames = + { +#if UNITY_2017_3_OR_NEWER + "UnityGameFramework.Runtime", +#endif + "Assembly-CSharp", +#if UNITY_2017_3_OR_NEWER + "UnityGameFramework.Editor", +#endif + "Assembly-CSharp-Editor", + }; + + /// + /// 获取配置路径。 + /// + /// 配置类型。 + /// 配置路径。 + internal static string GetConfigurationPath() where T : ConfigPathAttribute + { + foreach (System.Type type in Utility.Assembly.GetTypes()) + { + if (!type.IsAbstract || !type.IsSealed) + { + continue; + } + + foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) + { + if (fieldInfo.FieldType == typeof(string) && fieldInfo.IsDefined(typeof(T), false)) + { + return (string)fieldInfo.GetValue(null); + } + } + + foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) + { + if (propertyInfo.PropertyType == typeof(string) && propertyInfo.IsDefined(typeof(T), false)) + { + return (string)propertyInfo.GetValue(null, null); + } + } + } + + return null; + } + + /// + /// 在运行时程序集中获取指定基类的所有子类的名称。 + /// + /// 基类类型。 + /// 指定基类的所有子类的名称。 + internal static string[] GetRuntimeTypeNames(System.Type typeBase) + { + return GetTypeNames(typeBase, RuntimeAssemblyNames); + } + + /// + /// 在运行时或编辑器程序集中获取指定基类的所有子类的名称。 + /// + /// 基类类型。 + /// 指定基类的所有子类的名称。 + internal static string[] GetRuntimeOrEditorTypeNames(System.Type typeBase) + { + return GetTypeNames(typeBase, RuntimeOrEditorAssemblyNames); + } + + private static string[] GetTypeNames(System.Type typeBase, string[] assemblyNames) + { + List typeNames = new List(); + foreach (string assemblyName in assemblyNames) + { + Assembly assembly = null; + try + { + assembly = Assembly.Load(assemblyName); + } + catch + { + continue; + } + + if (assembly == null) + { + continue; + } + + System.Type[] types = assembly.GetTypes(); + foreach (System.Type type in types) + { + if (type.IsClass && !type.IsAbstract && typeBase.IsAssignableFrom(type)) + { + typeNames.Add(type.FullName); + } + } + } + + typeNames.Sort(); + return typeNames.ToArray(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/Misc/Type.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/Misc/Type.cs.meta new file mode 100644 index 0000000..8064749 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/Misc/Type.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 82f73088e6e538649abbb7e35e3d6bf5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer.meta new file mode 100644 index 0000000..3090394 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fd9595fe20f16b6418ee574335afadca +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/AssetsOrder.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/AssetsOrder.cs new file mode 100644 index 0000000..7914d97 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/AssetsOrder.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor.ResourceTools +{ + public enum AssetsOrder : byte + { + AssetNameAsc, + AssetNameDesc, + DependencyResourceCountAsc, + DependencyResourceCountDesc, + DependencyAssetCountAsc, + DependencyAssetCountDesc, + ScatteredDependencyAssetCountAsc, + ScatteredDependencyAssetCountDesc, + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/AssetsOrder.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/AssetsOrder.cs.meta new file mode 100644 index 0000000..22c68b5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/AssetsOrder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 53e74863b20de0742bad85898d617db6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/DependencyData.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/DependencyData.cs new file mode 100644 index 0000000..a4e77a3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/DependencyData.cs @@ -0,0 +1,96 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed class DependencyData + { + private List m_DependencyResources; + private List m_DependencyAssets; + private List m_ScatteredDependencyAssetNames; + + public DependencyData() + { + m_DependencyResources = new List(); + m_DependencyAssets = new List(); + m_ScatteredDependencyAssetNames = new List(); + } + + public int DependencyResourceCount + { + get + { + return m_DependencyResources.Count; + } + } + + public int DependencyAssetCount + { + get + { + return m_DependencyAssets.Count; + } + } + + public int ScatteredDependencyAssetCount + { + get + { + return m_ScatteredDependencyAssetNames.Count; + } + } + + public void AddDependencyAsset(Asset asset) + { + if (!m_DependencyResources.Contains(asset.Resource)) + { + m_DependencyResources.Add(asset.Resource); + } + + m_DependencyAssets.Add(asset); + } + + public void AddScatteredDependencyAsset(string dependencyAssetName) + { + m_ScatteredDependencyAssetNames.Add(dependencyAssetName); + } + + public Resource[] GetDependencyResources() + { + return m_DependencyResources.ToArray(); + } + + public Asset[] GetDependencyAssets() + { + return m_DependencyAssets.ToArray(); + } + + public string[] GetScatteredDependencyAssetNames() + { + return m_ScatteredDependencyAssetNames.ToArray(); + } + + public void RefreshData() + { + m_DependencyResources.Sort(DependencyResourcesComparer); + m_DependencyAssets.Sort(DependencyAssetsComparer); + m_ScatteredDependencyAssetNames.Sort(); + } + + private int DependencyResourcesComparer(Resource a, Resource b) + { + return a.FullName.CompareTo(b.FullName); + } + + private int DependencyAssetsComparer(Asset a, Asset b) + { + return a.Name.CompareTo(b.Name); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/DependencyData.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/DependencyData.cs.meta new file mode 100644 index 0000000..6a1408c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/DependencyData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 325edc30663628f4a917226eeee0b733 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzer.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzer.cs new file mode 100644 index 0000000..7401692 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzer.cs @@ -0,0 +1,533 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// 资源分析器。 + /// + internal sealed class ResourceAnalyzer : EditorWindow + { + private ResourceAnalyzerController m_Controller = null; + private bool m_Analyzed = false; + private int m_ToolbarIndex = 0; + + private int m_AssetCount = 0; + private string[] m_CachedAssetNames = null; + private int m_SelectedAssetIndex = -1; + private string m_SelectedAssetName = null; + private DependencyData m_SelectedDependencyData = null; + private AssetsOrder m_AssetsOrder = AssetsOrder.AssetNameAsc; + private string m_AssetsFilter = null; + private Vector2 m_AssetsScroll = Vector2.zero; + private Vector2 m_DependencyResourcesScroll = Vector2.zero; + private Vector2 m_DependencyAssetsScroll = Vector2.zero; + private Vector2 m_ScatteredDependencyAssetsScroll = Vector2.zero; + + private int m_ScatteredAssetCount = 0; + private string[] m_CachedScatteredAssetNames = null; + private int m_SelectedScatteredAssetIndex = -1; + private string m_SelectedScatteredAssetName = null; + private Asset[] m_SelectedHostAssets = null; + private ScatteredAssetsOrder m_ScatteredAssetsOrder = ScatteredAssetsOrder.AssetNameAsc; + private string m_ScatteredAssetsFilter = null; + private Vector2 m_ScatteredAssetsScroll = Vector2.zero; + private Vector2 m_HostAssetsScroll = Vector2.zero; + + private int m_CircularDependencyCount = 0; + private string[][] m_CachedCircularDependencyDatas = null; + private Vector2 m_CircularDependencyScroll = Vector2.zero; + + [MenuItem("Game Framework/Resource Tools/Resource Analyzer", false, 42)] + private static void Open() + { + ResourceAnalyzer window = GetWindow("Resource Analyzer", true); + window.minSize = new Vector2(800f, 600f); + } + + private void OnEnable() + { + m_Controller = new ResourceAnalyzerController(); + m_Controller.OnLoadingResource += OnLoadingResource; + m_Controller.OnLoadingAsset += OnLoadingAsset; + m_Controller.OnLoadCompleted += OnLoadCompleted; + m_Controller.OnAnalyzingAsset += OnAnalyzingAsset; + m_Controller.OnAnalyzeCompleted += OnAnalyzeCompleted; + + m_Analyzed = false; + m_ToolbarIndex = 0; + + m_AssetCount = 0; + m_CachedAssetNames = null; + m_SelectedAssetIndex = -1; + m_SelectedAssetName = null; + m_SelectedDependencyData = new DependencyData(); + m_AssetsOrder = AssetsOrder.ScatteredDependencyAssetCountDesc; + m_AssetsFilter = null; + m_AssetsScroll = Vector2.zero; + m_DependencyResourcesScroll = Vector2.zero; + m_DependencyAssetsScroll = Vector2.zero; + m_ScatteredDependencyAssetsScroll = Vector2.zero; + + m_ScatteredAssetCount = 0; + m_CachedScatteredAssetNames = null; + m_SelectedScatteredAssetIndex = -1; + m_SelectedScatteredAssetName = null; + m_SelectedHostAssets = new Asset[] { }; + m_ScatteredAssetsOrder = ScatteredAssetsOrder.HostAssetCountDesc; + m_ScatteredAssetsFilter = null; + m_ScatteredAssetsScroll = Vector2.zero; + m_HostAssetsScroll = Vector2.zero; + + m_CircularDependencyCount = 0; + m_CachedCircularDependencyDatas = null; + m_CircularDependencyScroll = Vector2.zero; + } + + private void OnGUI() + { + EditorGUILayout.BeginVertical(GUILayout.Width(position.width), GUILayout.Height(position.height)); + { + GUILayout.Space(5f); + int toolbarIndex = GUILayout.Toolbar(m_ToolbarIndex, new string[] { "Summary", "Asset Dependency Viewer", "Scattered Asset Viewer", "Circular Dependency Viewer" }, GUILayout.Height(30f)); + if (toolbarIndex != m_ToolbarIndex) + { + m_ToolbarIndex = toolbarIndex; + GUI.FocusControl(null); + } + + switch (m_ToolbarIndex) + { + case 0: + DrawSummary(); + break; + + case 1: + DrawAssetDependencyViewer(); + break; + + case 2: + DrawScatteredAssetViewer(); + break; + + case 3: + DrawCircularDependencyViewer(); + break; + } + } + EditorGUILayout.EndVertical(); + } + + private void DrawAnalyzeButton() + { + if (!m_Analyzed) + { + EditorGUILayout.HelpBox("Please analyze first.", MessageType.Info); + } + + if (GUILayout.Button("Analyze", GUILayout.Height(30f))) + { + m_Controller.Clear(); + + m_SelectedAssetIndex = -1; + m_SelectedAssetName = null; + m_SelectedDependencyData = new DependencyData(); + + m_SelectedScatteredAssetIndex = -1; + m_SelectedScatteredAssetName = null; + m_SelectedHostAssets = new Asset[] { }; + + if (m_Controller.Prepare()) + { + m_Controller.Analyze(); + m_Analyzed = true; + m_AssetCount = m_Controller.GetAssetNames().Length; + m_ScatteredAssetCount = m_Controller.GetScatteredAssetNames().Length; + m_CachedCircularDependencyDatas = m_Controller.GetCircularDependencyDatas(); + m_CircularDependencyCount = m_CachedCircularDependencyDatas.Length; + OnAssetsOrderOrFilterChanged(); + OnScatteredAssetsOrderOrFilterChanged(); + } + else + { + EditorUtility.DisplayDialog("Resource Analyze", "Can not parse 'ResourceCollection.xml', please use 'Resource Editor' tool first.", "OK"); + } + } + } + + private void DrawSummary() + { + DrawAnalyzeButton(); + } + + private void DrawAssetDependencyViewer() + { + if (!m_Analyzed) + { + DrawAnalyzeButton(); + return; + } + + EditorGUILayout.BeginHorizontal(); + { + GUILayout.Space(5f); + EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.4f)); + { + GUILayout.Space(5f); + string title = null; + if (string.IsNullOrEmpty(m_AssetsFilter)) + { + title = Utility.Text.Format("Assets In Resources ({0})", m_AssetCount); + } + else + { + title = Utility.Text.Format("Assets In Resources ({0}/{1})", m_CachedAssetNames.Length, m_AssetCount); + } + EditorGUILayout.LabelField(title, EditorStyles.boldLabel); + EditorGUILayout.BeginVertical("box", GUILayout.Height(position.height - 150f)); + { + m_AssetsScroll = EditorGUILayout.BeginScrollView(m_AssetsScroll); + { + int selectedIndex = GUILayout.SelectionGrid(m_SelectedAssetIndex, m_CachedAssetNames, 1, "toggle"); + if (selectedIndex != m_SelectedAssetIndex) + { + m_SelectedAssetIndex = selectedIndex; + m_SelectedAssetName = m_CachedAssetNames[selectedIndex]; + m_SelectedDependencyData = m_Controller.GetDependencyData(m_SelectedAssetName); + } + } + EditorGUILayout.EndScrollView(); + } + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical("box"); + { + EditorGUILayout.LabelField("Asset Name", m_SelectedAssetName ?? ""); + EditorGUILayout.LabelField("Resource Name", m_SelectedAssetName == null ? "" : m_Controller.GetAsset(m_SelectedAssetName).Resource.FullName); + EditorGUILayout.BeginHorizontal(); + { + AssetsOrder assetsOrder = (AssetsOrder)EditorGUILayout.EnumPopup("Order by", m_AssetsOrder); + if (assetsOrder != m_AssetsOrder) + { + m_AssetsOrder = assetsOrder; + OnAssetsOrderOrFilterChanged(); + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + string assetsFilter = EditorGUILayout.TextField("Assets Filter", m_AssetsFilter); + if (assetsFilter != m_AssetsFilter) + { + m_AssetsFilter = assetsFilter; + OnAssetsOrderOrFilterChanged(); + } + EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(m_AssetsFilter)); + { + if (GUILayout.Button("x", GUILayout.Width(20f))) + { + m_AssetsFilter = null; + GUI.FocusControl(null); + OnAssetsOrderOrFilterChanged(); + } + } + EditorGUI.EndDisabledGroup(); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.6f - 14f)); + { + GUILayout.Space(5f); + EditorGUILayout.LabelField(Utility.Text.Format("Dependency Resources ({0})", m_SelectedDependencyData.DependencyResourceCount), EditorStyles.boldLabel); + EditorGUILayout.BeginVertical("box", GUILayout.Height(position.height * 0.2f)); + { + m_DependencyResourcesScroll = EditorGUILayout.BeginScrollView(m_DependencyResourcesScroll); + { + Resource[] dependencyResources = m_SelectedDependencyData.GetDependencyResources(); + foreach (Resource dependencyResource in dependencyResources) + { + GUILayout.Label(dependencyResource.FullName); + } + } + EditorGUILayout.EndScrollView(); + } + EditorGUILayout.EndVertical(); + EditorGUILayout.LabelField(Utility.Text.Format("Dependency Assets ({0})", m_SelectedDependencyData.DependencyAssetCount), EditorStyles.boldLabel); + EditorGUILayout.BeginVertical("box", GUILayout.Height(position.height * 0.3f)); + { + m_DependencyAssetsScroll = EditorGUILayout.BeginScrollView(m_DependencyAssetsScroll); + { + Asset[] dependencyAssets = m_SelectedDependencyData.GetDependencyAssets(); + foreach (Asset dependencyAsset in dependencyAssets) + { + EditorGUILayout.BeginHorizontal(); + { + if (GUILayout.Button("GO", GUILayout.Width(30f))) + { + m_SelectedAssetName = dependencyAsset.Name; + m_SelectedAssetIndex = new List(m_CachedAssetNames).IndexOf(m_SelectedAssetName); + m_SelectedDependencyData = m_Controller.GetDependencyData(m_SelectedAssetName); + } + + GUILayout.Label(dependencyAsset.Name); + } + EditorGUILayout.EndHorizontal(); + } + } + EditorGUILayout.EndScrollView(); + } + EditorGUILayout.EndVertical(); + EditorGUILayout.LabelField(Utility.Text.Format("Scattered Dependency Assets ({0})", m_SelectedDependencyData.ScatteredDependencyAssetCount), EditorStyles.boldLabel); + EditorGUILayout.BeginVertical("box", GUILayout.Height(position.height * 0.5f - 116f)); + { + m_ScatteredDependencyAssetsScroll = EditorGUILayout.BeginScrollView(m_ScatteredDependencyAssetsScroll); + { + string[] scatteredDependencyAssetNames = m_SelectedDependencyData.GetScatteredDependencyAssetNames(); + foreach (string scatteredDependencyAssetName in scatteredDependencyAssetNames) + { + EditorGUILayout.BeginHorizontal(); + { + int count = m_Controller.GetHostAssets(scatteredDependencyAssetName).Length; + EditorGUI.BeginDisabledGroup(count < 2); + { + if (GUILayout.Button("GO", GUILayout.Width(30f))) + { + m_SelectedScatteredAssetName = scatteredDependencyAssetName; + m_SelectedScatteredAssetIndex = new List(m_CachedScatteredAssetNames).IndexOf(m_SelectedScatteredAssetName); + m_SelectedHostAssets = m_Controller.GetHostAssets(m_SelectedScatteredAssetName); + m_ToolbarIndex = 2; + GUI.FocusControl(null); + } + } + EditorGUI.EndDisabledGroup(); + GUILayout.Label(count > 1 ? Utility.Text.Format("{0} ({1})", scatteredDependencyAssetName, count) : scatteredDependencyAssetName); + } + EditorGUILayout.EndHorizontal(); + } + } + EditorGUILayout.EndScrollView(); + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndHorizontal(); + } + + private void DrawScatteredAssetViewer() + { + if (!m_Analyzed) + { + DrawAnalyzeButton(); + return; + } + + EditorGUILayout.BeginHorizontal(); + { + GUILayout.Space(5f); + EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.4f)); + { + GUILayout.Space(5f); + string title = null; + if (string.IsNullOrEmpty(m_ScatteredAssetsFilter)) + { + title = Utility.Text.Format("Scattered Assets ({0})", m_ScatteredAssetCount); + } + else + { + title = Utility.Text.Format("Scattered Assets ({0}/{1})", m_CachedScatteredAssetNames.Length, m_ScatteredAssetCount); + } + EditorGUILayout.LabelField(title, EditorStyles.boldLabel); + EditorGUILayout.BeginVertical("box", GUILayout.Height(position.height - 132f)); + { + m_ScatteredAssetsScroll = EditorGUILayout.BeginScrollView(m_ScatteredAssetsScroll); + { + int selectedIndex = GUILayout.SelectionGrid(m_SelectedScatteredAssetIndex, m_CachedScatteredAssetNames, 1, "toggle"); + if (selectedIndex != m_SelectedScatteredAssetIndex) + { + m_SelectedScatteredAssetIndex = selectedIndex; + m_SelectedScatteredAssetName = m_CachedScatteredAssetNames[selectedIndex]; + m_SelectedHostAssets = m_Controller.GetHostAssets(m_SelectedScatteredAssetName); + } + } + EditorGUILayout.EndScrollView(); + } + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical("box"); + { + EditorGUILayout.LabelField("Scattered Asset Name", m_SelectedScatteredAssetName ?? ""); + EditorGUILayout.BeginHorizontal(); + { + ScatteredAssetsOrder scatteredAssetsOrder = (ScatteredAssetsOrder)EditorGUILayout.EnumPopup("Order by", m_ScatteredAssetsOrder); + if (scatteredAssetsOrder != m_ScatteredAssetsOrder) + { + m_ScatteredAssetsOrder = scatteredAssetsOrder; + OnScatteredAssetsOrderOrFilterChanged(); + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + string scatteredAssetsFilter = EditorGUILayout.TextField("Assets Filter", m_ScatteredAssetsFilter); + if (scatteredAssetsFilter != m_ScatteredAssetsFilter) + { + m_ScatteredAssetsFilter = scatteredAssetsFilter; + OnScatteredAssetsOrderOrFilterChanged(); + } + EditorGUI.BeginDisabledGroup(string.IsNullOrEmpty(m_ScatteredAssetsFilter)); + { + if (GUILayout.Button("x", GUILayout.Width(20f))) + { + m_ScatteredAssetsFilter = null; + GUI.FocusControl(null); + OnScatteredAssetsOrderOrFilterChanged(); + } + } + EditorGUI.EndDisabledGroup(); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.6f - 14f)); + { + GUILayout.Space(5f); + EditorGUILayout.LabelField(Utility.Text.Format("Host Assets ({0})", m_SelectedHostAssets.Length), EditorStyles.boldLabel); + EditorGUILayout.BeginVertical("box", GUILayout.Height(position.height - 68f)); + { + m_HostAssetsScroll = EditorGUILayout.BeginScrollView(m_HostAssetsScroll); + { + foreach (Asset hostAsset in m_SelectedHostAssets) + { + EditorGUILayout.BeginHorizontal(); + { + if (GUILayout.Button("GO", GUILayout.Width(30f))) + { + m_SelectedAssetName = hostAsset.Name; + m_SelectedAssetIndex = new List(m_CachedAssetNames).IndexOf(m_SelectedAssetName); + m_SelectedDependencyData = m_Controller.GetDependencyData(m_SelectedAssetName); + m_ToolbarIndex = 1; + GUI.FocusControl(null); + } + + GUILayout.Label(Utility.Text.Format("{0} [{1}]", hostAsset.Name, hostAsset.Resource.FullName)); + } + EditorGUILayout.EndHorizontal(); + } + } + EditorGUILayout.EndScrollView(); + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndHorizontal(); + } + + private void DrawCircularDependencyViewer() + { + if (!m_Analyzed) + { + DrawAnalyzeButton(); + return; + } + + EditorGUILayout.BeginHorizontal(); + { + GUILayout.Space(5f); + EditorGUILayout.BeginVertical(); + { + GUILayout.Space(5f); + EditorGUILayout.LabelField(Utility.Text.Format("Circular Dependency ({0})", m_CircularDependencyCount), EditorStyles.boldLabel); + m_CircularDependencyScroll = EditorGUILayout.BeginScrollView(m_CircularDependencyScroll); + { + int count = 0; + foreach (string[] circularDependencyData in m_CachedCircularDependencyDatas) + { + GUILayout.Label(Utility.Text.Format("{0}) {1}", ++count, circularDependencyData[circularDependencyData.Length - 1]), EditorStyles.boldLabel); + EditorGUILayout.BeginVertical("box"); + { + foreach (string circularDependency in circularDependencyData) + { + EditorGUILayout.BeginHorizontal(); + { + GUILayout.Label(circularDependency); + if (GUILayout.Button("GO", GUILayout.Width(30f))) + { + m_SelectedAssetName = circularDependency; + m_SelectedAssetIndex = new List(m_CachedAssetNames).IndexOf(m_SelectedAssetName); + m_SelectedDependencyData = m_Controller.GetDependencyData(m_SelectedAssetName); + m_ToolbarIndex = 1; + GUI.FocusControl(null); + } + } + EditorGUILayout.EndHorizontal(); + } + } + EditorGUILayout.EndVertical(); + GUILayout.Space(5f); + } + } + EditorGUILayout.EndScrollView(); + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndHorizontal(); + } + + private void OnAssetsOrderOrFilterChanged() + { + m_CachedAssetNames = m_Controller.GetAssetNames(m_AssetsOrder, m_AssetsFilter); + if (!string.IsNullOrEmpty(m_SelectedAssetName)) + { + m_SelectedAssetIndex = new List(m_CachedAssetNames).IndexOf(m_SelectedAssetName); + } + } + + private void OnScatteredAssetsOrderOrFilterChanged() + { + m_CachedScatteredAssetNames = m_Controller.GetScatteredAssetNames(m_ScatteredAssetsOrder, m_ScatteredAssetsFilter); + if (!string.IsNullOrEmpty(m_SelectedScatteredAssetName)) + { + m_SelectedScatteredAssetIndex = new List(m_CachedScatteredAssetNames).IndexOf(m_SelectedScatteredAssetName); + } + } + + private void OnLoadingResource(int index, int count) + { + EditorUtility.DisplayProgressBar("Loading Resources", Utility.Text.Format("Loading resources, {0}/{1} loaded.", index, count), (float)index / count); + } + + private void OnLoadingAsset(int index, int count) + { + EditorUtility.DisplayProgressBar("Loading Assets", Utility.Text.Format("Loading assets, {0}/{1} loaded.", index, count), (float)index / count); + } + + private void OnLoadCompleted() + { + EditorUtility.ClearProgressBar(); + } + + private void OnAnalyzingAsset(int index, int count) + { + EditorUtility.DisplayProgressBar("Analyzing Assets", Utility.Text.Format("Analyzing assets, {0}/{1} analyzed.", index, count), (float)index / count); + } + + private void OnAnalyzeCompleted() + { + EditorUtility.ClearProgressBar(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzer.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzer.cs.meta new file mode 100644 index 0000000..0d35147 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2e7971f49bcdc654fb34a9fdaa2a6d29 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.CircularDependencyChecker.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.CircularDependencyChecker.cs new file mode 100644 index 0000000..4732179 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.CircularDependencyChecker.cs @@ -0,0 +1,76 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; +using System.Linq; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed partial class ResourceAnalyzerController + { + private sealed class CircularDependencyChecker + { + private readonly Stamp[] m_Stamps; + + public CircularDependencyChecker(Stamp[] stamps) + { + m_Stamps = stamps; + } + + public string[][] Check() + { + HashSet hosts = new HashSet(); + foreach (Stamp stamp in m_Stamps) + { + hosts.Add(stamp.HostAssetName); + } + + List results = new List(); + foreach (string host in hosts) + { + LinkedList route = new LinkedList(); + HashSet visited = new HashSet(); + if (Check(host, route, visited)) + { + results.Add(route.ToArray()); + } + } + + return results.ToArray(); + } + + private bool Check(string host, LinkedList route, HashSet visited) + { + visited.Add(host); + route.AddLast(host); + + foreach (Stamp stamp in m_Stamps) + { + if (host != stamp.HostAssetName) + { + continue; + } + + if (visited.Contains(stamp.DependencyAssetName)) + { + route.AddLast(stamp.DependencyAssetName); + return true; + } + + if (Check(stamp.DependencyAssetName, route, visited)) + { + return true; + } + } + + route.RemoveLast(); + visited.Remove(host); + return false; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.CircularDependencyChecker.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.CircularDependencyChecker.cs.meta new file mode 100644 index 0000000..561557b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.CircularDependencyChecker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 97329d75bce6b634282bf05ff3453fba +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.Stamp.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.Stamp.cs new file mode 100644 index 0000000..c964cbd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.Stamp.cs @@ -0,0 +1,43 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed partial class ResourceAnalyzerController + { + [StructLayout(LayoutKind.Auto)] + private struct Stamp + { + private readonly string m_HostAssetName; + private readonly string m_DependencyAssetName; + + public Stamp(string hostAssetName, string dependencyAssetName) + { + m_HostAssetName = hostAssetName; + m_DependencyAssetName = dependencyAssetName; + } + + public string HostAssetName + { + get + { + return m_HostAssetName; + } + } + + public string DependencyAssetName + { + get + { + return m_DependencyAssetName; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.Stamp.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.Stamp.cs.meta new file mode 100644 index 0000000..ad6ddac --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.Stamp.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15cf99f0cd968de4e876c49401fa5294 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.cs new file mode 100644 index 0000000..60f512f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.cs @@ -0,0 +1,324 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed partial class ResourceAnalyzerController + { + private readonly ResourceCollection m_ResourceCollection; + + private readonly Dictionary m_DependencyDatas; + private readonly Dictionary> m_ScatteredAssets; + private readonly List m_CircularDependencyDatas; + private readonly HashSet m_AnalyzedStamps; + + public ResourceAnalyzerController() + : this(null) + { + } + + public ResourceAnalyzerController(ResourceCollection resourceCollection) + { + m_ResourceCollection = resourceCollection != null ? resourceCollection : new ResourceCollection(); + + m_ResourceCollection.OnLoadingResource += delegate (int index, int count) + { + if (OnLoadingResource != null) + { + OnLoadingResource(index, count); + } + }; + + m_ResourceCollection.OnLoadingAsset += delegate (int index, int count) + { + if (OnLoadingAsset != null) + { + OnLoadingAsset(index, count); + } + }; + + m_ResourceCollection.OnLoadCompleted += delegate () + { + if (OnLoadCompleted != null) + { + OnLoadCompleted(); + } + }; + + m_DependencyDatas = new Dictionary(StringComparer.Ordinal); + m_ScatteredAssets = new Dictionary>(StringComparer.Ordinal); + m_AnalyzedStamps = new HashSet(); + m_CircularDependencyDatas = new List(); + } + + public event GameFrameworkAction OnLoadingResource = null; + + public event GameFrameworkAction OnLoadingAsset = null; + + public event GameFrameworkAction OnLoadCompleted = null; + + public event GameFrameworkAction OnAnalyzingAsset = null; + + public event GameFrameworkAction OnAnalyzeCompleted = null; + + public void Clear() + { + m_ResourceCollection.Clear(); + m_DependencyDatas.Clear(); + m_ScatteredAssets.Clear(); + m_CircularDependencyDatas.Clear(); + m_AnalyzedStamps.Clear(); + } + + public bool Prepare() + { + m_ResourceCollection.Clear(); + return m_ResourceCollection.Load(); + } + + public void Analyze() + { + m_DependencyDatas.Clear(); + m_ScatteredAssets.Clear(); + m_CircularDependencyDatas.Clear(); + m_AnalyzedStamps.Clear(); + + HashSet scriptAssetNames = GetFilteredAssetNames("t:Script"); + Asset[] assets = m_ResourceCollection.GetAssets(); + int count = assets.Length; + for (int i = 0; i < count; i++) + { + if (OnAnalyzingAsset != null) + { + OnAnalyzingAsset(i, count); + } + + string assetName = assets[i].Name; + if (string.IsNullOrEmpty(assetName)) + { + Debug.LogWarning(Utility.Text.Format("Can not find asset by guid '{0}'.", assets[i].Guid)); + continue; + } + + DependencyData dependencyData = new DependencyData(); + AnalyzeAsset(assetName, assets[i], dependencyData, scriptAssetNames); + dependencyData.RefreshData(); + m_DependencyDatas.Add(assetName, dependencyData); + } + + foreach (List scatteredAsset in m_ScatteredAssets.Values) + { + scatteredAsset.Sort((a, b) => a.Name.CompareTo(b.Name)); + } + + m_CircularDependencyDatas.AddRange(new CircularDependencyChecker(m_AnalyzedStamps.ToArray()).Check()); + + if (OnAnalyzeCompleted != null) + { + OnAnalyzeCompleted(); + } + } + + private void AnalyzeAsset(string assetName, Asset hostAsset, DependencyData dependencyData, HashSet scriptAssetNames) + { + string[] dependencyAssetNames = AssetDatabase.GetDependencies(assetName, false); + foreach (string dependencyAssetName in dependencyAssetNames) + { + if (scriptAssetNames.Contains(dependencyAssetName)) + { + continue; + } + + if (dependencyAssetName == assetName) + { + continue; + } + + if (dependencyAssetName.EndsWith(".unity", StringComparison.Ordinal)) + { + // 忽略对场景的依赖 + continue; + } + + Stamp stamp = new Stamp(hostAsset.Name, dependencyAssetName); + if (m_AnalyzedStamps.Contains(stamp)) + { + continue; + } + + m_AnalyzedStamps.Add(stamp); + + string guid = AssetDatabase.AssetPathToGUID(dependencyAssetName); + if (string.IsNullOrEmpty(guid)) + { + Debug.LogWarning(Utility.Text.Format("Can not find guid by asset '{0}'.", dependencyAssetName)); + continue; + } + + Asset asset = m_ResourceCollection.GetAsset(guid); + if (asset != null) + { + dependencyData.AddDependencyAsset(asset); + } + else + { + dependencyData.AddScatteredDependencyAsset(dependencyAssetName); + + List scatteredAssets = null; + if (!m_ScatteredAssets.TryGetValue(dependencyAssetName, out scatteredAssets)) + { + scatteredAssets = new List(); + m_ScatteredAssets.Add(dependencyAssetName, scatteredAssets); + } + + scatteredAssets.Add(hostAsset); + + AnalyzeAsset(dependencyAssetName, hostAsset, dependencyData, scriptAssetNames); + } + } + } + + public Asset GetAsset(string assetName) + { + return m_ResourceCollection.GetAsset(AssetDatabase.AssetPathToGUID(assetName)); + } + + public string[] GetAssetNames() + { + return GetAssetNames(AssetsOrder.AssetNameAsc, null); + } + + public string[] GetAssetNames(AssetsOrder order, string filter) + { + HashSet filteredAssetNames = GetFilteredAssetNames(filter); + IEnumerable> filteredResult = m_DependencyDatas.Where(pair => filteredAssetNames.Contains(pair.Key)); + IEnumerable> orderedResult = null; + switch (order) + { + case AssetsOrder.AssetNameAsc: + orderedResult = filteredResult.OrderBy(pair => pair.Key); + break; + + case AssetsOrder.AssetNameDesc: + orderedResult = filteredResult.OrderByDescending(pair => pair.Key); + break; + + case AssetsOrder.DependencyResourceCountAsc: + orderedResult = filteredResult.OrderBy(pair => pair.Value.DependencyResourceCount); + break; + + case AssetsOrder.DependencyResourceCountDesc: + orderedResult = filteredResult.OrderByDescending(pair => pair.Value.DependencyResourceCount); + break; + + case AssetsOrder.DependencyAssetCountAsc: + orderedResult = filteredResult.OrderBy(pair => pair.Value.DependencyAssetCount); + break; + + case AssetsOrder.DependencyAssetCountDesc: + orderedResult = filteredResult.OrderByDescending(pair => pair.Value.DependencyAssetCount); + break; + + case AssetsOrder.ScatteredDependencyAssetCountAsc: + orderedResult = filteredResult.OrderBy(pair => pair.Value.ScatteredDependencyAssetCount); + break; + + case AssetsOrder.ScatteredDependencyAssetCountDesc: + orderedResult = filteredResult.OrderByDescending(pair => pair.Value.ScatteredDependencyAssetCount); + break; + + default: + orderedResult = filteredResult; + break; + } + + return orderedResult.Select(pair => pair.Key).ToArray(); + } + + public DependencyData GetDependencyData(string assetName) + { + DependencyData dependencyData = null; + if (m_DependencyDatas.TryGetValue(assetName, out dependencyData)) + { + return dependencyData; + } + + return dependencyData; + } + + public string[] GetScatteredAssetNames() + { + return GetScatteredAssetNames(ScatteredAssetsOrder.HostAssetCountDesc, null); + } + + public string[] GetScatteredAssetNames(ScatteredAssetsOrder order, string filter) + { + HashSet filterAssetNames = GetFilteredAssetNames(filter); + IEnumerable>> filteredResult = m_ScatteredAssets.Where(pair => filterAssetNames.Contains(pair.Key) && pair.Value.Count > 1); + IEnumerable>> orderedResult = null; + switch (order) + { + case ScatteredAssetsOrder.AssetNameAsc: + orderedResult = filteredResult.OrderBy(pair => pair.Key); + break; + + case ScatteredAssetsOrder.AssetNameDesc: + orderedResult = filteredResult.OrderByDescending(pair => pair.Key); + break; + + case ScatteredAssetsOrder.HostAssetCountAsc: + orderedResult = filteredResult.OrderBy(pair => pair.Value.Count); + break; + + case ScatteredAssetsOrder.HostAssetCountDesc: + orderedResult = filteredResult.OrderByDescending(pair => pair.Value.Count); + break; + + default: + orderedResult = filteredResult; + break; + } + + return orderedResult.Select(pair => pair.Key).ToArray(); + } + + public Asset[] GetHostAssets(string scatteredAssetName) + { + List assets = null; + if (m_ScatteredAssets.TryGetValue(scatteredAssetName, out assets)) + { + return assets.ToArray(); + } + + return null; + } + + public string[][] GetCircularDependencyDatas() + { + return m_CircularDependencyDatas.ToArray(); + } + + private HashSet GetFilteredAssetNames(string filter) + { + string[] filterAssetGuids = AssetDatabase.FindAssets(filter); + HashSet filterAssetNames = new HashSet(); + foreach (string filterAssetGuid in filterAssetGuids) + { + filterAssetNames.Add(AssetDatabase.GUIDToAssetPath(filterAssetGuid)); + } + + return filterAssetNames; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.cs.meta new file mode 100644 index 0000000..e3411d0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ResourceAnalyzerController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f05a10a252bec6c44b19b0cf7c105ff3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ScatteredAssetsOrder.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ScatteredAssetsOrder.cs new file mode 100644 index 0000000..7e89eac --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ScatteredAssetsOrder.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor.ResourceTools +{ + public enum ScatteredAssetsOrder : byte + { + AssetNameAsc, + AssetNameDesc, + HostAssetCountAsc, + HostAssetCountDesc, + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ScatteredAssetsOrder.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ScatteredAssetsOrder.cs.meta new file mode 100644 index 0000000..e5c159a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceAnalyzer/ScatteredAssetsOrder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2d9068195c1bd334d8dfb4211ad27f7b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder.meta new file mode 100644 index 0000000..cab48f7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2dd745915ad459e4c9d5aef04e1dfeea +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/AssetBundleCompressionType.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/AssetBundleCompressionType.cs new file mode 100644 index 0000000..90acffb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/AssetBundleCompressionType.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// 对 AssetBundle 应用的压缩算法类型。 + /// + public enum AssetBundleCompressionType : byte + { + /// + /// 不使用压缩算法。 + /// + Uncompressed = 0, + + /// + /// 使用 LZ4 压缩算法。 + /// + LZ4, + + /// + /// 使用 LZMA 压缩算法。 + /// + LZMA + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/AssetBundleCompressionType.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/AssetBundleCompressionType.cs.meta new file mode 100644 index 0000000..0baf1ad --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/AssetBundleCompressionType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 690743de30449bf46aa333e5117930d1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/IBuildEventHandler.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/IBuildEventHandler.cs new file mode 100644 index 0000000..4a37246 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/IBuildEventHandler.cs @@ -0,0 +1,138 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// 生成资源事件处理函数。 + /// + public interface IBuildEventHandler + { + /// + /// 获取当某个平台生成失败时,是否继续生成下一个平台。 + /// + bool ContinueOnFailure + { + get; + } + + /// + /// 所有平台生成开始前的预处理事件。 + /// + /// 产品名称。 + /// 公司名称。 + /// 游戏识别号。 + /// 游戏框架版本。 + /// Unity 版本。 + /// 适用游戏版本。 + /// 内部资源版本。 + /// 生成的目标平台。 + /// AssetBundle 压缩类型。 + /// 压缩解压缩辅助器类型名称。 + /// 是否进行再压缩以降低传输开销。 + /// 是否强制重新构建 AssetBundle。 + /// 生成资源事件处理函数名称。 + /// 生成目录。 + /// AssetBundle 生成选项。 + /// 生成时的工作路径。 + /// 是否生成单机模式所需的文件。 + /// 为单机模式生成的文件存放于此路径。若游戏是单机游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。 + /// 是否生成可更新模式所需的远程文件。 + /// 为可更新模式生成的远程文件存放于此路径。若游戏是网络游戏,生成结束后应将此目录上传至 Web 服务器,供玩家下载用。 + /// 是否生成可更新模式所需的本地文件。 + /// 为可更新模式生成的本地文件存放于此路径。若游戏是网络游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。 + /// 生成报告路径。 + void OnPreprocessAllPlatforms(string productName, string companyName, string gameIdentifier, string gameFrameworkVersion, string unityVersion, string applicableGameVersion, int internalResourceVersion, + Platform platforms, AssetBundleCompressionType assetBundleCompression, string compressionHelperTypeName, bool additionalCompressionSelected, bool forceRebuildAssetBundleSelected, string buildEventHandlerTypeName, string outputDirectory, BuildAssetBundleOptions buildAssetBundleOptions, + string workingPath, bool outputPackageSelected, string outputPackagePath, bool outputFullSelected, string outputFullPath, bool outputPackedSelected, string outputPackedPath, string buildReportPath); + + /// + /// 某个平台生成开始前的预处理事件。 + /// + /// 生成平台。 + /// 生成时的工作路径。 + /// 是否生成单机模式所需的文件。 + /// 为单机模式生成的文件存放于此路径。若游戏是单机游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。 + /// 是否生成可更新模式所需的远程文件。 + /// 为可更新模式生成的远程文件存放于此路径。若游戏是网络游戏,生成结束后应将此目录上传至 Web 服务器,供玩家下载用。 + /// 是否生成可更新模式所需的本地文件。 + /// 为可更新模式生成的本地文件存放于此路径。若游戏是网络游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。 + void OnPreprocessPlatform(Platform platform, string workingPath, bool outputPackageSelected, string outputPackagePath, bool outputFullSelected, string outputFullPath, bool outputPackedSelected, string outputPackedPath); + + /// + /// 某个平台生成 AssetBundle 完成事件。 + /// + /// 生成平台。 + /// 生成时的工作路径。 + /// 是否生成单机模式所需的文件。 + /// 为单机模式生成的文件存放于此路径。若游戏是单机游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。 + /// 是否生成可更新模式所需的远程文件。 + /// 为可更新模式生成的远程文件存放于此路径。若游戏是网络游戏,生成结束后应将此目录上传至 Web 服务器,供玩家下载用。 + /// 是否生成可更新模式所需的本地文件。 + /// 为可更新模式生成的本地文件存放于此路径。若游戏是网络游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。 + /// AssetBundle 的描述文件。 + void OnBuildAssetBundlesComplete(Platform platform, string workingPath, bool outputPackageSelected, string outputPackagePath, bool outputFullSelected, string outputFullPath, bool outputPackedSelected, string outputPackedPath, AssetBundleManifest assetBundleManifest); + + /// + /// 某个平台可更新模式版本列表文件的输出事件。 + /// + /// 生成平台。 + /// 可更新模式版本列表文件的路径。 + /// 可更新模式版本列表文件的长度。 + /// 可更新模式版本列表文件的校验值。 + /// 可更新模式版本列表文件压缩后的长度。 + /// 可更新模式版本列表文件压缩后的校验值。 + void OnOutputUpdatableVersionListData(Platform platform, string versionListPath, int versionListLength, int versionListHashCode, int versionListCompressedLength, int versionListCompressedHashCode); + + /// + /// 某个平台生成结束后的后处理事件。 + /// + /// 生成平台。 + /// 生成时的工作路径。 + /// 是否生成单机模式所需的文件。 + /// 为单机模式生成的文件存放于此路径。若游戏是单机游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。 + /// 是否生成可更新模式所需的远程文件。 + /// 为可更新模式生成的远程文件存放于此路径。若游戏是网络游戏,生成结束后应将此目录上传至 Web 服务器,供玩家下载用。 + /// 是否生成可更新模式所需的本地文件。 + /// 为可更新模式生成的本地文件存放于此路径。若游戏是网络游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。 + /// 是否生成成功。 + void OnPostprocessPlatform(Platform platform, string workingPath, bool outputPackageSelected, string outputPackagePath, bool outputFullSelected, string outputFullPath, bool outputPackedSelected, string outputPackedPath, bool isSuccess); + + /// + /// 所有平台生成结束后的后处理事件。 + /// + /// 产品名称。 + /// 公司名称。 + /// 游戏识别号。 + /// 游戏框架版本。 + /// Unity 版本。 + /// 适用游戏版本。 + /// 内部资源版本。 + /// 生成的目标平台。 + /// AssetBundle 压缩类型。 + /// 压缩解压缩辅助器类型名称。 + /// 是否进行再压缩以降低传输开销。 + /// 是否强制重新构建 AssetBundle。 + /// 生成资源事件处理函数名称。 + /// 生成目录。 + /// AssetBundle 生成选项。 + /// 生成时的工作路径。 + /// 是否生成单机模式所需的文件。 + /// 为单机模式生成的文件存放于此路径。若游戏是单机游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。 + /// 是否生成可更新模式所需的远程文件。 + /// 为可更新模式生成的远程文件存放于此路径。若游戏是网络游戏,生成结束后应将此目录上传至 Web 服务器,供玩家下载用。 + /// 是否生成可更新模式所需的本地文件。 + /// 为可更新模式生成的本地文件存放于此路径。若游戏是网络游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。 + /// 生成报告路径。 + void OnPostprocessAllPlatforms(string productName, string companyName, string gameIdentifier, string gameFrameworkVersion, string unityVersion, string applicableGameVersion, int internalResourceVersion, + Platform platforms, AssetBundleCompressionType assetBundleCompression, string compressionHelperTypeName, bool additionalCompressionSelected, bool forceRebuildAssetBundleSelected, string buildEventHandlerTypeName, string outputDirectory, BuildAssetBundleOptions buildAssetBundleOptions, + string workingPath, bool outputPackageSelected, string outputPackagePath, bool outputFullSelected, string outputFullPath, bool outputPackedSelected, string outputPackedPath, string buildReportPath); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/IBuildEventHandler.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/IBuildEventHandler.cs.meta new file mode 100644 index 0000000..80d99e1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/IBuildEventHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a24c2d69ef707e94c8ec819667089bce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/Platform.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/Platform.cs new file mode 100644 index 0000000..35e7355 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/Platform.cs @@ -0,0 +1,57 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace UnityGameFramework.Editor.ResourceTools +{ + [Flags] + public enum Platform : int + { + Undefined = 0, + + /// + /// Windows 32 位。 + /// + Windows = 1 << 0, + + /// + /// Windows 64 位。 + /// + Windows64 = 1 << 1, + + /// + /// macOS。 + /// + MacOS = 1 << 2, + + /// + /// Linux。 + /// + Linux = 1 << 3, + + /// + /// iOS。 + /// + IOS = 1 << 4, + + /// + /// Android。 + /// + Android = 1 << 5, + + /// + /// Windows Store。 + /// + WindowsStore = 1 << 6, + + /// + /// WebGL。 + /// + WebGL = 1 << 7, + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/Platform.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/Platform.cs.meta new file mode 100644 index 0000000..fb32acc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/Platform.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 443d82794c390e043b1565cea8da60cd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilder.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilder.cs new file mode 100644 index 0000000..a0c3cd6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilder.cs @@ -0,0 +1,513 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.IO; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// 资源生成器。 + /// + internal sealed class ResourceBuilder : EditorWindow + { + private ResourceBuilderController m_Controller = null; + private bool m_OrderBuildResources = false; + private int m_CompressionHelperTypeNameIndex = 0; + private int m_BuildEventHandlerTypeNameIndex = 0; + + [MenuItem("Game Framework/Resource Tools/Resource Builder", false, 40)] + private static void Open() + { + ResourceBuilder window = GetWindow("Resource Builder", true); +#if UNITY_2019_3_OR_NEWER + window.minSize = new Vector2(800f, 640f); +#else + window.minSize = new Vector2(800f, 600f); +#endif + } + + private void OnEnable() + { + m_Controller = new ResourceBuilderController(); + m_Controller.OnLoadingResource += OnLoadingResource; + m_Controller.OnLoadingAsset += OnLoadingAsset; + m_Controller.OnLoadCompleted += OnLoadCompleted; + m_Controller.OnAnalyzingAsset += OnAnalyzingAsset; + m_Controller.OnAnalyzeCompleted += OnAnalyzeCompleted; + m_Controller.ProcessingAssetBundle += OnProcessingAssetBundle; + m_Controller.ProcessingBinary += OnProcessingBinary; + m_Controller.ProcessResourceComplete += OnProcessResourceComplete; + m_Controller.BuildResourceError += OnBuildResourceError; + + m_OrderBuildResources = false; + + if (m_Controller.Load()) + { + Debug.Log("Load configuration success."); + + m_CompressionHelperTypeNameIndex = 0; + string[] compressionHelperTypeNames = m_Controller.GetCompressionHelperTypeNames(); + for (int i = 0; i < compressionHelperTypeNames.Length; i++) + { + if (m_Controller.CompressionHelperTypeName == compressionHelperTypeNames[i]) + { + m_CompressionHelperTypeNameIndex = i; + break; + } + } + + m_Controller.RefreshCompressionHelper(); + + m_BuildEventHandlerTypeNameIndex = 0; + string[] buildEventHandlerTypeNames = m_Controller.GetBuildEventHandlerTypeNames(); + for (int i = 0; i < buildEventHandlerTypeNames.Length; i++) + { + if (m_Controller.BuildEventHandlerTypeName == buildEventHandlerTypeNames[i]) + { + m_BuildEventHandlerTypeNameIndex = i; + break; + } + } + + m_Controller.RefreshBuildEventHandler(); + } + else + { + Debug.LogWarning("Load configuration failure."); + } + } + + private void Update() + { + if (m_OrderBuildResources) + { + m_OrderBuildResources = false; + BuildResources(); + } + } + + private void OnGUI() + { + EditorGUILayout.BeginVertical(GUILayout.Width(position.width), GUILayout.Height(position.height)); + { + GUILayout.Space(5f); + EditorGUILayout.LabelField("Environment Information", EditorStyles.boldLabel); + EditorGUILayout.BeginVertical("box"); + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Product Name", GUILayout.Width(160f)); + EditorGUILayout.LabelField(m_Controller.ProductName); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Company Name", GUILayout.Width(160f)); + EditorGUILayout.LabelField(m_Controller.CompanyName); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Game Identifier", GUILayout.Width(160f)); + EditorGUILayout.LabelField(m_Controller.GameIdentifier); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Game Framework Version", GUILayout.Width(160f)); + EditorGUILayout.LabelField(m_Controller.GameFrameworkVersion); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Unity Version", GUILayout.Width(160f)); + EditorGUILayout.LabelField(m_Controller.UnityVersion); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Applicable Game Version", GUILayout.Width(160f)); + EditorGUILayout.LabelField(m_Controller.ApplicableGameVersion); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + GUILayout.Space(5f); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.BeginVertical(); + { + EditorGUILayout.LabelField("Platforms", EditorStyles.boldLabel); + EditorGUILayout.BeginHorizontal("box"); + { + EditorGUILayout.BeginVertical(); + { + DrawPlatform(Platform.Windows, "Windows"); + DrawPlatform(Platform.Windows64, "Windows x64"); + DrawPlatform(Platform.MacOS, "macOS"); + } + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical(); + { + DrawPlatform(Platform.Linux, "Linux"); + DrawPlatform(Platform.IOS, "iOS"); + DrawPlatform(Platform.Android, "Android"); + } + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical(); + { + DrawPlatform(Platform.WindowsStore, "Windows Store"); + DrawPlatform(Platform.WebGL, "WebGL"); + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndHorizontal(); + GUILayout.Space(5f); + EditorGUILayout.LabelField("Compression", EditorStyles.boldLabel); + EditorGUILayout.BeginVertical("box"); + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("AssetBundle Compression", GUILayout.Width(160f)); + m_Controller.AssetBundleCompression = (AssetBundleCompressionType)EditorGUILayout.EnumPopup(m_Controller.AssetBundleCompression); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Compression Helper", GUILayout.Width(160f)); + string[] names = m_Controller.GetCompressionHelperTypeNames(); + int selectedIndex = EditorGUILayout.Popup(m_CompressionHelperTypeNameIndex, names); + if (selectedIndex != m_CompressionHelperTypeNameIndex) + { + m_CompressionHelperTypeNameIndex = selectedIndex; + m_Controller.CompressionHelperTypeName = selectedIndex <= 0 ? string.Empty : names[selectedIndex]; + if (m_Controller.RefreshCompressionHelper()) + { + Debug.Log("Set compression helper success."); + } + else + { + Debug.LogWarning("Set compression helper failure."); + } + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Additional Compression", GUILayout.Width(160f)); + m_Controller.AdditionalCompressionSelected = EditorGUILayout.ToggleLeft("Additional Compression for Output Full Resources with Compression Helper", m_Controller.AdditionalCompressionSelected); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + GUILayout.Space(5f); + EditorGUILayout.LabelField("Build", EditorStyles.boldLabel); + EditorGUILayout.BeginVertical("box"); + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Force Rebuild AssetBundle", GUILayout.Width(160f)); + m_Controller.ForceRebuildAssetBundleSelected = EditorGUILayout.Toggle(m_Controller.ForceRebuildAssetBundleSelected); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Build Event Handler", GUILayout.Width(160f)); + string[] names = m_Controller.GetBuildEventHandlerTypeNames(); + int selectedIndex = EditorGUILayout.Popup(m_BuildEventHandlerTypeNameIndex, names); + if (selectedIndex != m_BuildEventHandlerTypeNameIndex) + { + m_BuildEventHandlerTypeNameIndex = selectedIndex; + m_Controller.BuildEventHandlerTypeName = selectedIndex <= 0 ? string.Empty : names[selectedIndex]; + if (m_Controller.RefreshBuildEventHandler()) + { + Debug.Log("Set build event handler success."); + } + else + { + Debug.LogWarning("Set build event handler failure."); + } + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Internal Resource Version", GUILayout.Width(160f)); + m_Controller.InternalResourceVersion = EditorGUILayout.IntField(m_Controller.InternalResourceVersion); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Resource Version", GUILayout.Width(160f)); + GUILayout.Label(Utility.Text.Format("{0} ({1})", m_Controller.ApplicableGameVersion, m_Controller.InternalResourceVersion)); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Output Directory", GUILayout.Width(160f)); + m_Controller.OutputDirectory = EditorGUILayout.TextField(m_Controller.OutputDirectory); + if (GUILayout.Button("Browse...", GUILayout.Width(80f))) + { + BrowseOutputDirectory(); + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Working Path", GUILayout.Width(160f)); + GUILayout.Label(m_Controller.WorkingPath); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUI.BeginDisabledGroup(!m_Controller.OutputPackageSelected); + EditorGUILayout.LabelField("Output Package Path", GUILayout.Width(160f)); + GUILayout.Label(m_Controller.OutputPackagePath); + EditorGUI.EndDisabledGroup(); + m_Controller.OutputPackageSelected = EditorGUILayout.ToggleLeft("Generate", m_Controller.OutputPackageSelected, GUILayout.Width(70f)); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUI.BeginDisabledGroup(!m_Controller.OutputFullSelected); + EditorGUILayout.LabelField("Output Full Path", GUILayout.Width(160f)); + GUILayout.Label(m_Controller.OutputFullPath); + EditorGUI.EndDisabledGroup(); + m_Controller.OutputFullSelected = EditorGUILayout.ToggleLeft("Generate", m_Controller.OutputFullSelected, GUILayout.Width(70f)); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUI.BeginDisabledGroup(!m_Controller.OutputPackedSelected); + EditorGUILayout.LabelField("Output Packed Path", GUILayout.Width(160f)); + GUILayout.Label(m_Controller.OutputPackedPath); + EditorGUI.EndDisabledGroup(); + m_Controller.OutputPackedSelected = EditorGUILayout.ToggleLeft("Generate", m_Controller.OutputPackedSelected, GUILayout.Width(70f)); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Build Report Path", GUILayout.Width(160f)); + GUILayout.Label(m_Controller.BuildReportPath); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + string buildMessage = string.Empty; + MessageType buildMessageType = MessageType.None; + GetBuildMessage(out buildMessage, out buildMessageType); + EditorGUILayout.HelpBox(buildMessage, buildMessageType); + GUILayout.Space(2f); + EditorGUILayout.BeginHorizontal(); + { + EditorGUI.BeginDisabledGroup(m_Controller.Platforms == Platform.Undefined || string.IsNullOrEmpty(m_Controller.CompressionHelperTypeName) || !m_Controller.IsValidOutputDirectory); + { + if (GUILayout.Button("Start Build Resources")) + { + m_OrderBuildResources = true; + } + } + EditorGUI.EndDisabledGroup(); + if (GUILayout.Button("Save", GUILayout.Width(80f))) + { + SaveConfiguration(); + } + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + } + + private void BrowseOutputDirectory() + { + string directory = EditorUtility.OpenFolderPanel("Select Output Directory", m_Controller.OutputDirectory, string.Empty); + if (!string.IsNullOrEmpty(directory)) + { + m_Controller.OutputDirectory = directory; + } + } + + private void GetBuildMessage(out string message, out MessageType messageType) + { + message = string.Empty; + messageType = MessageType.Error; + if (m_Controller.Platforms == Platform.Undefined) + { + if (!string.IsNullOrEmpty(message)) + { + message += Environment.NewLine; + } + + message += "Platform is invalid."; + } + + if (string.IsNullOrEmpty(m_Controller.CompressionHelperTypeName)) + { + if (!string.IsNullOrEmpty(message)) + { + message += Environment.NewLine; + } + + message += "Compression helper is invalid."; + } + + if (!m_Controller.IsValidOutputDirectory) + { + if (!string.IsNullOrEmpty(message)) + { + message += Environment.NewLine; + } + + message += "Output directory is invalid."; + } + + if (!string.IsNullOrEmpty(message)) + { + return; + } + + messageType = MessageType.Info; + if (Directory.Exists(m_Controller.OutputPackagePath)) + { + message += Utility.Text.Format("{0} will be overwritten.", m_Controller.OutputPackagePath); + messageType = MessageType.Warning; + } + + if (Directory.Exists(m_Controller.OutputFullPath)) + { + if (message.Length > 0) + { + message += " "; + } + + message += Utility.Text.Format("{0} will be overwritten.", m_Controller.OutputFullPath); + messageType = MessageType.Warning; + } + + if (Directory.Exists(m_Controller.OutputPackedPath)) + { + if (message.Length > 0) + { + message += " "; + } + + message += Utility.Text.Format("{0} will be overwritten.", m_Controller.OutputPackedPath); + messageType = MessageType.Warning; + } + + if (messageType == MessageType.Warning) + { + return; + } + + message = "Ready to build."; + } + + private void BuildResources() + { + if (m_Controller.BuildResources()) + { + Debug.Log("Build resources success."); + SaveConfiguration(); + } + else + { + Debug.LogWarning("Build resources failure."); + } + } + + private void SaveConfiguration() + { + if (m_Controller.Save()) + { + Debug.Log("Save configuration success."); + } + else + { + Debug.LogWarning("Save configuration failure."); + } + } + + private void DrawPlatform(Platform platform, string platformName) + { + m_Controller.SelectPlatform(platform, EditorGUILayout.ToggleLeft(platformName, m_Controller.IsPlatformSelected(platform))); + } + + private void OnLoadingResource(int index, int count) + { + EditorUtility.DisplayProgressBar("Loading Resources", Utility.Text.Format("Loading resources, {0}/{1} loaded.", index, count), (float)index / count); + } + + private void OnLoadingAsset(int index, int count) + { + EditorUtility.DisplayProgressBar("Loading Assets", Utility.Text.Format("Loading assets, {0}/{1} loaded.", index, count), (float)index / count); + } + + private void OnLoadCompleted() + { + EditorUtility.ClearProgressBar(); + } + + private void OnAnalyzingAsset(int index, int count) + { + EditorUtility.DisplayProgressBar("Analyzing Assets", Utility.Text.Format("Analyzing assets, {0}/{1} analyzed.", index, count), (float)index / count); + } + + private void OnAnalyzeCompleted() + { + EditorUtility.ClearProgressBar(); + } + + private bool OnProcessingAssetBundle(string assetBundleName, float progress) + { + if (EditorUtility.DisplayCancelableProgressBar("Processing AssetBundle", Utility.Text.Format("Processing '{0}'...", assetBundleName), progress)) + { + EditorUtility.ClearProgressBar(); + return true; + } + else + { + Repaint(); + return false; + } + } + + private bool OnProcessingBinary(string binaryName, float progress) + { + if (EditorUtility.DisplayCancelableProgressBar("Processing Binary", Utility.Text.Format("Processing '{0}'...", binaryName), progress)) + { + EditorUtility.ClearProgressBar(); + return true; + } + else + { + Repaint(); + return false; + } + } + + private void OnProcessResourceComplete(Platform platform) + { + EditorUtility.ClearProgressBar(); + Debug.Log(Utility.Text.Format("Build resources for '{0}' complete.", platform)); + } + + private void OnBuildResourceError(string errorMessage) + { + EditorUtility.ClearProgressBar(); + Debug.LogWarning(Utility.Text.Format("Build resources error with error message '{0}'.", errorMessage)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilder.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilder.cs.meta new file mode 100644 index 0000000..afd9986 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e863c5f9e4c0a9d47a926fbb0416a149 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderConfigPathAttribute.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderConfigPathAttribute.cs new file mode 100644 index 0000000..0632b22 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderConfigPathAttribute.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// ResourceBuilder 配置路径属性。 + /// + public sealed class ResourceBuilderConfigPathAttribute : ConfigPathAttribute + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderConfigPathAttribute.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderConfigPathAttribute.cs.meta new file mode 100644 index 0000000..a5d18b4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderConfigPathAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 099a19e921c6da944ba2cdf51139d818 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.AssetData.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.AssetData.cs new file mode 100644 index 0000000..1431d4b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.AssetData.cs @@ -0,0 +1,67 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed partial class ResourceBuilderController + { + private sealed class AssetData + { + private readonly string m_Guid; + private readonly string m_Name; + private readonly int m_Length; + private readonly int m_HashCode; + private readonly string[] m_DependencyAssetNames; + + public AssetData(string guid, string name, int length, int hashCode, string[] dependencyAssetNames) + { + m_Guid = guid; + m_Name = name; + m_Length = length; + m_HashCode = hashCode; + m_DependencyAssetNames = dependencyAssetNames; + } + + public string Guid + { + get + { + return m_Guid; + } + } + + public string Name + { + get + { + return m_Name; + } + } + + public int Length + { + get + { + return m_Length; + } + } + + public int HashCode + { + get + { + return m_HashCode; + } + } + + public string[] GetDependencyAssetNames() + { + return m_DependencyAssetNames; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.AssetData.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.AssetData.cs.meta new file mode 100644 index 0000000..472e462 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.AssetData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b52ab112713ba504a84693edd59a6b03 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.BuildReport.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.BuildReport.cs new file mode 100644 index 0000000..332a9f6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.BuildReport.cs @@ -0,0 +1,276 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; +using UnityEditor; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed partial class ResourceBuilderController + { + private sealed class BuildReport + { + private const string BuildReportName = "BuildReport.xml"; + private const string BuildLogName = "BuildLog.txt"; + + private string m_BuildReportName = null; + private string m_BuildLogName = null; + private string m_ProductName = null; + private string m_CompanyName = null; + private string m_GameIdentifier = null; + private string m_GameFrameworkVersion = null; + private string m_UnityVersion = null; + private string m_ApplicableGameVersion = null; + private int m_InternalResourceVersion = 0; + private Platform m_Platforms = Platform.Undefined; + private AssetBundleCompressionType m_AssetBundleCompression; + private string m_CompressionHelperTypeName; + private bool m_AdditionalCompressionSelected = false; + private bool m_ForceRebuildAssetBundleSelected = false; + private string m_BuildEventHandlerTypeName; + private string m_OutputDirectory; + private BuildAssetBundleOptions m_BuildAssetBundleOptions = BuildAssetBundleOptions.None; + private StringBuilder m_LogBuilder = null; + private SortedDictionary m_ResourceDatas = null; + + public void Initialize(string buildReportPath, string productName, string companyName, string gameIdentifier, string gameFrameworkVersion, string unityVersion, string applicableGameVersion, int internalResourceVersion, + Platform platforms, AssetBundleCompressionType assetBundleCompression, string compressionHelperTypeName, bool additionalCompressionSelected, bool forceRebuildAssetBundleSelected, string buildEventHandlerTypeName, string outputDirectory, BuildAssetBundleOptions buildAssetBundleOptions, SortedDictionary resourceDatas) + { + if (string.IsNullOrEmpty(buildReportPath)) + { + throw new GameFrameworkException("Build report path is invalid."); + } + + m_BuildReportName = Utility.Path.GetRegularPath(Path.Combine(buildReportPath, BuildReportName)); + m_BuildLogName = Utility.Path.GetRegularPath(Path.Combine(buildReportPath, BuildLogName)); + m_ProductName = productName; + m_CompanyName = companyName; + m_GameIdentifier = gameIdentifier; + m_GameFrameworkVersion = gameFrameworkVersion; + m_UnityVersion = unityVersion; + m_ApplicableGameVersion = applicableGameVersion; + m_InternalResourceVersion = internalResourceVersion; + m_Platforms = platforms; + m_AssetBundleCompression = assetBundleCompression; + m_CompressionHelperTypeName = compressionHelperTypeName; + m_AdditionalCompressionSelected = additionalCompressionSelected; + m_ForceRebuildAssetBundleSelected = forceRebuildAssetBundleSelected; + m_BuildEventHandlerTypeName = buildEventHandlerTypeName; + m_OutputDirectory = outputDirectory; + m_BuildAssetBundleOptions = buildAssetBundleOptions; + m_LogBuilder = new StringBuilder(); + m_ResourceDatas = resourceDatas; + } + + public void LogInfo(string format, params object[] args) + { + LogInternal("INFO", format, args); + } + + public void LogWarning(string format, params object[] args) + { + LogInternal("WARNING", format, args); + } + + public void LogError(string format, params object[] args) + { + LogInternal("ERROR", format, args); + } + + public void LogFatal(string format, params object[] args) + { + LogInternal("FATAL", format, args); + } + + public void SaveReport() + { + XmlElement xmlElement = null; + XmlAttribute xmlAttribute = null; + + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.AppendChild(xmlDocument.CreateXmlDeclaration("1.0", "UTF-8", null)); + + XmlElement xmlRoot = xmlDocument.CreateElement("UnityGameFramework"); + xmlDocument.AppendChild(xmlRoot); + + XmlElement xmlBuildReport = xmlDocument.CreateElement("BuildReport"); + xmlRoot.AppendChild(xmlBuildReport); + + XmlElement xmlSummary = xmlDocument.CreateElement("Summary"); + xmlBuildReport.AppendChild(xmlSummary); + + xmlElement = xmlDocument.CreateElement("ProductName"); + xmlElement.InnerText = m_ProductName; + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("CompanyName"); + xmlElement.InnerText = m_CompanyName; + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("GameIdentifier"); + xmlElement.InnerText = m_GameIdentifier; + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("GameFrameworkVersion"); + xmlElement.InnerText = m_GameFrameworkVersion; + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("UnityVersion"); + xmlElement.InnerText = m_UnityVersion; + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("ApplicableGameVersion"); + xmlElement.InnerText = m_ApplicableGameVersion; + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("InternalResourceVersion"); + xmlElement.InnerText = m_InternalResourceVersion.ToString(); + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("Platforms"); + xmlElement.InnerText = m_Platforms.ToString(); + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("AssetBundleCompression"); + xmlElement.InnerText = m_AssetBundleCompression.ToString(); + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("CompressionHelperTypeName"); + xmlElement.InnerText = m_CompressionHelperTypeName; + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("AdditionalCompressionSelected"); + xmlElement.InnerText = m_AdditionalCompressionSelected.ToString(); + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("ForceRebuildAssetBundleSelected"); + xmlElement.InnerText = m_ForceRebuildAssetBundleSelected.ToString(); + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("BuildEventHandlerTypeName"); + xmlElement.InnerText = m_BuildEventHandlerTypeName; + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("OutputDirectory"); + xmlElement.InnerText = m_OutputDirectory; + xmlSummary.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("BuildAssetBundleOptions"); + xmlElement.InnerText = m_BuildAssetBundleOptions.ToString(); + xmlSummary.AppendChild(xmlElement); + + XmlElement xmlResources = xmlDocument.CreateElement("Resources"); + xmlAttribute = xmlDocument.CreateAttribute("Count"); + xmlAttribute.Value = m_ResourceDatas.Count.ToString(); + xmlResources.Attributes.SetNamedItem(xmlAttribute); + xmlBuildReport.AppendChild(xmlResources); + foreach (ResourceData resourceData in m_ResourceDatas.Values) + { + XmlElement xmlResource = xmlDocument.CreateElement("Resource"); + xmlAttribute = xmlDocument.CreateAttribute("Name"); + xmlAttribute.Value = resourceData.Name; + xmlResource.Attributes.SetNamedItem(xmlAttribute); + if (resourceData.Variant != null) + { + xmlAttribute = xmlDocument.CreateAttribute("Variant"); + xmlAttribute.Value = resourceData.Variant; + xmlResource.Attributes.SetNamedItem(xmlAttribute); + } + + xmlAttribute = xmlDocument.CreateAttribute("Extension"); + xmlAttribute.Value = GetExtension(resourceData); + xmlResource.Attributes.SetNamedItem(xmlAttribute); + + if (resourceData.FileSystem != null) + { + xmlAttribute = xmlDocument.CreateAttribute("FileSystem"); + xmlAttribute.Value = resourceData.FileSystem; + xmlResource.Attributes.SetNamedItem(xmlAttribute); + } + + xmlAttribute = xmlDocument.CreateAttribute("LoadType"); + xmlAttribute.Value = ((byte)resourceData.LoadType).ToString(); + xmlResource.Attributes.SetNamedItem(xmlAttribute); + xmlAttribute = xmlDocument.CreateAttribute("Packed"); + xmlAttribute.Value = resourceData.Packed.ToString(); + xmlResource.Attributes.SetNamedItem(xmlAttribute); + string[] resourceGroups = resourceData.GetResourceGroups(); + if (resourceGroups.Length > 0) + { + xmlAttribute = xmlDocument.CreateAttribute("ResourceGroups"); + xmlAttribute.Value = string.Join(",", resourceGroups); + xmlResource.Attributes.SetNamedItem(xmlAttribute); + } + + xmlResources.AppendChild(xmlResource); + + AssetData[] assetDatas = resourceData.GetAssetDatas(); + XmlElement xmlAssets = xmlDocument.CreateElement("Assets"); + xmlAttribute = xmlDocument.CreateAttribute("Count"); + xmlAttribute.Value = assetDatas.Length.ToString(); + xmlAssets.Attributes.SetNamedItem(xmlAttribute); + xmlResource.AppendChild(xmlAssets); + foreach (AssetData assetData in assetDatas) + { + XmlElement xmlAsset = xmlDocument.CreateElement("Asset"); + xmlAttribute = xmlDocument.CreateAttribute("Guid"); + xmlAttribute.Value = assetData.Guid; + xmlAsset.Attributes.SetNamedItem(xmlAttribute); + xmlAttribute = xmlDocument.CreateAttribute("Name"); + xmlAttribute.Value = assetData.Name; + xmlAsset.Attributes.SetNamedItem(xmlAttribute); + xmlAttribute = xmlDocument.CreateAttribute("Length"); + xmlAttribute.Value = assetData.Length.ToString(); + xmlAsset.Attributes.SetNamedItem(xmlAttribute); + xmlAttribute = xmlDocument.CreateAttribute("HashCode"); + xmlAttribute.Value = assetData.HashCode.ToString(); + xmlAsset.Attributes.SetNamedItem(xmlAttribute); + xmlAssets.AppendChild(xmlAsset); + string[] dependencyAssetNames = assetData.GetDependencyAssetNames(); + if (dependencyAssetNames.Length > 0) + { + XmlElement xmlDependencyAssets = xmlDocument.CreateElement("DependencyAssets"); + xmlAttribute = xmlDocument.CreateAttribute("Count"); + xmlAttribute.Value = dependencyAssetNames.Length.ToString(); + xmlDependencyAssets.Attributes.SetNamedItem(xmlAttribute); + xmlAsset.AppendChild(xmlDependencyAssets); + foreach (string dependencyAssetName in dependencyAssetNames) + { + XmlElement xmlDependencyAsset = xmlDocument.CreateElement("DependencyAsset"); + xmlAttribute = xmlDocument.CreateAttribute("Name"); + xmlAttribute.Value = dependencyAssetName; + xmlDependencyAsset.Attributes.SetNamedItem(xmlAttribute); + xmlDependencyAssets.AppendChild(xmlDependencyAsset); + } + } + } + + XmlElement xmlCodes = xmlDocument.CreateElement("Codes"); + xmlResource.AppendChild(xmlCodes); + foreach (ResourceCode resourceCode in resourceData.GetCodes()) + { + XmlElement xmlCode = xmlDocument.CreateElement(resourceCode.Platform.ToString()); + xmlAttribute = xmlDocument.CreateAttribute("Length"); + xmlAttribute.Value = resourceCode.Length.ToString(); + xmlCode.Attributes.SetNamedItem(xmlAttribute); + xmlAttribute = xmlDocument.CreateAttribute("HashCode"); + xmlAttribute.Value = resourceCode.HashCode.ToString(); + xmlCode.Attributes.SetNamedItem(xmlAttribute); + xmlAttribute = xmlDocument.CreateAttribute("CompressedLength"); + xmlAttribute.Value = resourceCode.CompressedLength.ToString(); + xmlCode.Attributes.SetNamedItem(xmlAttribute); + xmlAttribute = xmlDocument.CreateAttribute("CompressedHashCode"); + xmlAttribute.Value = resourceCode.CompressedHashCode.ToString(); + xmlCode.Attributes.SetNamedItem(xmlAttribute); + xmlCodes.AppendChild(xmlCode); + } + } + + xmlDocument.Save(m_BuildReportName); + File.WriteAllText(m_BuildLogName, m_LogBuilder.ToString()); + } + + private void LogInternal(string type, string format, object[] args) + { + m_LogBuilder.AppendFormat("[{0:HH:mm:ss.fff}][{1}] ", DateTime.UtcNow.ToLocalTime(), type); + m_LogBuilder.AppendFormat(format, args); + m_LogBuilder.AppendLine(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.BuildReport.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.BuildReport.cs.meta new file mode 100644 index 0000000..70bd108 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.BuildReport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae0020ba4726cbd46b34a2341c16cd6a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.FileSystemHelper.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.FileSystemHelper.cs new file mode 100644 index 0000000..a0bd80a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.FileSystemHelper.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.FileSystem; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed partial class ResourceBuilderController + { + private sealed class FileSystemHelper : IFileSystemHelper + { + public FileSystemStream CreateFileSystemStream(string fullPath, FileSystemAccess access, bool createNew) + { + return new CommonFileSystemStream(fullPath, access, createNew); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.FileSystemHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.FileSystemHelper.cs.meta new file mode 100644 index 0000000..754d7b6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.FileSystemHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 23c25a2b879a092409b04f2e7851ac6b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.ResourceCode.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.ResourceCode.cs new file mode 100644 index 0000000..2d0358f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.ResourceCode.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed partial class ResourceBuilderController + { + private sealed class ResourceCode + { + private readonly Platform m_Platform; + private readonly int m_Length; + private readonly int m_HashCode; + private readonly int m_CompressedLength; + private readonly int m_CompressedHashCode; + + public ResourceCode(Platform platform, int length, int hashCode, int compressedLength, int compressedHashCode) + { + m_Platform = platform; + m_Length = length; + m_HashCode = hashCode; + m_CompressedLength = compressedLength; + m_CompressedHashCode = compressedHashCode; + } + + public Platform Platform + { + get + { + return m_Platform; + } + } + + public int Length + { + get + { + return m_Length; + } + } + + public int HashCode + { + get + { + return m_HashCode; + } + } + + public int CompressedLength + { + get + { + return m_CompressedLength; + } + } + + public int CompressedHashCode + { + get + { + return m_CompressedHashCode; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.ResourceCode.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.ResourceCode.cs.meta new file mode 100644 index 0000000..65a19fa --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.ResourceCode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 86943b1b61e58a340b707c7c11f47700 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.ResourceData.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.ResourceData.cs new file mode 100644 index 0000000..ad9afbd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.ResourceData.cs @@ -0,0 +1,167 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed partial class ResourceBuilderController + { + private sealed class ResourceData + { + private readonly string m_Name; + private readonly string m_Variant; + private readonly string m_FileSystem; + private readonly LoadType m_LoadType; + private readonly bool m_Packed; + private readonly string[] m_ResourceGroups; + private readonly List m_AssetDatas; + private readonly List m_Codes; + + public ResourceData(string name, string variant, string fileSystem, LoadType loadType, bool packed, string[] resourceGroups) + { + m_Name = name; + m_Variant = variant; + m_FileSystem = fileSystem; + m_LoadType = loadType; + m_Packed = packed; + m_ResourceGroups = resourceGroups; + m_AssetDatas = new List(); + m_Codes = new List(); + } + + public string Name + { + get + { + return m_Name; + } + } + + public string Variant + { + get + { + return m_Variant; + } + } + + public string FileSystem + { + get + { + return m_FileSystem; + } + } + + public bool IsLoadFromBinary + { + get + { + return m_LoadType == LoadType.LoadFromBinary || m_LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || m_LoadType == LoadType.LoadFromBinaryAndDecrypt; + } + } + + public LoadType LoadType + { + get + { + return m_LoadType; + } + } + + public bool Packed + { + get + { + return m_Packed; + } + } + + public int AssetCount + { + get + { + return m_AssetDatas.Count; + } + } + + public string[] GetResourceGroups() + { + return m_ResourceGroups; + } + + public string[] GetAssetGuids() + { + string[] assetGuids = new string[m_AssetDatas.Count]; + for (int i = 0; i < m_AssetDatas.Count; i++) + { + assetGuids[i] = m_AssetDatas[i].Guid; + } + + return assetGuids; + } + + public string[] GetAssetNames() + { + string[] assetNames = new string[m_AssetDatas.Count]; + for (int i = 0; i < m_AssetDatas.Count; i++) + { + assetNames[i] = m_AssetDatas[i].Name; + } + + return assetNames; + } + + public AssetData[] GetAssetDatas() + { + return m_AssetDatas.ToArray(); + } + + public AssetData GetAssetData(string assetName) + { + foreach (AssetData assetData in m_AssetDatas) + { + if (assetData.Name == assetName) + { + return assetData; + } + } + + return null; + } + + public void AddAssetData(string guid, string name, int length, int hashCode, string[] dependencyAssetNames) + { + m_AssetDatas.Add(new AssetData(guid, name, length, hashCode, dependencyAssetNames)); + } + + public ResourceCode GetCode(Platform platform) + { + foreach (ResourceCode code in m_Codes) + { + if (code.Platform == platform) + { + return code; + } + } + + return null; + } + + public ResourceCode[] GetCodes() + { + return m_Codes.ToArray(); + } + + public void AddCode(Platform platform, int length, int hashCode, int compressedLength, int compressedHashCode) + { + m_Codes.Add(new ResourceCode(platform, length, hashCode, compressedLength, compressedHashCode)); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.ResourceData.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.ResourceData.cs.meta new file mode 100644 index 0000000..5a662b5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.ResourceData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 61757cf57a877ce46a12429a7e8996dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.VersionListData.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.VersionListData.cs new file mode 100644 index 0000000..f45746d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.VersionListData.cs @@ -0,0 +1,54 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed partial class ResourceBuilderController + { + private sealed class VersionListData + { + public VersionListData(string path, int length, int hashCode, int compressedLength, int compressedHashCode) + { + Path = path; + Length = length; + HashCode = hashCode; + CompressedLength = compressedLength; + CompressedHashCode = compressedHashCode; + } + + public string Path + { + get; + private set; + } + + public int Length + { + get; + private set; + } + + public int HashCode + { + get; + private set; + } + + public int CompressedLength + { + get; + private set; + } + + public int CompressedHashCode + { + get; + private set; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.VersionListData.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.VersionListData.cs.meta new file mode 100644 index 0000000..77b014a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.VersionListData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c69cd2ac760709b4ab36ba15bc5d8759 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.cs new file mode 100644 index 0000000..1c039ac --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.cs @@ -0,0 +1,1567 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.FileSystem; +using GameFramework.Resource; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml; +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed partial class ResourceBuilderController + { + private const string RemoteVersionListFileName = "GameFrameworkVersion.dat"; + private const string LocalVersionListFileName = "GameFrameworkList.dat"; + private const string DefaultExtension = "dat"; + private const string NoneOptionName = ""; + private static readonly int AssetsStringLength = "Assets".Length; + + private readonly string m_ConfigurationPath; + private readonly ResourceCollection m_ResourceCollection; + private readonly ResourceAnalyzerController m_ResourceAnalyzerController; + private readonly SortedDictionary m_ResourceDatas; + private readonly Dictionary m_OutputPackageFileSystems; + private readonly Dictionary m_OutputPackedFileSystems; + private readonly BuildReport m_BuildReport; + private readonly List m_CompressionHelperTypeNames; + private readonly List m_BuildEventHandlerTypeNames; + private IBuildEventHandler m_BuildEventHandler; + private IFileSystemManager m_FileSystemManager; + + public ResourceBuilderController() + { + m_ConfigurationPath = Type.GetConfigurationPath() ?? Utility.Path.GetRegularPath(Path.Combine(Application.dataPath, "GameFramework/Configs/ResourceBuilder.xml")); + + m_ResourceCollection = new ResourceCollection(); + m_ResourceCollection.OnLoadingResource += delegate (int index, int count) + { + if (OnLoadingResource != null) + { + OnLoadingResource(index, count); + } + }; + + m_ResourceCollection.OnLoadingAsset += delegate (int index, int count) + { + if (OnLoadingAsset != null) + { + OnLoadingAsset(index, count); + } + }; + + m_ResourceCollection.OnLoadCompleted += delegate () + { + if (OnLoadCompleted != null) + { + OnLoadCompleted(); + } + }; + + m_ResourceAnalyzerController = new ResourceAnalyzerController(m_ResourceCollection); + + m_ResourceAnalyzerController.OnAnalyzingAsset += delegate (int index, int count) + { + if (OnAnalyzingAsset != null) + { + OnAnalyzingAsset(index, count); + } + }; + + m_ResourceAnalyzerController.OnAnalyzeCompleted += delegate () + { + if (OnAnalyzeCompleted != null) + { + OnAnalyzeCompleted(); + } + }; + + m_ResourceDatas = new SortedDictionary(StringComparer.Ordinal); + m_OutputPackageFileSystems = new Dictionary(StringComparer.Ordinal); + m_OutputPackedFileSystems = new Dictionary(StringComparer.Ordinal); + m_BuildReport = new BuildReport(); + + m_CompressionHelperTypeNames = new List + { + NoneOptionName + }; + + m_BuildEventHandlerTypeNames = new List + { + NoneOptionName + }; + + m_CompressionHelperTypeNames.AddRange(Type.GetRuntimeOrEditorTypeNames(typeof(Utility.Compression.ICompressionHelper))); + m_BuildEventHandlerTypeNames.AddRange(Type.GetRuntimeOrEditorTypeNames(typeof(IBuildEventHandler))); + m_BuildEventHandler = null; + m_FileSystemManager = null; + + Platforms = Platform.Undefined; + AssetBundleCompression = AssetBundleCompressionType.LZ4; + CompressionHelperTypeName = string.Empty; + AdditionalCompressionSelected = false; + ForceRebuildAssetBundleSelected = false; + BuildEventHandlerTypeName = string.Empty; + OutputDirectory = string.Empty; + OutputPackageSelected = OutputFullSelected = OutputPackedSelected = true; + } + + public string ProductName + { + get + { + return PlayerSettings.productName; + } + } + + public string CompanyName + { + get + { + return PlayerSettings.companyName; + } + } + + public string GameIdentifier + { + get + { +#if UNITY_5_6_OR_NEWER + return PlayerSettings.applicationIdentifier; +#else + return PlayerSettings.bundleIdentifier; +#endif + } + } + + public string GameFrameworkVersion + { + get + { + return GameFramework.Version.GameFrameworkVersion; + } + } + + public string UnityVersion + { + get + { + return Application.unityVersion; + } + } + + public string ApplicableGameVersion + { + get + { + return Application.version; + } + } + + public int InternalResourceVersion + { + get; + set; + } + + public Platform Platforms + { + get; + set; + } + + public AssetBundleCompressionType AssetBundleCompression + { + get; + set; + } + + public string CompressionHelperTypeName + { + get; + set; + } + + public bool AdditionalCompressionSelected + { + get; + set; + } + + public bool ForceRebuildAssetBundleSelected + { + get; + set; + } + + public string BuildEventHandlerTypeName + { + get; + set; + } + + public string OutputDirectory + { + get; + set; + } + + public bool OutputPackageSelected + { + get; + set; + } + + public bool OutputFullSelected + { + get; + set; + } + + public bool OutputPackedSelected + { + get; + set; + } + + public bool IsValidOutputDirectory + { + get + { + if (string.IsNullOrEmpty(OutputDirectory)) + { + return false; + } + + if (!Directory.Exists(OutputDirectory)) + { + return false; + } + + return true; + } + } + + public string WorkingPath + { + get + { + if (!IsValidOutputDirectory) + { + return string.Empty; + } + + return Utility.Path.GetRegularPath(new DirectoryInfo(Utility.Text.Format("{0}/Working/", OutputDirectory)).FullName); + } + } + + public string OutputPackagePath + { + get + { + if (!IsValidOutputDirectory) + { + return string.Empty; + } + + return Utility.Path.GetRegularPath(new DirectoryInfo(Utility.Text.Format("{0}/Package/{1}_{2}/", OutputDirectory, ApplicableGameVersion.Replace('.', '_'), InternalResourceVersion)).FullName); + } + } + + public string OutputFullPath + { + get + { + if (!IsValidOutputDirectory) + { + return string.Empty; + } + + return Utility.Path.GetRegularPath(new DirectoryInfo(Utility.Text.Format("{0}/Full/{1}_{2}/", OutputDirectory, ApplicableGameVersion.Replace('.', '_'), InternalResourceVersion)).FullName); + } + } + + public string OutputPackedPath + { + get + { + if (!IsValidOutputDirectory) + { + return string.Empty; + } + + return Utility.Path.GetRegularPath(new DirectoryInfo(Utility.Text.Format("{0}/Packed/{1}_{2}/", OutputDirectory, ApplicableGameVersion.Replace('.', '_'), InternalResourceVersion)).FullName); + } + } + + public string BuildReportPath + { + get + { + if (!IsValidOutputDirectory) + { + return string.Empty; + } + + return Utility.Path.GetRegularPath(new DirectoryInfo(Utility.Text.Format("{0}/BuildReport/{1}_{2}/", OutputDirectory, ApplicableGameVersion.Replace('.', '_'), InternalResourceVersion)).FullName); + } + } + + public event GameFrameworkAction OnLoadingResource = null; + + public event GameFrameworkAction OnLoadingAsset = null; + + public event GameFrameworkAction OnLoadCompleted = null; + + public event GameFrameworkAction OnAnalyzingAsset = null; + + public event GameFrameworkAction OnAnalyzeCompleted = null; + + public event GameFrameworkFunc ProcessingAssetBundle = null; + + public event GameFrameworkFunc ProcessingBinary = null; + + public event GameFrameworkAction ProcessResourceComplete = null; + + public event GameFrameworkAction BuildResourceError = null; + + public bool Load() + { + if (!File.Exists(m_ConfigurationPath)) + { + return false; + } + + try + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load(m_ConfigurationPath); + XmlNode xmlRoot = xmlDocument.SelectSingleNode("UnityGameFramework"); + XmlNode xmlEditor = xmlRoot.SelectSingleNode("ResourceBuilder"); + XmlNode xmlSettings = xmlEditor.SelectSingleNode("Settings"); + + XmlNodeList xmlNodeList = null; + XmlNode xmlNode = null; + + xmlNodeList = xmlSettings.ChildNodes; + for (int i = 0; i < xmlNodeList.Count; i++) + { + xmlNode = xmlNodeList.Item(i); + switch (xmlNode.Name) + { + case "InternalResourceVersion": + InternalResourceVersion = int.Parse(xmlNode.InnerText) + 1; + break; + + case "Platforms": + Platforms = (Platform)int.Parse(xmlNode.InnerText); + break; + + case "AssetBundleCompression": + AssetBundleCompression = (AssetBundleCompressionType)byte.Parse(xmlNode.InnerText); + break; + + case "CompressionHelperTypeName": + CompressionHelperTypeName = xmlNode.InnerText; + break; + + case "AdditionalCompressionSelected": + AdditionalCompressionSelected = bool.Parse(xmlNode.InnerText); + break; + + case "ForceRebuildAssetBundleSelected": + ForceRebuildAssetBundleSelected = bool.Parse(xmlNode.InnerText); + break; + + case "BuildEventHandlerTypeName": + BuildEventHandlerTypeName = xmlNode.InnerText; + break; + + case "OutputDirectory": + OutputDirectory = xmlNode.InnerText; + break; + + case "OutputPackageSelected": + OutputPackageSelected = bool.Parse(xmlNode.InnerText); + break; + + case "OutputFullSelected": + OutputFullSelected = bool.Parse(xmlNode.InnerText); + break; + + case "OutputPackedSelected": + OutputPackedSelected = bool.Parse(xmlNode.InnerText); + break; + } + } + } + catch + { + File.Delete(m_ConfigurationPath); + return false; + } + + return true; + } + + public bool Save() + { + try + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.AppendChild(xmlDocument.CreateXmlDeclaration("1.0", "UTF-8", null)); + + XmlElement xmlRoot = xmlDocument.CreateElement("UnityGameFramework"); + xmlDocument.AppendChild(xmlRoot); + + XmlElement xmlBuilder = xmlDocument.CreateElement("ResourceBuilder"); + xmlRoot.AppendChild(xmlBuilder); + + XmlElement xmlSettings = xmlDocument.CreateElement("Settings"); + xmlBuilder.AppendChild(xmlSettings); + + XmlElement xmlElement = null; + + xmlElement = xmlDocument.CreateElement("InternalResourceVersion"); + xmlElement.InnerText = InternalResourceVersion.ToString(); + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("Platforms"); + xmlElement.InnerText = ((int)Platforms).ToString(); + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("AssetBundleCompression"); + xmlElement.InnerText = ((byte)AssetBundleCompression).ToString(); + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("CompressionHelperTypeName"); + xmlElement.InnerText = CompressionHelperTypeName; + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("AdditionalCompressionSelected"); + xmlElement.InnerText = AdditionalCompressionSelected.ToString(); + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("ForceRebuildAssetBundleSelected"); + xmlElement.InnerText = ForceRebuildAssetBundleSelected.ToString(); + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("BuildEventHandlerTypeName"); + xmlElement.InnerText = BuildEventHandlerTypeName; + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("OutputDirectory"); + xmlElement.InnerText = OutputDirectory; + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("OutputPackageSelected"); + xmlElement.InnerText = OutputPackageSelected.ToString(); + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("OutputFullSelected"); + xmlElement.InnerText = OutputFullSelected.ToString(); + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("OutputPackedSelected"); + xmlElement.InnerText = OutputPackedSelected.ToString(); + xmlSettings.AppendChild(xmlElement); + + string configurationDirectoryName = Path.GetDirectoryName(m_ConfigurationPath); + if (!Directory.Exists(configurationDirectoryName)) + { + Directory.CreateDirectory(configurationDirectoryName); + } + + xmlDocument.Save(m_ConfigurationPath); + AssetDatabase.Refresh(); + return true; + } + catch + { + if (File.Exists(m_ConfigurationPath)) + { + File.Delete(m_ConfigurationPath); + } + + return false; + } + } + + public string[] GetCompressionHelperTypeNames() + { + return m_CompressionHelperTypeNames.ToArray(); + } + + public string[] GetBuildEventHandlerTypeNames() + { + return m_BuildEventHandlerTypeNames.ToArray(); + } + + public bool IsPlatformSelected(Platform platform) + { + return (Platforms & platform) != 0; + } + + public void SelectPlatform(Platform platform, bool selected) + { + if (selected) + { + Platforms |= platform; + } + else + { + Platforms &= ~platform; + } + } + + public bool RefreshCompressionHelper() + { + bool retVal = false; + if (!string.IsNullOrEmpty(CompressionHelperTypeName) && m_CompressionHelperTypeNames.Contains(CompressionHelperTypeName)) + { + System.Type compressionHelperType = Utility.Assembly.GetType(CompressionHelperTypeName); + if (compressionHelperType != null) + { + Utility.Compression.ICompressionHelper compressionHelper = (Utility.Compression.ICompressionHelper)Activator.CreateInstance(compressionHelperType); + if (compressionHelper != null) + { + Utility.Compression.SetCompressionHelper(compressionHelper); + return true; + } + } + } + else + { + retVal = true; + } + + CompressionHelperTypeName = string.Empty; + Utility.Compression.SetCompressionHelper(null); + return retVal; + } + + public bool RefreshBuildEventHandler() + { + bool retVal = false; + if (!string.IsNullOrEmpty(BuildEventHandlerTypeName) && m_BuildEventHandlerTypeNames.Contains(BuildEventHandlerTypeName)) + { + System.Type buildEventHandlerType = Utility.Assembly.GetType(BuildEventHandlerTypeName); + if (buildEventHandlerType != null) + { + IBuildEventHandler buildEventHandler = (IBuildEventHandler)Activator.CreateInstance(buildEventHandlerType); + if (buildEventHandler != null) + { + m_BuildEventHandler = buildEventHandler; + return true; + } + } + } + else + { + retVal = true; + } + + BuildEventHandlerTypeName = string.Empty; + m_BuildEventHandler = null; + return retVal; + } + + public bool BuildResources() + { + if (!IsValidOutputDirectory) + { + return false; + } + + if (Directory.Exists(OutputPackagePath)) + { + Directory.Delete(OutputPackagePath, true); + } + + Directory.CreateDirectory(OutputPackagePath); + + if (Directory.Exists(OutputFullPath)) + { + Directory.Delete(OutputFullPath, true); + } + + Directory.CreateDirectory(OutputFullPath); + + if (Directory.Exists(OutputPackedPath)) + { + Directory.Delete(OutputPackedPath, true); + } + + Directory.CreateDirectory(OutputPackedPath); + + if (Directory.Exists(BuildReportPath)) + { + Directory.Delete(BuildReportPath, true); + } + + Directory.CreateDirectory(BuildReportPath); + + BuildAssetBundleOptions buildAssetBundleOptions = GetBuildAssetBundleOptions(); + m_BuildReport.Initialize(BuildReportPath, ProductName, CompanyName, GameIdentifier, GameFrameworkVersion, UnityVersion, ApplicableGameVersion, InternalResourceVersion, + Platforms, AssetBundleCompression, CompressionHelperTypeName, AdditionalCompressionSelected, ForceRebuildAssetBundleSelected, BuildEventHandlerTypeName, OutputDirectory, buildAssetBundleOptions, m_ResourceDatas); + + try + { + m_BuildReport.LogInfo("Build Start Time: {0:yyyy-MM-dd HH:mm:ss.fff}", DateTime.UtcNow.ToLocalTime()); + + if (m_BuildEventHandler != null) + { + m_BuildReport.LogInfo("Execute build event handler 'OnPreprocessAllPlatforms'..."); + m_BuildEventHandler.OnPreprocessAllPlatforms(ProductName, CompanyName, GameIdentifier, GameFrameworkVersion, UnityVersion, ApplicableGameVersion, InternalResourceVersion, + Platforms, AssetBundleCompression, CompressionHelperTypeName, AdditionalCompressionSelected, ForceRebuildAssetBundleSelected, BuildEventHandlerTypeName, OutputDirectory, buildAssetBundleOptions, + WorkingPath, OutputPackageSelected, OutputPackagePath, OutputFullSelected, OutputFullPath, OutputPackedSelected, OutputPackedPath, BuildReportPath); + } + + m_BuildReport.LogInfo("Start prepare resource collection..."); + if (!m_ResourceCollection.Load()) + { + m_BuildReport.LogError("Can not parse 'ResourceCollection.xml', please use 'Resource Editor' tool first."); + + if (m_BuildEventHandler != null) + { + m_BuildReport.LogInfo("Execute build event handler 'OnPostprocessAllPlatforms'..."); + m_BuildEventHandler.OnPostprocessAllPlatforms(ProductName, CompanyName, GameIdentifier, GameFrameworkVersion, UnityVersion, ApplicableGameVersion, InternalResourceVersion, + Platforms, AssetBundleCompression, CompressionHelperTypeName, AdditionalCompressionSelected, ForceRebuildAssetBundleSelected, BuildEventHandlerTypeName, OutputDirectory, buildAssetBundleOptions, + WorkingPath, OutputPackageSelected, OutputPackagePath, OutputFullSelected, OutputFullPath, OutputPackedSelected, OutputPackedPath, BuildReportPath); + } + + m_BuildReport.SaveReport(); + return false; + } + + if (Platforms == Platform.Undefined) + { + m_BuildReport.LogError("Platform undefined."); + + if (m_BuildEventHandler != null) + { + m_BuildReport.LogInfo("Execute build event handler 'OnPostprocessAllPlatforms'..."); + m_BuildEventHandler.OnPostprocessAllPlatforms(ProductName, CompanyName, GameIdentifier, GameFrameworkVersion, UnityVersion, ApplicableGameVersion, InternalResourceVersion, + Platforms, AssetBundleCompression, CompressionHelperTypeName, AdditionalCompressionSelected, ForceRebuildAssetBundleSelected, BuildEventHandlerTypeName, OutputDirectory, buildAssetBundleOptions, + WorkingPath, OutputPackageSelected, OutputPackagePath, OutputFullSelected, OutputFullPath, OutputPackedSelected, OutputPackedPath, BuildReportPath); + } + + m_BuildReport.SaveReport(); + return false; + } + + m_BuildReport.LogInfo("Prepare resource collection complete."); + m_BuildReport.LogInfo("Start analyze assets dependency..."); + + m_ResourceAnalyzerController.Analyze(); + + m_BuildReport.LogInfo("Analyze assets dependency complete."); + m_BuildReport.LogInfo("Start prepare build data..."); + + AssetBundleBuild[] assetBundleBuildDatas = null; + ResourceData[] assetBundleResourceDatas = null; + ResourceData[] binaryResourceDatas = null; + if (!PrepareBuildData(out assetBundleBuildDatas, out assetBundleResourceDatas, out binaryResourceDatas)) + { + m_BuildReport.LogError("Prepare resource build data failure."); + + if (m_BuildEventHandler != null) + { + m_BuildReport.LogInfo("Execute build event handler 'OnPostprocessAllPlatforms'..."); + m_BuildEventHandler.OnPostprocessAllPlatforms(ProductName, CompanyName, GameIdentifier, GameFrameworkVersion, UnityVersion, ApplicableGameVersion, InternalResourceVersion, + Platforms, AssetBundleCompression, CompressionHelperTypeName, AdditionalCompressionSelected, ForceRebuildAssetBundleSelected, BuildEventHandlerTypeName, OutputDirectory, buildAssetBundleOptions, + WorkingPath, OutputPackageSelected, OutputPackagePath, OutputFullSelected, OutputFullPath, OutputPackedSelected, OutputPackedPath, BuildReportPath); + } + + m_BuildReport.SaveReport(); + return false; + } + + m_BuildReport.LogInfo("Prepare resource build data complete."); + m_BuildReport.LogInfo("Start build resources for selected platforms..."); + + bool watchResult = m_BuildEventHandler == null || !m_BuildEventHandler.ContinueOnFailure; + bool isSuccess = false; + isSuccess = BuildResources(Platform.Windows, assetBundleBuildDatas, buildAssetBundleOptions, assetBundleResourceDatas, binaryResourceDatas); + + if (!watchResult || isSuccess) + { + isSuccess = BuildResources(Platform.Windows64, assetBundleBuildDatas, buildAssetBundleOptions, assetBundleResourceDatas, binaryResourceDatas); + } + + if (!watchResult || isSuccess) + { + isSuccess = BuildResources(Platform.MacOS, assetBundleBuildDatas, buildAssetBundleOptions, assetBundleResourceDatas, binaryResourceDatas); + } + + if (!watchResult || isSuccess) + { + isSuccess = BuildResources(Platform.Linux, assetBundleBuildDatas, buildAssetBundleOptions, assetBundleResourceDatas, binaryResourceDatas); + } + + if (!watchResult || isSuccess) + { + isSuccess = BuildResources(Platform.IOS, assetBundleBuildDatas, buildAssetBundleOptions, assetBundleResourceDatas, binaryResourceDatas); + } + + if (!watchResult || isSuccess) + { + isSuccess = BuildResources(Platform.Android, assetBundleBuildDatas, buildAssetBundleOptions, assetBundleResourceDatas, binaryResourceDatas); + } + + if (!watchResult || isSuccess) + { + isSuccess = BuildResources(Platform.WindowsStore, assetBundleBuildDatas, buildAssetBundleOptions, assetBundleResourceDatas, binaryResourceDatas); + } + + if (!watchResult || isSuccess) + { + isSuccess = BuildResources(Platform.WebGL, assetBundleBuildDatas, buildAssetBundleOptions, assetBundleResourceDatas, binaryResourceDatas); + } + + if (m_BuildEventHandler != null) + { + m_BuildReport.LogInfo("Execute build event handler 'OnPostprocessAllPlatforms'..."); + m_BuildEventHandler.OnPostprocessAllPlatforms(ProductName, CompanyName, GameIdentifier, GameFrameworkVersion, UnityVersion, ApplicableGameVersion, InternalResourceVersion, + Platforms, AssetBundleCompression, CompressionHelperTypeName, AdditionalCompressionSelected, ForceRebuildAssetBundleSelected, BuildEventHandlerTypeName, OutputDirectory, buildAssetBundleOptions, + WorkingPath, OutputPackageSelected, OutputPackagePath, OutputFullSelected, OutputFullPath, OutputPackedSelected, OutputPackedPath, BuildReportPath); + } + + m_BuildReport.LogInfo("Build resources for selected platforms complete."); + m_BuildReport.SaveReport(); + + return true; + } + catch (Exception exception) + { + string errorMessage = exception.ToString(); + m_BuildReport.LogFatal(errorMessage); + m_BuildReport.SaveReport(); + if (BuildResourceError != null) + { + BuildResourceError(errorMessage); + } + + return false; + } + finally + { + m_OutputPackageFileSystems.Clear(); + m_OutputPackedFileSystems.Clear(); + if (m_FileSystemManager != null) + { + GameFrameworkEntry.Shutdown(); + m_FileSystemManager = null; + } + } + } + + private bool BuildResources(Platform platform, AssetBundleBuild[] assetBundleBuildDatas, BuildAssetBundleOptions buildAssetBundleOptions, ResourceData[] assetBundleResourceDatas, ResourceData[] binaryResourceDatas) + { + if (!IsPlatformSelected(platform)) + { + return true; + } + + string platformName = platform.ToString(); + m_BuildReport.LogInfo("Start build resources for '{0}'...", platformName); + + string workingPath = Utility.Text.Format("{0}{1}/", WorkingPath, platformName); + m_BuildReport.LogInfo("Working path is '{0}'.", workingPath); + + string outputPackagePath = Utility.Text.Format("{0}{1}/", OutputPackagePath, platformName); + if (OutputPackageSelected) + { + Directory.CreateDirectory(outputPackagePath); + m_BuildReport.LogInfo("Output package is selected, path is '{0}'.", outputPackagePath); + } + else + { + m_BuildReport.LogInfo("Output package is not selected."); + } + + string outputFullPath = Utility.Text.Format("{0}{1}/", OutputFullPath, platformName); + if (OutputFullSelected) + { + Directory.CreateDirectory(outputFullPath); + m_BuildReport.LogInfo("Output full is selected, path is '{0}'.", outputFullPath); + } + else + { + m_BuildReport.LogInfo("Output full is not selected."); + } + + string outputPackedPath = Utility.Text.Format("{0}{1}/", OutputPackedPath, platformName); + if (OutputPackedSelected) + { + Directory.CreateDirectory(outputPackedPath); + m_BuildReport.LogInfo("Output packed is selected, path is '{0}'.", outputPackedPath); + } + else + { + m_BuildReport.LogInfo("Output packed is not selected."); + } + + // Clean working path + List validNames = new List(); + foreach (ResourceData assetBundleResourceData in assetBundleResourceDatas) + { + validNames.Add(GetResourceFullName(assetBundleResourceData.Name, assetBundleResourceData.Variant).ToLowerInvariant()); + } + + if (Directory.Exists(workingPath)) + { + Uri workingUri = new Uri(workingPath, UriKind.Absolute); + string[] fileNames = Directory.GetFiles(workingPath, "*", SearchOption.AllDirectories); + foreach (string fileName in fileNames) + { + if (fileName.EndsWith(".manifest", StringComparison.Ordinal)) + { + continue; + } + + string relativeName = workingUri.MakeRelativeUri(new Uri(fileName, UriKind.Absolute)).ToString(); + if (!validNames.Contains(relativeName)) + { + File.Delete(fileName); + } + } + + string[] manifestNames = Directory.GetFiles(workingPath, "*.manifest", SearchOption.AllDirectories); + foreach (string manifestName in manifestNames) + { + if (!File.Exists(manifestName.Substring(0, manifestName.LastIndexOf('.')))) + { + File.Delete(manifestName); + } + } + + Utility.Path.RemoveEmptyDirectory(workingPath); + } + + if (!Directory.Exists(workingPath)) + { + Directory.CreateDirectory(workingPath); + } + + if (m_BuildEventHandler != null) + { + m_BuildReport.LogInfo("Execute build event handler 'OnPreprocessPlatform' for '{0}'...", platformName); + m_BuildEventHandler.OnPreprocessPlatform(platform, workingPath, OutputPackageSelected, outputPackagePath, OutputFullSelected, outputFullPath, OutputPackedSelected, outputPackedPath); + } + + // Build AssetBundles + m_BuildReport.LogInfo("Unity start build asset bundles for '{0}'...", platformName); + AssetBundleManifest assetBundleManifest = BuildPipeline.BuildAssetBundles(workingPath, assetBundleBuildDatas, buildAssetBundleOptions, GetBuildTarget(platform)); + if (assetBundleManifest == null) + { + m_BuildReport.LogError("Build asset bundles for '{0}' failure.", platformName); + + if (m_BuildEventHandler != null) + { + m_BuildReport.LogInfo("Execute build event handler 'OnPostprocessPlatform' for '{0}'...", platformName); + m_BuildEventHandler.OnPostprocessPlatform(platform, workingPath, OutputPackageSelected, outputPackagePath, OutputFullSelected, outputFullPath, OutputPackedSelected, outputPackedPath, false); + } + + return false; + } + + if (m_BuildEventHandler != null) + { + m_BuildReport.LogInfo("Execute build event handler 'OnBuildAssetBundlesComplete' for '{0}'...", platformName); + m_BuildEventHandler.OnBuildAssetBundlesComplete(platform, workingPath, OutputPackageSelected, outputPackagePath, OutputFullSelected, outputFullPath, OutputPackedSelected, outputPackedPath, assetBundleManifest); + } + + m_BuildReport.LogInfo("Unity build asset bundles for '{0}' complete.", platformName); + + // Create FileSystems + m_BuildReport.LogInfo("Start create file system for '{0}'...", platformName); + + if (OutputPackageSelected) + { + CreateFileSystems(m_ResourceDatas.Values, outputPackagePath, m_OutputPackageFileSystems); + } + + if (OutputPackedSelected) + { + CreateFileSystems(GetPackedResourceDatas(), outputPackedPath, m_OutputPackedFileSystems); + } + + m_BuildReport.LogInfo("Create file system for '{0}' complete.", platformName); + + // Process AssetBundles + for (int i = 0; i < assetBundleResourceDatas.Length; i++) + { + string fullName = GetResourceFullName(assetBundleResourceDatas[i].Name, assetBundleResourceDatas[i].Variant); + if (ProcessingAssetBundle != null) + { + if (ProcessingAssetBundle(fullName, (float)(i + 1) / assetBundleResourceDatas.Length)) + { + m_BuildReport.LogWarning("The build has been canceled by user."); + + if (m_BuildEventHandler != null) + { + m_BuildReport.LogInfo("Execute build event handler 'OnPostprocessPlatform' for '{0}'...", platformName); + m_BuildEventHandler.OnPostprocessPlatform(platform, workingPath, OutputPackageSelected, outputPackagePath, OutputFullSelected, outputFullPath, OutputPackedSelected, outputPackedPath, false); + } + + return false; + } + } + + m_BuildReport.LogInfo("Start process asset bundle '{0}' for '{1}'...", fullName, platformName); + + if (!ProcessAssetBundle(platform, workingPath, outputPackagePath, outputFullPath, outputPackedPath, AdditionalCompressionSelected, assetBundleResourceDatas[i].Name, assetBundleResourceDatas[i].Variant, assetBundleResourceDatas[i].FileSystem)) + { + return false; + } + + m_BuildReport.LogInfo("Process asset bundle '{0}' for '{1}' complete.", fullName, platformName); + } + + // Process Binaries + for (int i = 0; i < binaryResourceDatas.Length; i++) + { + string fullName = GetResourceFullName(binaryResourceDatas[i].Name, binaryResourceDatas[i].Variant); + if (ProcessingBinary != null) + { + if (ProcessingBinary(fullName, (float)(i + 1) / binaryResourceDatas.Length)) + { + m_BuildReport.LogWarning("The build has been canceled by user."); + + if (m_BuildEventHandler != null) + { + m_BuildReport.LogInfo("Execute build event handler 'OnPostprocessPlatform' for '{0}'...", platformName); + m_BuildEventHandler.OnPostprocessPlatform(platform, workingPath, OutputPackageSelected, outputPackagePath, OutputFullSelected, outputFullPath, OutputPackedSelected, outputPackedPath, false); + } + + return false; + } + } + + m_BuildReport.LogInfo("Start process binary '{0}' for '{1}'...", fullName, platformName); + + if (!ProcessBinary(platform, workingPath, outputPackagePath, outputFullPath, outputPackedPath, AdditionalCompressionSelected, binaryResourceDatas[i].Name, binaryResourceDatas[i].Variant, binaryResourceDatas[i].FileSystem)) + { + return false; + } + + m_BuildReport.LogInfo("Process binary '{0}' for '{1}' complete.", fullName, platformName); + } + + if (OutputPackageSelected) + { + ProcessPackageVersionList(outputPackagePath, platform); + m_BuildReport.LogInfo("Process package version list for '{0}' complete.", platformName); + } + + if (OutputFullSelected) + { + VersionListData versionListData = ProcessUpdatableVersionList(outputFullPath, platform); + m_BuildReport.LogInfo("Process updatable version list for '{0}' complete, updatable version list path is '{1}', length is '{2}', hash code is '{3}[0x{3:X8}]', compressed length is '{4}', compressed hash code is '{5}[0x{5:X8}]'.", platformName, versionListData.Path, versionListData.Length, versionListData.HashCode, versionListData.CompressedLength, versionListData.CompressedHashCode); + if (m_BuildEventHandler != null) + { + m_BuildReport.LogInfo("Execute build event handler 'OnOutputUpdatableVersionListData' for '{0}'...", platformName); + m_BuildEventHandler.OnOutputUpdatableVersionListData(platform, versionListData.Path, versionListData.Length, versionListData.HashCode, versionListData.CompressedLength, versionListData.CompressedHashCode); + } + } + + if (OutputPackedSelected) + { + ProcessReadOnlyVersionList(outputPackedPath, platform); + m_BuildReport.LogInfo("Process read-only version list for '{0}' complete.", platformName); + } + + if (m_BuildEventHandler != null) + { + m_BuildReport.LogInfo("Execute build event handler 'OnPostprocessPlatform' for '{0}'...", platformName); + m_BuildEventHandler.OnPostprocessPlatform(platform, workingPath, OutputPackageSelected, outputPackagePath, OutputFullSelected, outputFullPath, OutputPackedSelected, outputPackedPath, true); + } + + if (ProcessResourceComplete != null) + { + ProcessResourceComplete(platform); + } + + m_BuildReport.LogInfo("Build resources for '{0}' success.", platformName); + return true; + } + + private bool ProcessAssetBundle(Platform platform, string workingPath, string outputPackagePath, string outputFullPath, string outputPackedPath, bool additionalCompressionSelected, string name, string variant, string fileSystem) + { + string fullName = GetResourceFullName(name, variant); + ResourceData resourceData = m_ResourceDatas[fullName]; + string workingName = Utility.Path.GetRegularPath(Path.Combine(workingPath, fullName.ToLowerInvariant())); + + byte[] bytes = File.ReadAllBytes(workingName); + int length = bytes.Length; + int hashCode = Utility.Verifier.GetCrc32(bytes); + int compressedLength = length; + int compressedHashCode = hashCode; + + byte[] hashBytes = Utility.Converter.GetBytes(hashCode); + if (resourceData.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt) + { + bytes = Utility.Encryption.GetQuickXorBytes(bytes, hashBytes); + } + else if (resourceData.LoadType == LoadType.LoadFromMemoryAndDecrypt) + { + bytes = Utility.Encryption.GetXorBytes(bytes, hashBytes); + } + + return ProcessOutput(platform, outputPackagePath, outputFullPath, outputPackedPath, additionalCompressionSelected, name, variant, fileSystem, resourceData, bytes, length, hashCode, compressedLength, compressedHashCode); + } + + private bool ProcessBinary(Platform platform, string workingPath, string outputPackagePath, string outputFullPath, string outputPackedPath, bool additionalCompressionSelected, string name, string variant, string fileSystem) + { + string fullName = GetResourceFullName(name, variant); + ResourceData resourceData = m_ResourceDatas[fullName]; + string assetName = resourceData.GetAssetNames()[0]; + string assetPath = Utility.Path.GetRegularPath(Application.dataPath.Substring(0, Application.dataPath.Length - AssetsStringLength) + assetName); + + byte[] bytes = File.ReadAllBytes(assetPath); + int length = bytes.Length; + int hashCode = Utility.Verifier.GetCrc32(bytes); + int compressedLength = length; + int compressedHashCode = hashCode; + + byte[] hashBytes = Utility.Converter.GetBytes(hashCode); + if (resourceData.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt) + { + bytes = Utility.Encryption.GetQuickXorBytes(bytes, hashBytes); + } + else if (resourceData.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + bytes = Utility.Encryption.GetXorBytes(bytes, hashBytes); + } + + return ProcessOutput(platform, outputPackagePath, outputFullPath, outputPackedPath, additionalCompressionSelected, name, variant, fileSystem, resourceData, bytes, length, hashCode, compressedLength, compressedHashCode); + } + + private void ProcessPackageVersionList(string outputPackagePath, Platform platform) + { + Asset[] originalAssets = m_ResourceCollection.GetAssets(); + PackageVersionList.Asset[] assets = new PackageVersionList.Asset[originalAssets.Length]; + for (int i = 0; i < assets.Length; i++) + { + Asset originalAsset = originalAssets[i]; + assets[i] = new PackageVersionList.Asset(originalAsset.Name, GetDependencyAssetIndexes(originalAsset.Name)); + } + + SortedDictionary.ValueCollection resourceDatas = m_ResourceDatas.Values; + + int index = 0; + PackageVersionList.Resource[] resources = new PackageVersionList.Resource[m_ResourceCollection.ResourceCount]; + foreach (ResourceData resourceData in resourceDatas) + { + ResourceCode resourceCode = resourceData.GetCode(platform); + resources[index++] = new PackageVersionList.Resource(resourceData.Name, resourceData.Variant, GetExtension(resourceData), (byte)resourceData.LoadType, resourceCode.Length, resourceCode.HashCode, GetAssetIndexes(resourceData)); + } + + string[] fileSystemNames = GetFileSystemNames(resourceDatas); + PackageVersionList.FileSystem[] fileSystems = new PackageVersionList.FileSystem[fileSystemNames.Length]; + for (int i = 0; i < fileSystems.Length; i++) + { + fileSystems[i] = new PackageVersionList.FileSystem(fileSystemNames[i], GetResourceIndexesFromFileSystem(resourceDatas, fileSystemNames[i])); + } + + string[] resourceGroupNames = GetResourceGroupNames(resourceDatas); + PackageVersionList.ResourceGroup[] resourceGroups = new PackageVersionList.ResourceGroup[resourceGroupNames.Length]; + for (int i = 0; i < resourceGroups.Length; i++) + { + resourceGroups[i] = new PackageVersionList.ResourceGroup(resourceGroupNames[i], GetResourceIndexesFromResourceGroup(resourceDatas, resourceGroupNames[i])); + } + + PackageVersionList versionList = new PackageVersionList(ApplicableGameVersion, InternalResourceVersion, assets, resources, fileSystems, resourceGroups); + PackageVersionListSerializer serializer = new PackageVersionListSerializer(); + serializer.RegisterSerializeCallback(0, BuiltinVersionListSerializer.PackageVersionListSerializeCallback_V0); + serializer.RegisterSerializeCallback(1, BuiltinVersionListSerializer.PackageVersionListSerializeCallback_V1); + serializer.RegisterSerializeCallback(2, BuiltinVersionListSerializer.PackageVersionListSerializeCallback_V2); + string packageVersionListPath = Utility.Path.GetRegularPath(Path.Combine(outputPackagePath, RemoteVersionListFileName)); + using (FileStream fileStream = new FileStream(packageVersionListPath, FileMode.Create, FileAccess.Write)) + { + if (!serializer.Serialize(fileStream, versionList)) + { + throw new GameFrameworkException("Serialize package version list failure."); + } + } + } + + private VersionListData ProcessUpdatableVersionList(string outputFullPath, Platform platform) + { + Asset[] originalAssets = m_ResourceCollection.GetAssets(); + UpdatableVersionList.Asset[] assets = new UpdatableVersionList.Asset[originalAssets.Length]; + for (int i = 0; i < assets.Length; i++) + { + Asset originalAsset = originalAssets[i]; + assets[i] = new UpdatableVersionList.Asset(originalAsset.Name, GetDependencyAssetIndexes(originalAsset.Name)); + } + + SortedDictionary.ValueCollection resourceDatas = m_ResourceDatas.Values; + + int index = 0; + UpdatableVersionList.Resource[] resources = new UpdatableVersionList.Resource[m_ResourceCollection.ResourceCount]; + foreach (ResourceData resourceData in resourceDatas) + { + ResourceCode resourceCode = resourceData.GetCode(platform); + resources[index++] = new UpdatableVersionList.Resource(resourceData.Name, resourceData.Variant, GetExtension(resourceData), (byte)resourceData.LoadType, resourceCode.Length, resourceCode.HashCode, resourceCode.CompressedLength, resourceCode.CompressedHashCode, GetAssetIndexes(resourceData)); + } + + string[] fileSystemNames = GetFileSystemNames(resourceDatas); + UpdatableVersionList.FileSystem[] fileSystems = new UpdatableVersionList.FileSystem[fileSystemNames.Length]; + for (int i = 0; i < fileSystems.Length; i++) + { + fileSystems[i] = new UpdatableVersionList.FileSystem(fileSystemNames[i], GetResourceIndexesFromFileSystem(resourceDatas, fileSystemNames[i])); + } + + string[] resourceGroupNames = GetResourceGroupNames(resourceDatas); + UpdatableVersionList.ResourceGroup[] resourceGroups = new UpdatableVersionList.ResourceGroup[resourceGroupNames.Length]; + for (int i = 0; i < resourceGroups.Length; i++) + { + resourceGroups[i] = new UpdatableVersionList.ResourceGroup(resourceGroupNames[i], GetResourceIndexesFromResourceGroup(resourceDatas, resourceGroupNames[i])); + } + + UpdatableVersionList versionList = new UpdatableVersionList(ApplicableGameVersion, InternalResourceVersion, assets, resources, fileSystems, resourceGroups); + UpdatableVersionListSerializer serializer = new UpdatableVersionListSerializer(); + serializer.RegisterSerializeCallback(0, BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback_V0); + serializer.RegisterSerializeCallback(1, BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback_V1); + serializer.RegisterSerializeCallback(2, BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback_V2); + string updatableVersionListPath = Utility.Path.GetRegularPath(Path.Combine(outputFullPath, RemoteVersionListFileName)); + using (FileStream fileStream = new FileStream(updatableVersionListPath, FileMode.Create, FileAccess.Write)) + { + if (!serializer.Serialize(fileStream, versionList)) + { + throw new GameFrameworkException("Serialize updatable version list failure."); + } + } + + byte[] bytes = File.ReadAllBytes(updatableVersionListPath); + int length = bytes.Length; + int hashCode = Utility.Verifier.GetCrc32(bytes); + bytes = Utility.Compression.Compress(bytes); + int compressedLength = bytes.Length; + File.WriteAllBytes(updatableVersionListPath, bytes); + int compressedHashCode = Utility.Verifier.GetCrc32(bytes); + int dotPosition = RemoteVersionListFileName.LastIndexOf('.'); + string versionListFullNameWithCrc32 = Utility.Text.Format("{0}.{2:x8}.{1}", RemoteVersionListFileName.Substring(0, dotPosition), RemoteVersionListFileName.Substring(dotPosition + 1), hashCode); + string updatableVersionListPathWithCrc32 = Utility.Path.GetRegularPath(Path.Combine(outputFullPath, versionListFullNameWithCrc32)); + File.Move(updatableVersionListPath, updatableVersionListPathWithCrc32); + + return new VersionListData(updatableVersionListPathWithCrc32, length, hashCode, compressedLength, compressedHashCode); + } + + private void ProcessReadOnlyVersionList(string outputPackedPath, Platform platform) + { + ResourceData[] packedResourceDatas = GetPackedResourceDatas(); + + LocalVersionList.Resource[] resources = new LocalVersionList.Resource[packedResourceDatas.Length]; + for (int i = 0; i < resources.Length; i++) + { + ResourceData resourceData = packedResourceDatas[i]; + ResourceCode resourceCode = resourceData.GetCode(platform); + resources[i] = new LocalVersionList.Resource(resourceData.Name, resourceData.Variant, GetExtension(resourceData), (byte)resourceData.LoadType, resourceCode.Length, resourceCode.HashCode); + } + + string[] packedFileSystemNames = GetFileSystemNames(packedResourceDatas); + LocalVersionList.FileSystem[] fileSystems = new LocalVersionList.FileSystem[packedFileSystemNames.Length]; + for (int i = 0; i < fileSystems.Length; i++) + { + fileSystems[i] = new LocalVersionList.FileSystem(packedFileSystemNames[i], GetResourceIndexesFromFileSystem(packedResourceDatas, packedFileSystemNames[i])); + } + + LocalVersionList versionList = new LocalVersionList(resources, fileSystems); + ReadOnlyVersionListSerializer serializer = new ReadOnlyVersionListSerializer(); + serializer.RegisterSerializeCallback(0, BuiltinVersionListSerializer.LocalVersionListSerializeCallback_V0); + serializer.RegisterSerializeCallback(1, BuiltinVersionListSerializer.LocalVersionListSerializeCallback_V1); + serializer.RegisterSerializeCallback(2, BuiltinVersionListSerializer.LocalVersionListSerializeCallback_V2); + string readOnlyVersionListPath = Utility.Path.GetRegularPath(Path.Combine(outputPackedPath, LocalVersionListFileName)); + using (FileStream fileStream = new FileStream(readOnlyVersionListPath, FileMode.Create, FileAccess.Write)) + { + if (!serializer.Serialize(fileStream, versionList)) + { + throw new GameFrameworkException("Serialize read-only version list failure."); + } + } + } + + private int[] GetDependencyAssetIndexes(string assetName) + { + List dependencyAssetIndexes = new List(); + Asset[] assets = m_ResourceCollection.GetAssets(); + DependencyData dependencyData = m_ResourceAnalyzerController.GetDependencyData(assetName); + foreach (Asset dependencyAsset in dependencyData.GetDependencyAssets()) + { + for (int i = 0; i < assets.Length; i++) + { + if (assets[i] == dependencyAsset) + { + dependencyAssetIndexes.Add(i); + break; + } + } + } + + dependencyAssetIndexes.Sort(); + return dependencyAssetIndexes.ToArray(); + } + + private int[] GetAssetIndexes(ResourceData resourceData) + { + Asset[] assets = m_ResourceCollection.GetAssets(); + string[] assetGuids = resourceData.GetAssetGuids(); + int[] assetIndexes = new int[assetGuids.Length]; + for (int i = 0; i < assetGuids.Length; i++) + { + assetIndexes[i] = Array.BinarySearch(assets, m_ResourceCollection.GetAsset(assetGuids[i])); + if (assetIndexes[i] < 0) + { + throw new GameFrameworkException("Asset is invalid."); + } + } + + return assetIndexes; + } + + private ResourceData[] GetPackedResourceDatas() + { + List packedResourceDatas = new List(); + foreach (ResourceData resourceData in m_ResourceDatas.Values) + { + if (!resourceData.Packed) + { + continue; + } + + packedResourceDatas.Add(resourceData); + } + + return packedResourceDatas.ToArray(); + } + + private string[] GetFileSystemNames(IEnumerable resourceDatas) + { + HashSet fileSystemNames = new HashSet(); + foreach (ResourceData resourceData in resourceDatas) + { + if (resourceData.FileSystem == null) + { + continue; + } + + fileSystemNames.Add(resourceData.FileSystem); + } + + return fileSystemNames.OrderBy(x => x).ToArray(); + } + + private int[] GetResourceIndexesFromFileSystem(IEnumerable resourceDatas, string fileSystemName) + { + int index = 0; + List resourceIndexes = new List(); + foreach (ResourceData resourceData in resourceDatas) + { + if (resourceData.FileSystem == fileSystemName) + { + resourceIndexes.Add(index); + } + + index++; + } + + resourceIndexes.Sort(); + return resourceIndexes.ToArray(); + } + + private string[] GetResourceGroupNames(IEnumerable resourceDatas) + { + HashSet resourceGroupNames = new HashSet(); + foreach (ResourceData resourceData in resourceDatas) + { + foreach (string resourceGroup in resourceData.GetResourceGroups()) + { + resourceGroupNames.Add(resourceGroup); + } + } + + return resourceGroupNames.OrderBy(x => x).ToArray(); + } + + private int[] GetResourceIndexesFromResourceGroup(IEnumerable resourceDatas, string resourceGroupName) + { + int index = 0; + List resourceIndexes = new List(); + foreach (ResourceData resourceData in resourceDatas) + { + foreach (string resourceGroup in resourceData.GetResourceGroups()) + { + if (resourceGroup == resourceGroupName) + { + resourceIndexes.Add(index); + break; + } + } + + index++; + } + + resourceIndexes.Sort(); + return resourceIndexes.ToArray(); + } + + private void CreateFileSystems(IEnumerable resourceDatas, string outputPath, Dictionary outputFileSystem) + { + outputFileSystem.Clear(); + string[] fileSystemNames = GetFileSystemNames(resourceDatas); + if (fileSystemNames.Length > 0 && m_FileSystemManager == null) + { + m_FileSystemManager = GameFrameworkEntry.GetModule(); + m_FileSystemManager.SetFileSystemHelper(new FileSystemHelper()); + } + + foreach (string fileSystemName in fileSystemNames) + { + int fileCount = GetResourceIndexesFromFileSystem(resourceDatas, fileSystemName).Length; + string fullPath = Utility.Path.GetRegularPath(Path.Combine(outputPath, Utility.Text.Format("{0}.{1}", fileSystemName, DefaultExtension))); + string directory = Path.GetDirectoryName(fullPath); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + IFileSystem fileSystem = m_FileSystemManager.CreateFileSystem(fullPath, FileSystemAccess.Write, fileCount, fileCount); + outputFileSystem.Add(fileSystemName, fileSystem); + } + } + + private bool ProcessOutput(Platform platform, string outputPackagePath, string outputFullPath, string outputPackedPath, bool additionalCompressionSelected, string name, string variant, string fileSystem, ResourceData resourceData, byte[] bytes, int length, int hashCode, int compressedLength, int compressedHashCode) + { + string fullNameWithExtension = Utility.Text.Format("{0}.{1}", GetResourceFullName(name, variant), GetExtension(resourceData)); + + if (OutputPackageSelected) + { + if (string.IsNullOrEmpty(fileSystem)) + { + string packagePath = Utility.Path.GetRegularPath(Path.Combine(outputPackagePath, fullNameWithExtension)); + string packageDirectoryName = Path.GetDirectoryName(packagePath); + if (!Directory.Exists(packageDirectoryName)) + { + Directory.CreateDirectory(packageDirectoryName); + } + + File.WriteAllBytes(packagePath, bytes); + } + else + { + if (!m_OutputPackageFileSystems[fileSystem].WriteFile(fullNameWithExtension, bytes)) + { + return false; + } + } + } + + if (OutputPackedSelected && resourceData.Packed) + { + if (string.IsNullOrEmpty(fileSystem)) + { + string packedPath = Utility.Path.GetRegularPath(Path.Combine(outputPackedPath, fullNameWithExtension)); + string packedDirectoryName = Path.GetDirectoryName(packedPath); + if (!Directory.Exists(packedDirectoryName)) + { + Directory.CreateDirectory(packedDirectoryName); + } + + File.WriteAllBytes(packedPath, bytes); + } + else + { + if (!m_OutputPackedFileSystems[fileSystem].WriteFile(fullNameWithExtension, bytes)) + { + return false; + } + } + } + + if (OutputFullSelected) + { + string fullNameWithCrc32AndExtension = variant != null ? Utility.Text.Format("{0}.{1}.{2:x8}.{3}", name, variant, hashCode, DefaultExtension) : Utility.Text.Format("{0}.{1:x8}.{2}", name, hashCode, DefaultExtension); + string fullPath = Utility.Path.GetRegularPath(Path.Combine(outputFullPath, fullNameWithCrc32AndExtension)); + string fullDirectoryName = Path.GetDirectoryName(fullPath); + if (!Directory.Exists(fullDirectoryName)) + { + Directory.CreateDirectory(fullDirectoryName); + } + + if (additionalCompressionSelected) + { + byte[] compressedBytes = Utility.Compression.Compress(bytes); + compressedLength = compressedBytes.Length; + compressedHashCode = Utility.Verifier.GetCrc32(compressedBytes); + File.WriteAllBytes(fullPath, compressedBytes); + } + else + { + File.WriteAllBytes(fullPath, bytes); + } + } + + resourceData.AddCode(platform, length, hashCode, compressedLength, compressedHashCode); + return true; + } + + private BuildAssetBundleOptions GetBuildAssetBundleOptions() + { + BuildAssetBundleOptions buildOptions = BuildAssetBundleOptions.None; + + if (ForceRebuildAssetBundleSelected) + { + buildOptions |= BuildAssetBundleOptions.ForceRebuildAssetBundle; + } + + if (AssetBundleCompression == AssetBundleCompressionType.Uncompressed) + { + buildOptions |= BuildAssetBundleOptions.UncompressedAssetBundle; + } + else if (AssetBundleCompression == AssetBundleCompressionType.LZ4) + { + buildOptions |= BuildAssetBundleOptions.ChunkBasedCompression; + } + + return buildOptions; + } + + private bool PrepareBuildData(out AssetBundleBuild[] assetBundleBuildDatas, out ResourceData[] assetBundleResourceDatas, out ResourceData[] binaryResourceDatas) + { + assetBundleBuildDatas = null; + assetBundleResourceDatas = null; + binaryResourceDatas = null; + m_ResourceDatas.Clear(); + + Resource[] resources = m_ResourceCollection.GetResources(); + foreach (Resource resource in resources) + { + m_ResourceDatas.Add(resource.FullName, new ResourceData(resource.Name, resource.Variant, resource.FileSystem, resource.LoadType, resource.Packed, resource.GetResourceGroups())); + } + + Asset[] assets = m_ResourceCollection.GetAssets(); + foreach (Asset asset in assets) + { + string assetName = asset.Name; + if (string.IsNullOrEmpty(assetName)) + { + m_BuildReport.LogError("Can not find asset by guid '{0}'.", asset.Guid); + return false; + } + + string assetFileFullName = Application.dataPath.Substring(0, Application.dataPath.Length - AssetsStringLength) + assetName; + if (!File.Exists(assetFileFullName)) + { + m_BuildReport.LogError("Can not find asset '{0}'.", assetFileFullName); + return false; + } + + byte[] assetBytes = File.ReadAllBytes(assetFileFullName); + int assetHashCode = Utility.Verifier.GetCrc32(assetBytes); + + List dependencyAssetNames = new List(); + DependencyData dependencyData = m_ResourceAnalyzerController.GetDependencyData(assetName); + Asset[] dependencyAssets = dependencyData.GetDependencyAssets(); + foreach (Asset dependencyAsset in dependencyAssets) + { + dependencyAssetNames.Add(dependencyAsset.Name); + } + + dependencyAssetNames.Sort(); + + m_ResourceDatas[asset.Resource.FullName].AddAssetData(asset.Guid, assetName, assetBytes.Length, assetHashCode, dependencyAssetNames.ToArray()); + } + + List assetBundleBuildDataList = new List(); + List assetBundleResourceDataList = new List(); + List binaryResourceDataList = new List(); + foreach (ResourceData resourceData in m_ResourceDatas.Values) + { + if (resourceData.AssetCount <= 0) + { + m_BuildReport.LogError("Resource '{0}' has no asset.", GetResourceFullName(resourceData.Name, resourceData.Variant)); + return false; + } + + if (resourceData.IsLoadFromBinary) + { + binaryResourceDataList.Add(resourceData); + } + else + { + assetBundleResourceDataList.Add(resourceData); + + AssetBundleBuild build = new AssetBundleBuild(); + build.assetBundleName = resourceData.Name; + build.assetBundleVariant = resourceData.Variant; + build.assetNames = resourceData.GetAssetNames(); + assetBundleBuildDataList.Add(build); + } + } + + assetBundleBuildDatas = assetBundleBuildDataList.ToArray(); + assetBundleResourceDatas = assetBundleResourceDataList.ToArray(); + binaryResourceDatas = binaryResourceDataList.ToArray(); + return true; + } + + private static string GetResourceFullName(string name, string variant) + { + return !string.IsNullOrEmpty(variant) ? Utility.Text.Format("{0}.{1}", name, variant) : name; + } + + private static BuildTarget GetBuildTarget(Platform platform) + { + switch (platform) + { + case Platform.Windows: + return BuildTarget.StandaloneWindows; + + case Platform.Windows64: + return BuildTarget.StandaloneWindows64; + + case Platform.MacOS: +#if UNITY_2017_3_OR_NEWER + return BuildTarget.StandaloneOSX; +#else + return BuildTarget.StandaloneOSXUniversal; +#endif + case Platform.Linux: + return BuildTarget.StandaloneLinux64; + + case Platform.IOS: + return BuildTarget.iOS; + + case Platform.Android: + return BuildTarget.Android; + + case Platform.WindowsStore: + return BuildTarget.WSAPlayer; + + case Platform.WebGL: + return BuildTarget.WebGL; + + default: + throw new GameFrameworkException("Platform is invalid."); + } + } + + private static string GetExtension(ResourceData data) + { + if (data.IsLoadFromBinary) + { + string assetName = data.GetAssetNames()[0]; + int position = assetName.LastIndexOf('.'); + if (position >= 0) + { + return assetName.Substring(position + 1); + } + } + + return DefaultExtension; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.cs.meta new file mode 100644 index 0000000..4bd0398 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceBuilder/ResourceBuilderController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2678da0502f5874429b8bce3d35f573f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection.meta new file mode 100644 index 0000000..80df7f1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bc804e13da19ff043aac07751e249b43 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/Asset.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/Asset.cs new file mode 100644 index 0000000..fa7c54c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/Asset.cs @@ -0,0 +1,59 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using UnityEditor; + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// 资源。 + /// + public sealed class Asset : IComparable + { + private Asset(string guid, Resource resource) + { + Guid = guid; + Resource = resource; + } + + public string Guid + { + get; + private set; + } + + public string Name + { + get + { + return AssetDatabase.GUIDToAssetPath(Guid); + } + } + + public Resource Resource + { + get; + set; + } + + public int CompareTo(Asset asset) + { + return string.Compare(Guid, asset.Guid, StringComparison.Ordinal); + } + + public static Asset Create(string guid) + { + return new Asset(guid, null); + } + + public static Asset Create(string guid, Resource resource) + { + return new Asset(guid, resource); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/Asset.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/Asset.cs.meta new file mode 100644 index 0000000..c983873 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/Asset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f0147356ab2aa7548b5448288d785afe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/AssetType.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/AssetType.cs new file mode 100644 index 0000000..1259b6c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/AssetType.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// 资源类型。 + /// + public enum AssetType : byte + { + /// + /// 未知。 + /// + Unknown = 0, + + /// + /// 存放资源。 + /// + Asset, + + /// + /// 存放场景。 + /// + Scene, + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/AssetType.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/AssetType.cs.meta new file mode 100644 index 0000000..ead3459 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/AssetType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ca96b555ae5b2c34e8cc830446f11525 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/LoadType.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/LoadType.cs new file mode 100644 index 0000000..8cec7db --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/LoadType.cs @@ -0,0 +1,50 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// 资源加载方式类型。 + /// + public enum LoadType : byte + { + /// + /// 使用文件方式加载。 + /// + LoadFromFile = 0, + + /// + /// 使用内存方式加载。 + /// + LoadFromMemory, + + /// + /// 使用内存快速解密方式加载。 + /// + LoadFromMemoryAndQuickDecrypt, + + /// + /// 使用内存解密方式加载。 + /// + LoadFromMemoryAndDecrypt, + + /// + /// 使用二进制方式加载。 + /// + LoadFromBinary, + + /// + /// 使用二进制快速解密方式加载。 + /// + LoadFromBinaryAndQuickDecrypt, + + /// + /// 使用二进制解密方式加载。 + /// + LoadFromBinaryAndDecrypt + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/LoadType.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/LoadType.cs.meta new file mode 100644 index 0000000..df7e038 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/LoadType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f5660cbfaa767b84fbc1ef8799919b26 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/Resource.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/Resource.cs new file mode 100644 index 0000000..645b182 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/Resource.cs @@ -0,0 +1,209 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System.Collections.Generic; + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// 资源。 + /// + public sealed class Resource + { + private readonly List m_Assets; + private readonly List m_ResourceGroups; + + private Resource(string name, string variant, string fileSystem, LoadType loadType, bool packed, string[] resourceGroups) + { + m_Assets = new List(); + m_ResourceGroups = new List(); + + Name = name; + Variant = variant; + AssetType = AssetType.Unknown; + FileSystem = fileSystem; + LoadType = loadType; + Packed = packed; + + foreach (string resourceGroup in resourceGroups) + { + AddResourceGroup(resourceGroup); + } + } + + public string Name + { + get; + private set; + } + + public string Variant + { + get; + private set; + } + + public string FullName + { + get + { + return Variant != null ? Utility.Text.Format("{0}.{1}", Name, Variant) : Name; + } + } + + public AssetType AssetType + { + get; + private set; + } + + public bool IsLoadFromBinary + { + get + { + return LoadType == LoadType.LoadFromBinary || LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || LoadType == LoadType.LoadFromBinaryAndDecrypt; + } + } + + public string FileSystem + { + get; + set; + } + + public LoadType LoadType + { + get; + set; + } + + public bool Packed + { + get; + set; + } + + public static Resource Create(string name, string variant, string fileSystem, LoadType loadType, bool packed, string[] resourceGroups) + { + return new Resource(name, variant, fileSystem, loadType, packed, resourceGroups ?? new string[0]); + } + + public Asset[] GetAssets() + { + return m_Assets.ToArray(); + } + + public Asset GetFirstAsset() + { + return m_Assets.Count > 0 ? m_Assets[0] : null; + } + + public void Rename(string name, string variant) + { + Name = name; + Variant = variant; + } + + public void AssignAsset(Asset asset, bool isScene) + { + if (asset.Resource != null) + { + asset.Resource.UnassignAsset(asset); + } + + AssetType = isScene ? AssetType.Scene : AssetType.Asset; + asset.Resource = this; + m_Assets.Add(asset); + m_Assets.Sort(AssetComparer); + } + + public void UnassignAsset(Asset asset) + { + asset.Resource = null; + m_Assets.Remove(asset); + if (m_Assets.Count <= 0) + { + AssetType = AssetType.Unknown; + } + } + + public string[] GetResourceGroups() + { + return m_ResourceGroups.ToArray(); + } + + public bool HasResourceGroup(string resourceGroup) + { + if (string.IsNullOrEmpty(resourceGroup)) + { + return false; + } + + return m_ResourceGroups.Contains(resourceGroup); + } + + public void AddResourceGroup(string resourceGroup) + { + if (string.IsNullOrEmpty(resourceGroup)) + { + return; + } + + if (m_ResourceGroups.Contains(resourceGroup)) + { + return; + } + + m_ResourceGroups.Add(resourceGroup); + m_ResourceGroups.Sort(); + } + + public void SetDefaultResourceGroup(string defaultResourceGroup) + { + if (string.IsNullOrEmpty(defaultResourceGroup)) + { + return; + } + + if (m_ResourceGroups.Count <= 0) + { + m_ResourceGroups.Add(defaultResourceGroup); + } + else + { + m_ResourceGroups[0] = defaultResourceGroup; + } + } + + public bool RemoveResourceGroup(string resourceGroup) + { + if (string.IsNullOrEmpty(resourceGroup)) + { + return false; + } + + return m_ResourceGroups.Remove(resourceGroup); + } + + public void Clear() + { + foreach (Asset asset in m_Assets) + { + asset.Resource = null; + } + + m_Assets.Clear(); + m_ResourceGroups.Clear(); + } + + private int AssetComparer(Asset a, Asset b) + { + return a.Guid.CompareTo(b.Guid); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/Resource.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/Resource.cs.meta new file mode 100644 index 0000000..b4b12ad --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/Resource.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2d3d5c5d16bedc54c976247a6a5b429e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/ResourceCollection.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/ResourceCollection.cs new file mode 100644 index 0000000..75d6bfb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/ResourceCollection.cs @@ -0,0 +1,635 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Xml; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// 资源集合。 + /// + public sealed class ResourceCollection + { + private const string SceneExtension = ".unity"; + private static readonly Regex ResourceNameRegex = new Regex(@"^([A-Za-z0-9\._-]+/)*[A-Za-z0-9\._-]+$"); + private static readonly Regex ResourceVariantRegex = new Regex(@"^[a-z0-9_-]+$"); + + private readonly string m_ConfigurationPath; + private readonly SortedDictionary m_Resources; + private readonly SortedDictionary m_Assets; + + public ResourceCollection() + { + m_ConfigurationPath = Type.GetConfigurationPath() ?? Utility.Path.GetRegularPath(Path.Combine(Application.dataPath, "GameFramework/Configs/ResourceCollection.xml")); + m_Resources = new SortedDictionary(StringComparer.Ordinal); + m_Assets = new SortedDictionary(StringComparer.Ordinal); + } + + public int ResourceCount + { + get + { + return m_Resources.Count; + } + } + + public int AssetCount + { + get + { + return m_Assets.Count; + } + } + + public event GameFrameworkAction OnLoadingResource = null; + + public event GameFrameworkAction OnLoadingAsset = null; + + public event GameFrameworkAction OnLoadCompleted = null; + + public void Clear() + { + m_Resources.Clear(); + m_Assets.Clear(); + } + + public bool Load() + { + Clear(); + + if (!File.Exists(m_ConfigurationPath)) + { + return false; + } + + try + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load(m_ConfigurationPath); + XmlNode xmlRoot = xmlDocument.SelectSingleNode("UnityGameFramework"); + XmlNode xmlCollection = xmlRoot.SelectSingleNode("ResourceCollection"); + XmlNode xmlResources = xmlCollection.SelectSingleNode("Resources"); + XmlNode xmlAssets = xmlCollection.SelectSingleNode("Assets"); + + XmlNodeList xmlNodeList = null; + XmlNode xmlNode = null; + int count = 0; + + xmlNodeList = xmlResources.ChildNodes; + count = xmlNodeList.Count; + for (int i = 0; i < count; i++) + { + if (OnLoadingResource != null) + { + OnLoadingResource(i, count); + } + + xmlNode = xmlNodeList.Item(i); + if (xmlNode.Name != "Resource") + { + continue; + } + + string name = xmlNode.Attributes.GetNamedItem("Name").Value; + string variant = xmlNode.Attributes.GetNamedItem("Variant") != null ? xmlNode.Attributes.GetNamedItem("Variant").Value : null; + string fileSystem = xmlNode.Attributes.GetNamedItem("FileSystem") != null ? xmlNode.Attributes.GetNamedItem("FileSystem").Value : null; + byte loadType = 0; + if (xmlNode.Attributes.GetNamedItem("LoadType") != null) + { + byte.TryParse(xmlNode.Attributes.GetNamedItem("LoadType").Value, out loadType); + } + + bool packed = false; + if (xmlNode.Attributes.GetNamedItem("Packed") != null) + { + bool.TryParse(xmlNode.Attributes.GetNamedItem("Packed").Value, out packed); + } + + string[] resourceGroups = xmlNode.Attributes.GetNamedItem("ResourceGroups") != null ? xmlNode.Attributes.GetNamedItem("ResourceGroups").Value.Split(',') : null; + if (!AddResource(name, variant, fileSystem, (LoadType)loadType, packed, resourceGroups)) + { + Debug.LogWarning(Utility.Text.Format("Can not add resource '{0}'.", GetResourceFullName(name, variant))); + continue; + } + } + + xmlNodeList = xmlAssets.ChildNodes; + count = xmlNodeList.Count; + for (int i = 0; i < count; i++) + { + if (OnLoadingAsset != null) + { + OnLoadingAsset(i, count); + } + + xmlNode = xmlNodeList.Item(i); + if (xmlNode.Name != "Asset") + { + continue; + } + + string guid = xmlNode.Attributes.GetNamedItem("Guid").Value; + string name = xmlNode.Attributes.GetNamedItem("ResourceName").Value; + string variant = xmlNode.Attributes.GetNamedItem("ResourceVariant") != null ? xmlNode.Attributes.GetNamedItem("ResourceVariant").Value : null; + if (!AssignAsset(guid, name, variant)) + { + Debug.LogWarning(Utility.Text.Format("Can not assign asset '{0}' to resource '{1}'.", guid, GetResourceFullName(name, variant))); + continue; + } + } + + if (OnLoadCompleted != null) + { + OnLoadCompleted(); + } + + return true; + } + catch + { + File.Delete(m_ConfigurationPath); + if (OnLoadCompleted != null) + { + OnLoadCompleted(); + } + + return false; + } + } + + public bool Save() + { + try + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.AppendChild(xmlDocument.CreateXmlDeclaration("1.0", "UTF-8", null)); + + XmlElement xmlRoot = xmlDocument.CreateElement("UnityGameFramework"); + xmlDocument.AppendChild(xmlRoot); + + XmlElement xmlCollection = xmlDocument.CreateElement("ResourceCollection"); + xmlRoot.AppendChild(xmlCollection); + + XmlElement xmlResources = xmlDocument.CreateElement("Resources"); + xmlCollection.AppendChild(xmlResources); + + XmlElement xmlAssets = xmlDocument.CreateElement("Assets"); + xmlCollection.AppendChild(xmlAssets); + + XmlElement xmlElement = null; + XmlAttribute xmlAttribute = null; + + foreach (Resource resource in m_Resources.Values) + { + xmlElement = xmlDocument.CreateElement("Resource"); + xmlAttribute = xmlDocument.CreateAttribute("Name"); + xmlAttribute.Value = resource.Name; + xmlElement.Attributes.SetNamedItem(xmlAttribute); + + if (resource.Variant != null) + { + xmlAttribute = xmlDocument.CreateAttribute("Variant"); + xmlAttribute.Value = resource.Variant; + xmlElement.Attributes.SetNamedItem(xmlAttribute); + } + + if (resource.FileSystem != null) + { + xmlAttribute = xmlDocument.CreateAttribute("FileSystem"); + xmlAttribute.Value = resource.FileSystem; + xmlElement.Attributes.SetNamedItem(xmlAttribute); + } + + xmlAttribute = xmlDocument.CreateAttribute("LoadType"); + xmlAttribute.Value = ((byte)resource.LoadType).ToString(); + xmlElement.Attributes.SetNamedItem(xmlAttribute); + xmlAttribute = xmlDocument.CreateAttribute("Packed"); + xmlAttribute.Value = resource.Packed.ToString(); + xmlElement.Attributes.SetNamedItem(xmlAttribute); + string[] resourceGroups = resource.GetResourceGroups(); + if (resourceGroups.Length > 0) + { + xmlAttribute = xmlDocument.CreateAttribute("ResourceGroups"); + xmlAttribute.Value = string.Join(",", resourceGroups); + xmlElement.Attributes.SetNamedItem(xmlAttribute); + } + + xmlResources.AppendChild(xmlElement); + } + + foreach (Asset asset in m_Assets.Values) + { + xmlElement = xmlDocument.CreateElement("Asset"); + xmlAttribute = xmlDocument.CreateAttribute("Guid"); + xmlAttribute.Value = asset.Guid; + xmlElement.Attributes.SetNamedItem(xmlAttribute); + xmlAttribute = xmlDocument.CreateAttribute("ResourceName"); + xmlAttribute.Value = asset.Resource.Name; + xmlElement.Attributes.SetNamedItem(xmlAttribute); + if (asset.Resource.Variant != null) + { + xmlAttribute = xmlDocument.CreateAttribute("ResourceVariant"); + xmlAttribute.Value = asset.Resource.Variant; + xmlElement.Attributes.SetNamedItem(xmlAttribute); + } + + xmlAssets.AppendChild(xmlElement); + } + + string configurationDirectoryName = Path.GetDirectoryName(m_ConfigurationPath); + if (!Directory.Exists(configurationDirectoryName)) + { + Directory.CreateDirectory(configurationDirectoryName); + } + + xmlDocument.Save(m_ConfigurationPath); + AssetDatabase.Refresh(); + return true; + } + catch + { + if (File.Exists(m_ConfigurationPath)) + { + File.Delete(m_ConfigurationPath); + } + + return false; + } + } + + public Resource[] GetResources() + { + return m_Resources.Values.ToArray(); + } + + public Resource GetResource(string name, string variant) + { + if (!IsValidResourceName(name, variant)) + { + return null; + } + + Resource resource = null; + if (m_Resources.TryGetValue(GetResourceFullName(name, variant).ToLowerInvariant(), out resource)) + { + return resource; + } + + return null; + } + + public bool HasResource(string name, string variant) + { + if (!IsValidResourceName(name, variant)) + { + return false; + } + + return m_Resources.ContainsKey(GetResourceFullName(name, variant).ToLowerInvariant()); + } + + public bool AddResource(string name, string variant, string fileSystem, LoadType loadType, bool packed) + { + return AddResource(name, variant, fileSystem, loadType, packed, null); + } + + public bool AddResource(string name, string variant, string fileSystem, LoadType loadType, bool packed, string[] resourceGroups) + { + if (!IsValidResourceName(name, variant)) + { + return false; + } + + if (!IsAvailableResourceName(name, variant, null)) + { + return false; + } + + if (fileSystem != null && !ResourceNameRegex.IsMatch(fileSystem)) + { + return false; + } + + Resource resource = Resource.Create(name, variant, fileSystem, loadType, packed, resourceGroups); + m_Resources.Add(resource.FullName.ToLowerInvariant(), resource); + + return true; + } + + public bool RenameResource(string oldName, string oldVariant, string newName, string newVariant) + { + if (!IsValidResourceName(oldName, oldVariant) || !IsValidResourceName(newName, newVariant)) + { + return false; + } + + Resource resource = GetResource(oldName, oldVariant); + if (resource == null) + { + return false; + } + + if (oldName == newName && oldVariant == newVariant) + { + return true; + } + + if (!IsAvailableResourceName(newName, newVariant, resource)) + { + return false; + } + + m_Resources.Remove(resource.FullName.ToLowerInvariant()); + resource.Rename(newName, newVariant); + m_Resources.Add(resource.FullName.ToLowerInvariant(), resource); + + return true; + } + + public bool RemoveResource(string name, string variant) + { + if (!IsValidResourceName(name, variant)) + { + return false; + } + + Resource resource = GetResource(name, variant); + if (resource == null) + { + return false; + } + + Asset[] assets = resource.GetAssets(); + resource.Clear(); + m_Resources.Remove(resource.FullName.ToLowerInvariant()); + foreach (Asset asset in assets) + { + m_Assets.Remove(asset.Guid); + } + + return true; + } + + public bool SetResourceLoadType(string name, string variant, LoadType loadType) + { + if (!IsValidResourceName(name, variant)) + { + return false; + } + + Resource resource = GetResource(name, variant); + if (resource == null) + { + return false; + } + + if ((loadType == LoadType.LoadFromBinary || loadType == LoadType.LoadFromBinaryAndQuickDecrypt || loadType == LoadType.LoadFromBinaryAndDecrypt) && resource.GetAssets().Length > 1) + { + return false; + } + + resource.LoadType = loadType; + return true; + } + + public bool SetResourcePacked(string name, string variant, bool packed) + { + if (!IsValidResourceName(name, variant)) + { + return false; + } + + Resource resource = GetResource(name, variant); + if (resource == null) + { + return false; + } + + resource.Packed = packed; + return true; + } + + public Asset[] GetAssets() + { + return m_Assets.Values.ToArray(); + } + + public Asset[] GetAssets(string name, string variant) + { + if (!IsValidResourceName(name, variant)) + { + return new Asset[0]; + } + + Resource resource = GetResource(name, variant); + if (resource == null) + { + return new Asset[0]; + } + + return resource.GetAssets(); + } + + public Asset GetAsset(string guid) + { + if (string.IsNullOrEmpty(guid)) + { + return null; + } + + Asset asset = null; + if (m_Assets.TryGetValue(guid, out asset)) + { + return asset; + } + + return null; + } + + public bool HasAsset(string guid) + { + if (string.IsNullOrEmpty(guid)) + { + return false; + } + + return m_Assets.ContainsKey(guid); + } + + public bool AssignAsset(string guid, string name, string variant) + { + if (string.IsNullOrEmpty(guid)) + { + return false; + } + + if (!IsValidResourceName(name, variant)) + { + return false; + } + + Resource resource = GetResource(name, variant); + if (resource == null) + { + return false; + } + + string assetName = AssetDatabase.GUIDToAssetPath(guid); + if (string.IsNullOrEmpty(assetName)) + { + return false; + } + + Asset[] assetsInResource = resource.GetAssets(); + foreach (Asset assetInResource in assetsInResource) + { + if (assetInResource.Name == assetName) + { + continue; + } + + if (assetInResource.Name.ToLowerInvariant() == assetName.ToLowerInvariant()) + { + return false; + } + } + + bool isScene = assetName.EndsWith(SceneExtension, StringComparison.Ordinal); + if (isScene && resource.AssetType == AssetType.Asset || !isScene && resource.AssetType == AssetType.Scene) + { + return false; + } + + Asset asset = GetAsset(guid); + if (resource.IsLoadFromBinary && assetsInResource.Length > 0 && asset != assetsInResource[0]) + { + return false; + } + + if (asset == null) + { + asset = Asset.Create(guid); + m_Assets.Add(asset.Guid, asset); + } + + resource.AssignAsset(asset, isScene); + + return true; + } + + public bool UnassignAsset(string guid) + { + if (string.IsNullOrEmpty(guid)) + { + return false; + } + + Asset asset = GetAsset(guid); + if (asset != null) + { + asset.Resource.UnassignAsset(asset); + m_Assets.Remove(asset.Guid); + } + + return true; + } + + private string GetResourceFullName(string name, string variant) + { + return !string.IsNullOrEmpty(variant) ? Utility.Text.Format("{0}.{1}", name, variant) : name; + } + + private bool IsValidResourceName(string name, string variant) + { + if (string.IsNullOrEmpty(name)) + { + return false; + } + + if (!ResourceNameRegex.IsMatch(name)) + { + return false; + } + + if (variant != null && !ResourceVariantRegex.IsMatch(variant)) + { + return false; + } + + return true; + } + + private bool IsAvailableResourceName(string name, string variant, Resource current) + { + Resource found = GetResource(name, variant); + if (found != null && found != current) + { + return false; + } + + string[] foundPathNames = name.Split('/'); + foreach (Resource resource in m_Resources.Values) + { + if (current != null && resource == current) + { + continue; + } + + if (resource.Name == name) + { + if (resource.Variant == null && variant != null) + { + return false; + } + + if (resource.Variant != null && variant == null) + { + return false; + } + } + + if (resource.Name.Length > name.Length + && resource.Name.IndexOf(name, StringComparison.CurrentCultureIgnoreCase) == 0 + && resource.Name[name.Length] == '/') + { + return false; + } + + if (name.Length > resource.Name.Length + && name.IndexOf(resource.Name, StringComparison.CurrentCultureIgnoreCase) == 0 + && name[resource.Name.Length] == '/') + { + return false; + } + + string[] pathNames = resource.Name.Split('/'); + for (int i = 0; i < foundPathNames.Length - 1 && i < pathNames.Length - 1; i++) + { + if (foundPathNames[i].ToLowerInvariant() != pathNames[i].ToLowerInvariant()) + { + break; + } + + if (foundPathNames[i] != pathNames[i]) + { + return false; + } + } + } + + return true; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/ResourceCollection.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/ResourceCollection.cs.meta new file mode 100644 index 0000000..f79b8dd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/ResourceCollection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d1736b422b0ea4c46bbaf798d320e6f1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/ResourceCollectionConfigPathAttribute.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/ResourceCollectionConfigPathAttribute.cs new file mode 100644 index 0000000..cfcdbdf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/ResourceCollectionConfigPathAttribute.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// ResourceCollection 配置路径属性。 + /// + public sealed class ResourceCollectionConfigPathAttribute : ConfigPathAttribute + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/ResourceCollectionConfigPathAttribute.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/ResourceCollectionConfigPathAttribute.cs.meta new file mode 100644 index 0000000..570a125 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceCollection/ResourceCollectionConfigPathAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1eb3245545d87064b814268034cc7af6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor.meta new file mode 100644 index 0000000..c910193 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8e537bb30b04ebc41bd7575567444988 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/AssetSorterType.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/AssetSorterType.cs new file mode 100644 index 0000000..c8aafd7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/AssetSorterType.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor.ResourceTools +{ + public enum AssetSorterType : byte + { + Path, + Name, + Guid, + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/AssetSorterType.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/AssetSorterType.cs.meta new file mode 100644 index 0000000..bfa9ba5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/AssetSorterType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5463b22a6a4019146a38f7b80dbe6fa7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.MenuState.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.MenuState.cs new file mode 100644 index 0000000..2692310 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.MenuState.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEditor; + +namespace UnityGameFramework.Editor.ResourceTools +{ + internal sealed partial class ResourceEditor : EditorWindow + { + private enum MenuState : byte + { + Normal, + Add, + Rename, + Remove, + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.MenuState.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.MenuState.cs.meta new file mode 100644 index 0000000..70df25a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.MenuState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 32b00a6c44b75494f8576b42717b1f1f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.ResourceFolder.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.ResourceFolder.cs new file mode 100644 index 0000000..98b2c69 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.ResourceFolder.cs @@ -0,0 +1,164 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + internal sealed partial class ResourceEditor : EditorWindow + { + private sealed class ResourceFolder + { + private static Texture s_CachedIcon = null; + + private readonly List m_Folders; + private readonly List m_Items; + + public ResourceFolder(string name, ResourceFolder folder) + { + m_Folders = new List(); + m_Items = new List(); + + Name = name; + Folder = folder; + } + + public string Name + { + get; + private set; + } + + public ResourceFolder Folder + { + get; + private set; + } + + public string FromRootPath + { + get + { + return Folder == null ? string.Empty : (Folder.Folder == null ? Name : Utility.Text.Format("{0}/{1}", Folder.FromRootPath, Name)); + } + } + + public int Depth + { + get + { + return Folder != null ? Folder.Depth + 1 : 0; + } + } + + public static Texture Icon + { + get + { + if (s_CachedIcon == null) + { + s_CachedIcon = AssetDatabase.GetCachedIcon("Assets"); + } + + return s_CachedIcon; + } + } + + public void Clear() + { + m_Folders.Clear(); + m_Items.Clear(); + } + + public ResourceFolder[] GetFolders() + { + return m_Folders.ToArray(); + } + + public ResourceFolder GetFolder(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Resource folder name is invalid."); + } + + foreach (ResourceFolder folder in m_Folders) + { + if (folder.Name == name) + { + return folder; + } + } + + return null; + } + + public ResourceFolder AddFolder(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Resource folder name is invalid."); + } + + ResourceFolder folder = GetFolder(name); + if (folder != null) + { + throw new GameFrameworkException("Resource folder is already exist."); + } + + folder = new ResourceFolder(name, this); + m_Folders.Add(folder); + + return folder; + } + + public ResourceItem[] GetItems() + { + return m_Items.ToArray(); + } + + public ResourceItem GetItem(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Resource item name is invalid."); + } + + foreach (ResourceItem item in m_Items) + { + if (item.Name == name) + { + return item; + } + } + + return null; + } + + public void AddItem(string name, Resource resource) + { + ResourceItem item = GetItem(name); + if (item != null) + { + throw new GameFrameworkException("Resource item is already exist."); + } + + item = new ResourceItem(name, resource, this); + m_Items.Add(item); + m_Items.Sort(ResourceItemComparer); + } + + private int ResourceItemComparer(ResourceItem a, ResourceItem b) + { + return a.Name.CompareTo(b.Name); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.ResourceFolder.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.ResourceFolder.cs.meta new file mode 100644 index 0000000..04868b9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.ResourceFolder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8cb7e55dc8f5c0b4c8bdad2802a24162 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.ResourceItem.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.ResourceItem.cs new file mode 100644 index 0000000..d293444 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.ResourceItem.cs @@ -0,0 +1,159 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + internal sealed partial class ResourceEditor : EditorWindow + { + private sealed class ResourceItem + { + private static Texture s_CachedUnknownIcon = null; + private static Texture s_CachedAssetIcon = null; + private static Texture s_CachedSceneIcon = null; + + public ResourceItem(string name, Resource resource, ResourceFolder folder) + { + if (resource == null) + { + throw new GameFrameworkException("Resource is invalid."); + } + + if (folder == null) + { + throw new GameFrameworkException("Resource folder is invalid."); + } + + Name = name; + Resource = resource; + Folder = folder; + } + + public string Name + { + get; + private set; + } + + public Resource Resource + { + get; + private set; + } + + public ResourceFolder Folder + { + get; + private set; + } + + public string FromRootPath + { + get + { + return Folder.Folder == null ? Name : Utility.Text.Format("{0}/{1}", Folder.FromRootPath, Name); + } + } + + public int Depth + { + get + { + return Folder != null ? Folder.Depth + 1 : 0; + } + } + + public Texture Icon + { + get + { + if (Resource.IsLoadFromBinary) + { + Asset asset = Resource.GetFirstAsset(); + if (asset != null) + { + Texture texture = AssetDatabase.GetCachedIcon(AssetDatabase.GUIDToAssetPath(asset.Guid)); + return texture != null ? texture : CachedUnknownIcon; + } + } + else + { + switch (Resource.AssetType) + { + case AssetType.Asset: + return CachedAssetIcon; + + case AssetType.Scene: + return CachedSceneIcon; + } + } + + return CachedUnknownIcon; + } + } + + private static Texture CachedUnknownIcon + { + get + { + if (s_CachedUnknownIcon == null) + { + string iconName = null; +#if UNITY_2018_3_OR_NEWER + iconName = "GameObject Icon"; +#else + iconName = "Prefab Icon"; +#endif + s_CachedUnknownIcon = GetIcon(iconName); + } + + return s_CachedUnknownIcon; + } + } + + private static Texture CachedAssetIcon + { + get + { + if (s_CachedAssetIcon == null) + { + string iconName = null; +#if UNITY_2018_3_OR_NEWER + iconName = "Prefab Icon"; +#else + iconName = "PrefabNormal Icon"; +#endif + s_CachedAssetIcon = GetIcon(iconName); + } + + return s_CachedAssetIcon; + } + } + + private static Texture CachedSceneIcon + { + get + { + if (s_CachedSceneIcon == null) + { + s_CachedSceneIcon = GetIcon("SceneAsset Icon"); + } + + return s_CachedSceneIcon; + } + } + + private static Texture GetIcon(string iconName) + { + return EditorGUIUtility.IconContent(iconName).image; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.ResourceItem.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.ResourceItem.cs.meta new file mode 100644 index 0000000..352c136 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.ResourceItem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3f2127e06af00f84294606afa2dfc494 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.cs new file mode 100644 index 0000000..fe048ff --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.cs @@ -0,0 +1,1129 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// 资源编辑器。 + /// + internal sealed partial class ResourceEditor : EditorWindow + { + private ResourceEditorController m_Controller = null; + private MenuState m_MenuState = MenuState.Normal; + private Resource m_SelectedResource = null; + private ResourceFolder m_ResourceRoot = null; + private HashSet m_ExpandedResourceFolderNames = null; + private HashSet m_SelectedAssetsInSelectedResource = null; + private HashSet m_ExpandedSourceFolders = null; + private HashSet m_SelectedSourceAssets = null; + private Texture m_MissingSourceAssetIcon = null; + + private HashSet m_CachedSelectedSourceFolders = null; + private HashSet m_CachedUnselectedSourceFolders = null; + private HashSet m_CachedAssignedSourceFolders = null; + private HashSet m_CachedUnassignedSourceFolders = null; + private HashSet m_CachedAssignedSourceAssets = null; + private HashSet m_CachedUnassignedSourceAssets = null; + + private Vector2 m_ResourcesViewScroll = Vector2.zero; + private Vector2 m_ResourceViewScroll = Vector2.zero; + private Vector2 m_SourceAssetsViewScroll = Vector2.zero; + private string m_InputResourceName = null; + private string m_InputResourceVariant = null; + private string m_InputDefaultResourceGroup = null; + private bool m_HideAssignedSourceAssets = false; + private int m_CurrentResourceContentCount = 0; + private int m_CurrentResourceRowOnDraw = 0; + private int m_CurrentSourceRowOnDraw = 0; + + [MenuItem("Game Framework/Resource Tools/Resource Editor", false, 41)] + private static void Open() + { + ResourceEditor window = GetWindow("Resource Editor", true); + window.minSize = new Vector2(1400f, 600f); + } + + private void OnEnable() + { + m_Controller = new ResourceEditorController(); + m_Controller.OnLoadingResource += OnLoadingResource; + m_Controller.OnLoadingAsset += OnLoadingAsset; + m_Controller.OnLoadCompleted += OnLoadCompleted; + m_Controller.OnAssetAssigned += OnAssetAssigned; + m_Controller.OnAssetUnassigned += OnAssetUnassigned; + + m_MenuState = MenuState.Normal; + m_SelectedResource = null; + m_ResourceRoot = new ResourceFolder("Resources", null); + m_ExpandedResourceFolderNames = new HashSet(); + m_SelectedAssetsInSelectedResource = new HashSet(); + m_ExpandedSourceFolders = new HashSet(); + m_SelectedSourceAssets = new HashSet(); + m_MissingSourceAssetIcon = EditorGUIUtility.IconContent("console.warnicon.sml").image; + + m_CachedSelectedSourceFolders = new HashSet(); + m_CachedUnselectedSourceFolders = new HashSet(); + m_CachedAssignedSourceFolders = new HashSet(); + m_CachedUnassignedSourceFolders = new HashSet(); + m_CachedAssignedSourceAssets = new HashSet(); + m_CachedUnassignedSourceAssets = new HashSet(); + + m_ResourcesViewScroll = Vector2.zero; + m_ResourceViewScroll = Vector2.zero; + m_SourceAssetsViewScroll = Vector2.zero; + m_InputResourceName = null; + m_InputResourceVariant = null; + m_InputDefaultResourceGroup = null; + m_HideAssignedSourceAssets = false; + m_CurrentResourceContentCount = 0; + m_CurrentResourceRowOnDraw = 0; + m_CurrentSourceRowOnDraw = 0; + + if (m_Controller.Load()) + { + Debug.Log("Load configuration success."); + } + else + { + Debug.LogWarning("Load configuration failure."); + } + + EditorUtility.DisplayProgressBar("Prepare Resource Editor", "Processing...", 0f); + RefreshResourceTree(); + EditorUtility.ClearProgressBar(); + } + + private void OnGUI() + { + EditorGUILayout.BeginHorizontal(GUILayout.Width(position.width), GUILayout.Height(position.height)); + { + GUILayout.Space(2f); + EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.25f)); + { + GUILayout.Space(5f); + EditorGUILayout.LabelField(Utility.Text.Format("Resource List ({0})", m_Controller.ResourceCount), EditorStyles.boldLabel); + EditorGUILayout.BeginHorizontal("box", GUILayout.Height(position.height - 52f)); + { + DrawResourcesView(); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + GUILayout.Space(5f); + DrawResourcesMenu(); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.25f)); + { + GUILayout.Space(5f); + EditorGUILayout.LabelField(Utility.Text.Format("Resource Content ({0})", m_CurrentResourceContentCount), EditorStyles.boldLabel); + EditorGUILayout.BeginHorizontal("box", GUILayout.Height(position.height - 52f)); + { + DrawResourceView(); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + GUILayout.Space(5f); + DrawResourceMenu(); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + EditorGUILayout.BeginVertical(GUILayout.Width(position.width * 0.5f - 16f)); + { + GUILayout.Space(5f); + EditorGUILayout.LabelField("Asset List", EditorStyles.boldLabel); + EditorGUILayout.BeginHorizontal("box", GUILayout.Height(position.height - 52f)); + { + DrawSourceAssetsView(); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + GUILayout.Space(5f); + DrawSourceAssetsMenu(); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + GUILayout.Space(5f); + } + EditorGUILayout.EndHorizontal(); + } + + private void DrawResourcesView() + { + m_CurrentResourceRowOnDraw = 0; + m_ResourcesViewScroll = EditorGUILayout.BeginScrollView(m_ResourcesViewScroll); + { + DrawResourceFolder(m_ResourceRoot); + } + EditorGUILayout.EndScrollView(); + } + + private void DrawResourceFolder(ResourceFolder folder) + { + bool expand = IsExpandedResourceFolder(folder); + EditorGUILayout.BeginHorizontal(); + { +#if UNITY_2019_3_OR_NEWER + bool foldout = EditorGUI.Foldout(new Rect(18f + 14f * folder.Depth, 20f * m_CurrentResourceRowOnDraw + 4f, int.MaxValue, 14f), expand, string.Empty, true); +#else + bool foldout = EditorGUI.Foldout(new Rect(18f + 14f * folder.Depth, 20f * m_CurrentResourceRowOnDraw + 2f, int.MaxValue, 14f), expand, string.Empty, true); +#endif + if (expand != foldout) + { + expand = !expand; + SetExpandedResourceFolder(folder, expand); + } + +#if UNITY_2019_3_OR_NEWER + GUI.DrawTexture(new Rect(32f + 14f * folder.Depth, 20f * m_CurrentResourceRowOnDraw + 3f, 16f, 16f), ResourceFolder.Icon); + EditorGUILayout.LabelField(string.Empty, GUILayout.Width(44f + 14f * folder.Depth), GUILayout.Height(18f)); +#else + GUI.DrawTexture(new Rect(32f + 14f * folder.Depth, 20f * m_CurrentResourceRowOnDraw + 1f, 16f, 16f), ResourceFolder.Icon); + EditorGUILayout.LabelField(string.Empty, GUILayout.Width(40f + 14f * folder.Depth), GUILayout.Height(18f)); +#endif + EditorGUILayout.LabelField(folder.Name); + } + EditorGUILayout.EndHorizontal(); + + m_CurrentResourceRowOnDraw++; + + if (expand) + { + foreach (ResourceFolder subFolder in folder.GetFolders()) + { + DrawResourceFolder(subFolder); + } + + foreach (ResourceItem resourceItem in folder.GetItems()) + { + DrawResourceItem(resourceItem); + } + } + } + + private void DrawResourceItem(ResourceItem resourceItem) + { + EditorGUILayout.BeginHorizontal(); + { + string title = resourceItem.Name; + if (resourceItem.Resource.Packed) + { + title = "[Packed] " + title; + } + + float emptySpace = position.width; + if (EditorGUILayout.Toggle(m_SelectedResource == resourceItem.Resource, GUILayout.Width(emptySpace - 12f))) + { + ChangeSelectedResource(resourceItem.Resource); + } + else if (m_SelectedResource == resourceItem.Resource) + { + ChangeSelectedResource(null); + } + + GUILayout.Space(-emptySpace + 24f); +#if UNITY_2019_3_OR_NEWER + GUI.DrawTexture(new Rect(32f + 14f * resourceItem.Depth, 20f * m_CurrentResourceRowOnDraw + 3f, 16f, 16f), resourceItem.Icon); + EditorGUILayout.LabelField(string.Empty, GUILayout.Width(30f + 14f * resourceItem.Depth), GUILayout.Height(18f)); +#else + GUI.DrawTexture(new Rect(32f + 14f * resourceItem.Depth, 20f * m_CurrentResourceRowOnDraw + 1f, 16f, 16f), resourceItem.Icon); + EditorGUILayout.LabelField(string.Empty, GUILayout.Width(26f + 14f * resourceItem.Depth), GUILayout.Height(18f)); +#endif + EditorGUILayout.LabelField(title); + } + EditorGUILayout.EndHorizontal(); + m_CurrentResourceRowOnDraw++; + } + + private void DrawResourcesMenu() + { + switch (m_MenuState) + { + case MenuState.Normal: + DrawResourcesMenu_Normal(); + break; + + case MenuState.Add: + DrawResourcesMenu_Add(); + break; + + case MenuState.Rename: + DrawResourcesMenu_Rename(); + break; + + case MenuState.Remove: + DrawResourcesMenu_Remove(); + break; + } + } + + private void DrawResourcesMenu_Normal() + { + if (GUILayout.Button("Add", GUILayout.Width(65f))) + { + m_MenuState = MenuState.Add; + m_InputResourceName = null; + m_InputResourceVariant = null; + m_InputDefaultResourceGroup = "Base"; + GUI.FocusControl(null); + } + EditorGUI.BeginDisabledGroup(m_SelectedResource == null); + { + if (GUILayout.Button("Rename", GUILayout.Width(65f))) + { + m_MenuState = MenuState.Rename; + m_InputResourceName = m_SelectedResource != null ? m_SelectedResource.Name : null; + m_InputResourceVariant = m_SelectedResource != null ? m_SelectedResource.Variant : null; + m_InputDefaultResourceGroup = m_SelectedResource != null ? m_SelectedResource.GetResourceGroups()[0] : null; + GUI.FocusControl(null); + } + if (GUILayout.Button("Remove", GUILayout.Width(65f))) + { + m_MenuState = MenuState.Remove; + } + if (m_SelectedResource == null) + { + EditorGUILayout.EnumPopup(LoadType.LoadFromFile); + } + else + { + LoadType loadType = (LoadType)EditorGUILayout.EnumPopup(m_SelectedResource.LoadType); + if (loadType != m_SelectedResource.LoadType) + { + SetResourceLoadType(loadType); + } + } + bool packed = EditorGUILayout.ToggleLeft("Packed", m_SelectedResource != null && m_SelectedResource.Packed, GUILayout.Width(65f)); + if (m_SelectedResource != null && packed != m_SelectedResource.Packed) + { + SetResourcePacked(packed); + } + } + EditorGUI.EndDisabledGroup(); + } + + private void DrawResourcesMenu_Add() + { + GUI.SetNextControlName("NewResourceNameTextField"); + m_InputResourceName = EditorGUILayout.TextField(m_InputResourceName); + GUI.SetNextControlName("NewResourceVariantTextField"); + m_InputResourceVariant = EditorGUILayout.TextField(m_InputResourceVariant, GUILayout.Width(30f)); + GUI.SetNextControlName("NewResourceGroupsTextField"); + m_InputDefaultResourceGroup = EditorGUILayout.TextField(m_InputDefaultResourceGroup, GUILayout.Width(30f)); + + if (GUI.GetNameOfFocusedControl() == "NewResourceNameTextField" || GUI.GetNameOfFocusedControl() == "NewResourceVariantTextField" || GUI.GetNameOfFocusedControl() == "NewResourceGroupsTextField") + { + if (Event.current.isKey && Event.current.keyCode == KeyCode.Return) + { + EditorUtility.DisplayProgressBar("Add Resource", "Processing...", 0f); + AddResource(m_InputResourceName, m_InputResourceVariant, m_InputDefaultResourceGroup, true); + EditorUtility.ClearProgressBar(); + Repaint(); + } + } + + if (GUILayout.Button("Add", GUILayout.Width(50f))) + { + EditorUtility.DisplayProgressBar("Add Resource", "Processing...", 0f); + AddResource(m_InputResourceName, m_InputResourceVariant, m_InputDefaultResourceGroup, true); + EditorUtility.ClearProgressBar(); + } + + if (GUILayout.Button("Back", GUILayout.Width(50f))) + { + m_MenuState = MenuState.Normal; + } + } + + private void DrawResourcesMenu_Rename() + { + if (m_SelectedResource == null) + { + m_MenuState = MenuState.Normal; + return; + } + + GUI.SetNextControlName("RenameResourceNameTextField"); + m_InputResourceName = EditorGUILayout.TextField(m_InputResourceName); + GUI.SetNextControlName("RenameResourceVariantTextField"); + m_InputResourceVariant = EditorGUILayout.TextField(m_InputResourceVariant, GUILayout.Width(30f)); + GUI.SetNextControlName("RenameResourceGroupsTextField"); + m_InputDefaultResourceGroup = EditorGUILayout.TextField(m_InputDefaultResourceGroup, GUILayout.Width(30f)); + + if (GUI.GetNameOfFocusedControl() == "RenameResourceNameTextField" || GUI.GetNameOfFocusedControl() == "RenameResourceVariantTextField" || GUI.GetNameOfFocusedControl() == "RenameResourceGroupsTextField") + { + if (Event.current.isKey && Event.current.keyCode == KeyCode.Return) + { + EditorUtility.DisplayProgressBar("Rename Resource", "Processing...", 0f); + RenameResource(m_SelectedResource, m_InputResourceName, m_InputResourceVariant, m_InputDefaultResourceGroup); + EditorUtility.ClearProgressBar(); + Repaint(); + } + } + + if (GUILayout.Button("OK", GUILayout.Width(50f))) + { + EditorUtility.DisplayProgressBar("Rename Resource", "Processing...", 0f); + RenameResource(m_SelectedResource, m_InputResourceName, m_InputResourceVariant, m_InputDefaultResourceGroup); + EditorUtility.ClearProgressBar(); + } + + if (GUILayout.Button("Back", GUILayout.Width(50f))) + { + m_MenuState = MenuState.Normal; + } + } + + private void DrawResourcesMenu_Remove() + { + if (m_SelectedResource == null) + { + m_MenuState = MenuState.Normal; + return; + } + + GUILayout.Label(Utility.Text.Format("Remove '{0}' ?", m_SelectedResource.FullName)); + + if (GUILayout.Button("Yes", GUILayout.Width(50f))) + { + EditorUtility.DisplayProgressBar("Remove Resource", "Processing...", 0f); + RemoveResource(); + EditorUtility.ClearProgressBar(); + m_MenuState = MenuState.Normal; + } + + if (GUILayout.Button("No", GUILayout.Width(50f))) + { + m_MenuState = MenuState.Normal; + } + } + + private void DrawResourceView() + { + m_ResourceViewScroll = EditorGUILayout.BeginScrollView(m_ResourceViewScroll); + { + if (m_SelectedResource != null) + { + int index = 0; + Asset[] assets = m_Controller.GetAssets(m_SelectedResource.Name, m_SelectedResource.Variant); + m_CurrentResourceContentCount = assets.Length; + foreach (Asset asset in assets) + { + SourceAsset sourceAsset = m_Controller.GetSourceAsset(asset.Guid); + string assetName = sourceAsset != null ? (m_Controller.AssetSorter == AssetSorterType.Path ? sourceAsset.Path : (m_Controller.AssetSorter == AssetSorterType.Name ? sourceAsset.Name : sourceAsset.Guid)) : asset.Guid; + EditorGUILayout.BeginHorizontal(); + { + float emptySpace = position.width; + bool select = IsSelectedAssetInSelectedResource(asset); + if (select != EditorGUILayout.Toggle(select, GUILayout.Width(emptySpace - 12f))) + { + select = !select; + SetSelectedAssetInSelectedResource(asset, select); + } + + GUILayout.Space(-emptySpace + 24f); +#if UNITY_2019_3_OR_NEWER + GUI.DrawTexture(new Rect(20f, 20f * index++ + 3f, 16f, 16f), sourceAsset != null ? sourceAsset.Icon : m_MissingSourceAssetIcon); + EditorGUILayout.LabelField(string.Empty, GUILayout.Width(16f), GUILayout.Height(18f)); +#else + GUI.DrawTexture(new Rect(20f, 20f * index++ + 1f, 16f, 16f), sourceAsset != null ? sourceAsset.Icon : m_MissingSourceAssetIcon); + EditorGUILayout.LabelField(string.Empty, GUILayout.Width(14f), GUILayout.Height(18f)); +#endif + EditorGUILayout.LabelField(assetName); + } + EditorGUILayout.EndHorizontal(); + } + } + else + { + m_CurrentResourceContentCount = 0; + } + } + EditorGUILayout.EndScrollView(); + } + + private void DrawResourceMenu() + { + if (GUILayout.Button("All", GUILayout.Width(50f)) && m_SelectedResource != null) + { + Asset[] assets = m_Controller.GetAssets(m_SelectedResource.Name, m_SelectedResource.Variant); + foreach (Asset asset in assets) + { + SetSelectedAssetInSelectedResource(asset, true); + } + } + if (GUILayout.Button("None", GUILayout.Width(50f))) + { + m_SelectedAssetsInSelectedResource.Clear(); + } + m_Controller.AssetSorter = (AssetSorterType)EditorGUILayout.EnumPopup(m_Controller.AssetSorter, GUILayout.Width(60f)); + GUILayout.Label(string.Empty); + EditorGUI.BeginDisabledGroup(m_SelectedResource == null || m_SelectedAssetsInSelectedResource.Count <= 0); + { + if (GUILayout.Button(Utility.Text.Format("{0} >>", m_SelectedAssetsInSelectedResource.Count), GUILayout.Width(80f))) + { + foreach (Asset asset in m_SelectedAssetsInSelectedResource) + { + UnassignAsset(asset); + } + + m_SelectedAssetsInSelectedResource.Clear(); + } + } + EditorGUI.EndDisabledGroup(); + } + + private void DrawSourceAssetsView() + { + m_CurrentSourceRowOnDraw = 0; + m_SourceAssetsViewScroll = EditorGUILayout.BeginScrollView(m_SourceAssetsViewScroll); + { + DrawSourceFolder(m_Controller.SourceAssetRoot); + } + EditorGUILayout.EndScrollView(); + } + + private void DrawSourceAssetsMenu() + { + HashSet selectedSourceAssets = GetSelectedSourceAssets(); + EditorGUI.BeginDisabledGroup(m_SelectedResource == null || selectedSourceAssets.Count <= 0); + { + if (GUILayout.Button(Utility.Text.Format("<< {0}", selectedSourceAssets.Count), GUILayout.Width(80f))) + { + foreach (SourceAsset sourceAsset in selectedSourceAssets) + { + AssignAsset(sourceAsset, m_SelectedResource); + } + + m_SelectedSourceAssets.Clear(); + m_CachedSelectedSourceFolders.Clear(); + } + } + EditorGUI.EndDisabledGroup(); + EditorGUI.BeginDisabledGroup(selectedSourceAssets.Count <= 0); + { + if (GUILayout.Button(Utility.Text.Format("<<< {0}", selectedSourceAssets.Count), GUILayout.Width(80f))) + { + int index = 0; + int count = selectedSourceAssets.Count; + foreach (SourceAsset sourceAsset in selectedSourceAssets) + { + EditorUtility.DisplayProgressBar("Add Resources", Utility.Text.Format("{0}/{1} processing...", ++index, count), (float)index / count); + int dotIndex = sourceAsset.FromRootPath.IndexOf('.'); + string name = dotIndex > 0 ? sourceAsset.FromRootPath.Substring(0, dotIndex) : sourceAsset.FromRootPath; + AddResource(name, null, "Base", false); + Resource resource = m_Controller.GetResource(name, null); + if (resource == null) + { + continue; + } + + AssignAsset(sourceAsset, resource); + } + + EditorUtility.DisplayProgressBar("Add Resources", "Complete processing...", 1f); + RefreshResourceTree(); + EditorUtility.ClearProgressBar(); + m_SelectedSourceAssets.Clear(); + m_CachedSelectedSourceFolders.Clear(); + } + } + EditorGUI.EndDisabledGroup(); + bool hideAssignedSourceAssets = EditorGUILayout.ToggleLeft("Hide Assigned", m_HideAssignedSourceAssets, GUILayout.Width(100f)); + if (hideAssignedSourceAssets != m_HideAssignedSourceAssets) + { + m_HideAssignedSourceAssets = hideAssignedSourceAssets; + m_CachedSelectedSourceFolders.Clear(); + m_CachedUnselectedSourceFolders.Clear(); + m_CachedAssignedSourceFolders.Clear(); + m_CachedUnassignedSourceFolders.Clear(); + } + + GUILayout.Label(string.Empty); + if (GUILayout.Button("Clean", GUILayout.Width(80f))) + { + EditorUtility.DisplayProgressBar("Clean", "Processing...", 0f); + CleanResource(); + EditorUtility.ClearProgressBar(); + } + if (GUILayout.Button("Save", GUILayout.Width(80f))) + { + EditorUtility.DisplayProgressBar("Save", "Processing...", 0f); + SaveConfiguration(); + EditorUtility.ClearProgressBar(); + } + } + + private void DrawSourceFolder(SourceFolder sourceFolder) + { + if (m_HideAssignedSourceAssets && IsAssignedSourceFolder(sourceFolder)) + { + return; + } + + bool expand = IsExpandedSourceFolder(sourceFolder); + EditorGUILayout.BeginHorizontal(); + { + bool select = IsSelectedSourceFolder(sourceFolder); + if (select != EditorGUILayout.Toggle(select, GUILayout.Width(12f + 14f * sourceFolder.Depth))) + { + select = !select; + SetSelectedSourceFolder(sourceFolder, select); + } + + GUILayout.Space(-14f * sourceFolder.Depth); +#if UNITY_2019_3_OR_NEWER + bool foldout = EditorGUI.Foldout(new Rect(18f + 14f * sourceFolder.Depth, 20f * m_CurrentSourceRowOnDraw + 4f, int.MaxValue, 14f), expand, string.Empty, true); +#else + bool foldout = EditorGUI.Foldout(new Rect(18f + 14f * sourceFolder.Depth, 20f * m_CurrentSourceRowOnDraw + 2f, int.MaxValue, 14f), expand, string.Empty, true); +#endif + if (expand != foldout) + { + expand = !expand; + SetExpandedSourceFolder(sourceFolder, expand); + } + +#if UNITY_2019_3_OR_NEWER + GUI.DrawTexture(new Rect(32f + 14f * sourceFolder.Depth, 20f * m_CurrentSourceRowOnDraw + 3f, 16f, 16f), SourceFolder.Icon); + EditorGUILayout.LabelField(string.Empty, GUILayout.Width(30f + 14f * sourceFolder.Depth), GUILayout.Height(18f)); +#else + GUI.DrawTexture(new Rect(32f + 14f * sourceFolder.Depth, 20f * m_CurrentSourceRowOnDraw + 1f, 16f, 16f), SourceFolder.Icon); + EditorGUILayout.LabelField(string.Empty, GUILayout.Width(26f + 14f * sourceFolder.Depth), GUILayout.Height(18f)); +#endif + EditorGUILayout.LabelField(sourceFolder.Name); + } + EditorGUILayout.EndHorizontal(); + + m_CurrentSourceRowOnDraw++; + + if (expand) + { + foreach (SourceFolder subSourceFolder in sourceFolder.GetFolders()) + { + DrawSourceFolder(subSourceFolder); + } + + foreach (SourceAsset sourceAsset in sourceFolder.GetAssets()) + { + DrawSourceAsset(sourceAsset); + } + } + } + + private void DrawSourceAsset(SourceAsset sourceAsset) + { + if (m_HideAssignedSourceAssets && IsAssignedSourceAsset(sourceAsset)) + { + return; + } + + EditorGUILayout.BeginHorizontal(); + { + float emptySpace = position.width; + bool select = IsSelectedSourceAsset(sourceAsset); + if (select != EditorGUILayout.Toggle(select, GUILayout.Width(emptySpace - 12f))) + { + select = !select; + SetSelectedSourceAsset(sourceAsset, select); + } + + GUILayout.Space(-emptySpace + 24f); +#if UNITY_2019_3_OR_NEWER + GUI.DrawTexture(new Rect(32f + 14f * sourceAsset.Depth, 20f * m_CurrentSourceRowOnDraw + 3f, 16f, 16f), sourceAsset.Icon); + EditorGUILayout.LabelField(string.Empty, GUILayout.Width(30f + 14f * sourceAsset.Depth), GUILayout.Height(18f)); +#else + GUI.DrawTexture(new Rect(32f + 14f * sourceAsset.Depth, 20f * m_CurrentSourceRowOnDraw + 1f, 16f, 16f), sourceAsset.Icon); + EditorGUILayout.LabelField(string.Empty, GUILayout.Width(26f + 14f * sourceAsset.Depth), GUILayout.Height(18f)); +#endif + EditorGUILayout.LabelField(sourceAsset.Name); + Asset asset = m_Controller.GetAsset(sourceAsset.Guid); + EditorGUILayout.LabelField(asset != null ? GetResourceFullName(asset.Resource.Name, asset.Resource.Variant) : string.Empty, GUILayout.Width(position.width * 0.15f)); + } + EditorGUILayout.EndHorizontal(); + m_CurrentSourceRowOnDraw++; + } + + private void ChangeSelectedResource(Resource resource) + { + if (m_SelectedResource == resource) + { + return; + } + + m_SelectedResource = resource; + m_SelectedAssetsInSelectedResource.Clear(); + } + + private void SaveConfiguration() + { + if (m_Controller.Save()) + { + Debug.Log("Save configuration success."); + } + else + { + Debug.LogWarning("Save configuration failure."); + } + } + + private void AddResource(string name, string variant, string defaultResourceGroup, bool refresh) + { + if (variant == string.Empty) + { + variant = null; + } + + string fullName = GetResourceFullName(name, variant); + if (m_Controller.AddResource(name, variant, null, LoadType.LoadFromFile, false, defaultResourceGroup)) + { + if (refresh) + { + RefreshResourceTree(); + } + + Debug.Log(Utility.Text.Format("Add resource '{0}' success.", fullName)); + m_MenuState = MenuState.Normal; + } + else + { + Debug.LogWarning(Utility.Text.Format("Add resource '{0}' failure.", fullName)); + } + } + + private void RenameResource(Resource resource, string newName, string newVariant, string defaultResourceGroup) + { + if (resource == null) + { + Debug.LogWarning("Resource is invalid."); + return; + } + + if (newVariant == string.Empty) + { + newVariant = null; + } + + string oldFullName = resource.FullName; + string newFullName = GetResourceFullName(newName, newVariant); + if (m_Controller.RenameResource(resource.Name, resource.Variant, newName, newVariant)) + { + resource.SetDefaultResourceGroup(defaultResourceGroup); + RefreshResourceTree(); + Debug.Log(Utility.Text.Format("Rename resource '{0}' to '{1}' success.", oldFullName, newFullName)); + m_MenuState = MenuState.Normal; + } + else + { + Debug.LogWarning(Utility.Text.Format("Rename resource '{0}' to '{1}' failure.", oldFullName, newFullName)); + } + } + + private void RemoveResource() + { + string fullName = m_SelectedResource.FullName; + if (m_Controller.RemoveResource(m_SelectedResource.Name, m_SelectedResource.Variant)) + { + ChangeSelectedResource(null); + RefreshResourceTree(); + Debug.Log(Utility.Text.Format("Remove resource '{0}' success.", fullName)); + } + else + { + Debug.LogWarning(Utility.Text.Format("Remove resource '{0}' failure.", fullName)); + } + } + + private void SetResourceLoadType(LoadType loadType) + { + string fullName = m_SelectedResource.FullName; + if (m_Controller.SetResourceLoadType(m_SelectedResource.Name, m_SelectedResource.Variant, loadType)) + { + Debug.Log(Utility.Text.Format("Set resource '{0}' load type to '{1}' success.", fullName, loadType)); + } + else + { + Debug.LogWarning(Utility.Text.Format("Set resource '{0}' load type to '{1}' failure.", fullName, loadType)); + } + } + + private void SetResourcePacked(bool packed) + { + string fullName = m_SelectedResource.FullName; + if (m_Controller.SetResourcePacked(m_SelectedResource.Name, m_SelectedResource.Variant, packed)) + { + Debug.Log(Utility.Text.Format("{1} resource '{0}' success.", fullName, packed ? "Pack" : "Unpack")); + } + else + { + Debug.LogWarning(Utility.Text.Format("{1} resource '{0}' failure.", fullName, packed ? "Pack" : "Unpack")); + } + } + + private void AssignAsset(SourceAsset sourceAsset, Resource resource) + { + if (!m_Controller.AssignAsset(sourceAsset.Guid, resource.Name, resource.Variant)) + { + Debug.LogWarning(Utility.Text.Format("Assign asset '{0}' to resource '{1}' failure.", sourceAsset.Name, resource.FullName)); + } + } + + private void UnassignAsset(Asset asset) + { + if (!m_Controller.UnassignAsset(asset.Guid)) + { + Debug.LogWarning(Utility.Text.Format("Unassign asset '{0}' from resource '{1}' failure.", asset.Guid, m_SelectedResource.FullName)); + } + } + + private void CleanResource() + { + int unknownAssetCount = m_Controller.RemoveUnknownAssets(); + int unusedResourceCount = m_Controller.RemoveUnusedResources(); + RefreshResourceTree(); + + Debug.Log(Utility.Text.Format("Clean complete, {0} unknown assets and {1} unused resources has been removed.", unknownAssetCount, unusedResourceCount)); + } + + private void RefreshResourceTree() + { + m_ResourceRoot.Clear(); + Resource[] resources = m_Controller.GetResources(); + foreach (Resource resource in resources) + { + string[] splitedPath = resource.Name.Split('/'); + ResourceFolder folder = m_ResourceRoot; + for (int i = 0; i < splitedPath.Length - 1; i++) + { + ResourceFolder subFolder = folder.GetFolder(splitedPath[i]); + folder = subFolder == null ? folder.AddFolder(splitedPath[i]) : subFolder; + } + + string fullName = resource.Variant != null ? Utility.Text.Format("{0}.{1}", splitedPath[splitedPath.Length - 1], resource.Variant) : splitedPath[splitedPath.Length - 1]; + folder.AddItem(fullName, resource); + } + } + + private bool IsExpandedResourceFolder(ResourceFolder folder) + { + return m_ExpandedResourceFolderNames.Contains(folder.FromRootPath); + } + + private void SetExpandedResourceFolder(ResourceFolder folder, bool expand) + { + if (expand) + { + m_ExpandedResourceFolderNames.Add(folder.FromRootPath); + } + else + { + m_ExpandedResourceFolderNames.Remove(folder.FromRootPath); + } + } + + private bool IsSelectedAssetInSelectedResource(Asset asset) + { + return m_SelectedAssetsInSelectedResource.Contains(asset); + } + + private void SetSelectedAssetInSelectedResource(Asset asset, bool select) + { + if (select) + { + m_SelectedAssetsInSelectedResource.Add(asset); + } + else + { + m_SelectedAssetsInSelectedResource.Remove(asset); + } + } + + private bool IsExpandedSourceFolder(SourceFolder sourceFolder) + { + return m_ExpandedSourceFolders.Contains(sourceFolder); + } + + private void SetExpandedSourceFolder(SourceFolder sourceFolder, bool expand) + { + if (expand) + { + m_ExpandedSourceFolders.Add(sourceFolder); + } + else + { + m_ExpandedSourceFolders.Remove(sourceFolder); + } + } + + private bool IsSelectedSourceFolder(SourceFolder sourceFolder) + { + if (m_CachedSelectedSourceFolders.Contains(sourceFolder)) + { + return true; + } + + if (m_CachedUnselectedSourceFolders.Contains(sourceFolder)) + { + return false; + } + + foreach (SourceAsset sourceAsset in sourceFolder.GetAssets()) + { + if (m_HideAssignedSourceAssets && IsAssignedSourceAsset(sourceAsset)) + { + continue; + } + + if (!IsSelectedSourceAsset(sourceAsset)) + { + m_CachedUnselectedSourceFolders.Add(sourceFolder); + return false; + } + } + + foreach (SourceFolder subSourceFolder in sourceFolder.GetFolders()) + { + if (m_HideAssignedSourceAssets && IsAssignedSourceFolder(sourceFolder)) + { + continue; + } + + if (!IsSelectedSourceFolder(subSourceFolder)) + { + m_CachedUnselectedSourceFolders.Add(sourceFolder); + return false; + } + } + + m_CachedSelectedSourceFolders.Add(sourceFolder); + return true; + } + + private void SetSelectedSourceFolder(SourceFolder sourceFolder, bool select) + { + if (select) + { + m_CachedSelectedSourceFolders.Add(sourceFolder); + m_CachedUnselectedSourceFolders.Remove(sourceFolder); + + SourceFolder folder = sourceFolder; + while (folder != null) + { + m_CachedUnselectedSourceFolders.Remove(folder); + folder = folder.Folder; + } + } + else + { + m_CachedSelectedSourceFolders.Remove(sourceFolder); + m_CachedUnselectedSourceFolders.Add(sourceFolder); + + SourceFolder folder = sourceFolder; + while (folder != null) + { + m_CachedSelectedSourceFolders.Remove(folder); + folder = folder.Folder; + } + } + + foreach (SourceAsset sourceAsset in sourceFolder.GetAssets()) + { + if (m_HideAssignedSourceAssets && IsAssignedSourceAsset(sourceAsset)) + { + continue; + } + + SetSelectedSourceAsset(sourceAsset, select); + } + + foreach (SourceFolder subSourceFolder in sourceFolder.GetFolders()) + { + if (m_HideAssignedSourceAssets && IsAssignedSourceFolder(subSourceFolder)) + { + continue; + } + + SetSelectedSourceFolder(subSourceFolder, select); + } + } + + private bool IsSelectedSourceAsset(SourceAsset sourceAsset) + { + return m_SelectedSourceAssets.Contains(sourceAsset); + } + + private void SetSelectedSourceAsset(SourceAsset sourceAsset, bool select) + { + if (select) + { + m_SelectedSourceAssets.Add(sourceAsset); + + SourceFolder folder = sourceAsset.Folder; + while (folder != null) + { + m_CachedUnselectedSourceFolders.Remove(folder); + folder = folder.Folder; + } + } + else + { + m_SelectedSourceAssets.Remove(sourceAsset); + + SourceFolder folder = sourceAsset.Folder; + while (folder != null) + { + m_CachedSelectedSourceFolders.Remove(folder); + folder = folder.Folder; + } + } + } + + private bool IsAssignedSourceAsset(SourceAsset sourceAsset) + { + if (m_CachedAssignedSourceAssets.Contains(sourceAsset)) + { + return true; + } + + if (m_CachedUnassignedSourceAssets.Contains(sourceAsset)) + { + return false; + } + + return m_Controller.GetAsset(sourceAsset.Guid) != null; + } + + private bool IsAssignedSourceFolder(SourceFolder sourceFolder) + { + if (m_CachedAssignedSourceFolders.Contains(sourceFolder)) + { + return true; + } + + if (m_CachedUnassignedSourceFolders.Contains(sourceFolder)) + { + return false; + } + + foreach (SourceAsset sourceAsset in sourceFolder.GetAssets()) + { + if (!IsAssignedSourceAsset(sourceAsset)) + { + m_CachedUnassignedSourceFolders.Add(sourceFolder); + return false; + } + } + + foreach (SourceFolder subSourceFolder in sourceFolder.GetFolders()) + { + if (!IsAssignedSourceFolder(subSourceFolder)) + { + m_CachedUnassignedSourceFolders.Add(sourceFolder); + return false; + } + } + + m_CachedAssignedSourceFolders.Add(sourceFolder); + return true; + } + + private HashSet GetSelectedSourceAssets() + { + if (!m_HideAssignedSourceAssets) + { + return m_SelectedSourceAssets; + } + + HashSet selectedUnassignedSourceAssets = new HashSet(); + foreach (SourceAsset sourceAsset in m_SelectedSourceAssets) + { + if (!IsAssignedSourceAsset(sourceAsset)) + { + selectedUnassignedSourceAssets.Add(sourceAsset); + } + } + + return selectedUnassignedSourceAssets; + } + + private string GetResourceFullName(string name, string variant) + { + return variant != null ? Utility.Text.Format("{0}.{1}", name, variant) : name; + } + + private void OnLoadingResource(int index, int count) + { + EditorUtility.DisplayProgressBar("Loading Resources", Utility.Text.Format("Loading resources, {0}/{1} loaded.", index, count), (float)index / count); + } + + private void OnLoadingAsset(int index, int count) + { + EditorUtility.DisplayProgressBar("Loading Assets", Utility.Text.Format("Loading assets, {0}/{1} loaded.", index, count), (float)index / count); + } + + private void OnLoadCompleted() + { + EditorUtility.ClearProgressBar(); + } + + private void OnAssetAssigned(SourceAsset[] sourceAssets) + { + HashSet affectedFolders = new HashSet(); + foreach (SourceAsset sourceAsset in sourceAssets) + { + m_CachedAssignedSourceAssets.Add(sourceAsset); + m_CachedUnassignedSourceAssets.Remove(sourceAsset); + + affectedFolders.Add(sourceAsset.Folder); + } + + foreach (SourceFolder sourceFolder in affectedFolders) + { + SourceFolder folder = sourceFolder; + while (folder != null) + { + m_CachedUnassignedSourceFolders.Remove(folder); + folder = folder.Folder; + } + } + } + + private void OnAssetUnassigned(SourceAsset[] sourceAssets) + { + HashSet affectedFolders = new HashSet(); + foreach (SourceAsset sourceAsset in sourceAssets) + { + m_CachedAssignedSourceAssets.Remove(sourceAsset); + m_CachedUnassignedSourceAssets.Add(sourceAsset); + + affectedFolders.Add(sourceAsset.Folder); + } + + foreach (SourceFolder sourceFolder in affectedFolders) + { + SourceFolder folder = sourceFolder; + while (folder != null) + { + m_CachedSelectedSourceFolders.Remove(folder); + m_CachedAssignedSourceFolders.Remove(folder); + m_CachedUnassignedSourceFolders.Add(folder); + folder = folder.Folder; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.cs.meta new file mode 100644 index 0000000..a3dab36 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 956e53f5acdcb4c40a8ecc68d943dde0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditorConfigPathAttribute.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditorConfigPathAttribute.cs new file mode 100644 index 0000000..fda042c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditorConfigPathAttribute.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// ResourceEditor 配置路径属性。 + /// + public sealed class ResourceEditorConfigPathAttribute : ConfigPathAttribute + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditorConfigPathAttribute.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditorConfigPathAttribute.cs.meta new file mode 100644 index 0000000..0071545 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditorConfigPathAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af287b4a1d99d3946b1aab8f70c78964 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditorController.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditorController.cs new file mode 100644 index 0000000..c53eb60 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditorController.cs @@ -0,0 +1,679 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed class ResourceEditorController + { + private const string DefaultSourceAssetRootPath = "Assets"; + + private readonly string m_ConfigurationPath; + private readonly ResourceCollection m_ResourceCollection; + private readonly List m_SourceAssetSearchPaths; + private readonly List m_SourceAssetSearchRelativePaths; + private readonly Dictionary m_SourceAssets; + private SourceFolder m_SourceAssetRoot; + private string m_SourceAssetRootPath; + private string m_SourceAssetUnionTypeFilter; + private string m_SourceAssetUnionLabelFilter; + private string m_SourceAssetExceptTypeFilter; + private string m_SourceAssetExceptLabelFilter; + private AssetSorterType m_AssetSorter; + + public ResourceEditorController() + { + m_ConfigurationPath = Type.GetConfigurationPath() ?? Utility.Path.GetRegularPath(Path.Combine(Application.dataPath, "GameFramework/Configs/ResourceEditor.xml")); + m_ResourceCollection = new ResourceCollection(); + m_ResourceCollection.OnLoadingResource += delegate (int index, int count) + { + if (OnLoadingResource != null) + { + OnLoadingResource(index, count); + } + }; + + m_ResourceCollection.OnLoadingAsset += delegate (int index, int count) + { + if (OnLoadingAsset != null) + { + OnLoadingAsset(index, count); + } + }; + + m_ResourceCollection.OnLoadCompleted += delegate () + { + if (OnLoadCompleted != null) + { + OnLoadCompleted(); + } + }; + + m_SourceAssetSearchPaths = new List(); + m_SourceAssetSearchRelativePaths = new List(); + m_SourceAssets = new Dictionary(StringComparer.Ordinal); + m_SourceAssetRoot = null; + m_SourceAssetRootPath = null; + m_SourceAssetUnionTypeFilter = null; + m_SourceAssetUnionLabelFilter = null; + m_SourceAssetExceptTypeFilter = null; + m_SourceAssetExceptLabelFilter = null; + m_AssetSorter = AssetSorterType.Path; + + SourceAssetRootPath = DefaultSourceAssetRootPath; + } + + public int ResourceCount + { + get + { + return m_ResourceCollection.ResourceCount; + } + } + + public int AssetCount + { + get + { + return m_ResourceCollection.AssetCount; + } + } + + public SourceFolder SourceAssetRoot + { + get + { + return m_SourceAssetRoot; + } + } + + public string SourceAssetRootPath + { + get + { + return m_SourceAssetRootPath; + } + set + { + if (m_SourceAssetRootPath == value) + { + return; + } + + m_SourceAssetRootPath = value.Replace('\\', '/'); + m_SourceAssetRoot = new SourceFolder(m_SourceAssetRootPath, null); + RefreshSourceAssetSearchPaths(); + } + } + + public string SourceAssetUnionTypeFilter + { + get + { + return m_SourceAssetUnionTypeFilter; + } + set + { + if (m_SourceAssetUnionTypeFilter == value) + { + return; + } + + m_SourceAssetUnionTypeFilter = value; + } + } + + public string SourceAssetUnionLabelFilter + { + get + { + return m_SourceAssetUnionLabelFilter; + } + set + { + if (m_SourceAssetUnionLabelFilter == value) + { + return; + } + + m_SourceAssetUnionLabelFilter = value; + } + } + + public string SourceAssetExceptTypeFilter + { + get + { + return m_SourceAssetExceptTypeFilter; + } + set + { + if (m_SourceAssetExceptTypeFilter == value) + { + return; + } + + m_SourceAssetExceptTypeFilter = value; + } + } + + public string SourceAssetExceptLabelFilter + { + get + { + return m_SourceAssetExceptLabelFilter; + } + set + { + if (m_SourceAssetExceptLabelFilter == value) + { + return; + } + + m_SourceAssetExceptLabelFilter = value; + } + } + + public AssetSorterType AssetSorter + { + get + { + return m_AssetSorter; + } + set + { + if (m_AssetSorter == value) + { + return; + } + + m_AssetSorter = value; + } + } + + public event GameFrameworkAction OnLoadingResource = null; + + public event GameFrameworkAction OnLoadingAsset = null; + + public event GameFrameworkAction OnLoadCompleted = null; + + public event GameFrameworkAction OnAssetAssigned = null; + + public event GameFrameworkAction OnAssetUnassigned = null; + + public bool Load() + { + if (!File.Exists(m_ConfigurationPath)) + { + return false; + } + + try + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load(m_ConfigurationPath); + XmlNode xmlRoot = xmlDocument.SelectSingleNode("UnityGameFramework"); + XmlNode xmlEditor = xmlRoot.SelectSingleNode("ResourceEditor"); + XmlNode xmlSettings = xmlEditor.SelectSingleNode("Settings"); + + XmlNodeList xmlNodeList = null; + XmlNode xmlNode = null; + + xmlNodeList = xmlSettings.ChildNodes; + for (int i = 0; i < xmlNodeList.Count; i++) + { + xmlNode = xmlNodeList.Item(i); + switch (xmlNode.Name) + { + case "SourceAssetRootPath": + SourceAssetRootPath = xmlNode.InnerText; + break; + + case "SourceAssetSearchPaths": + m_SourceAssetSearchRelativePaths.Clear(); + XmlNodeList xmlNodeListInner = xmlNode.ChildNodes; + XmlNode xmlNodeInner = null; + for (int j = 0; j < xmlNodeListInner.Count; j++) + { + xmlNodeInner = xmlNodeListInner.Item(j); + if (xmlNodeInner.Name != "SourceAssetSearchPath") + { + continue; + } + + m_SourceAssetSearchRelativePaths.Add(xmlNodeInner.Attributes.GetNamedItem("RelativePath").Value); + } + break; + + case "SourceAssetUnionTypeFilter": + SourceAssetUnionTypeFilter = xmlNode.InnerText; + break; + + case "SourceAssetUnionLabelFilter": + SourceAssetUnionLabelFilter = xmlNode.InnerText; + break; + + case "SourceAssetExceptTypeFilter": + SourceAssetExceptTypeFilter = xmlNode.InnerText; + break; + + case "SourceAssetExceptLabelFilter": + SourceAssetExceptLabelFilter = xmlNode.InnerText; + break; + + case "AssetSorter": + AssetSorter = (AssetSorterType)Enum.Parse(typeof(AssetSorterType), xmlNode.InnerText); + break; + } + } + + RefreshSourceAssetSearchPaths(); + } + catch + { + File.Delete(m_ConfigurationPath); + return false; + } + + ScanSourceAssets(); + + m_ResourceCollection.Load(); + + return true; + } + + public bool Save() + { + try + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.AppendChild(xmlDocument.CreateXmlDeclaration("1.0", "UTF-8", null)); + + XmlElement xmlRoot = xmlDocument.CreateElement("UnityGameFramework"); + xmlDocument.AppendChild(xmlRoot); + + XmlElement xmlEditor = xmlDocument.CreateElement("ResourceEditor"); + xmlRoot.AppendChild(xmlEditor); + + XmlElement xmlSettings = xmlDocument.CreateElement("Settings"); + xmlEditor.AppendChild(xmlSettings); + + XmlElement xmlElement = null; + XmlAttribute xmlAttribute = null; + + xmlElement = xmlDocument.CreateElement("SourceAssetRootPath"); + xmlElement.InnerText = SourceAssetRootPath.ToString(); + xmlSettings.AppendChild(xmlElement); + + xmlElement = xmlDocument.CreateElement("SourceAssetSearchPaths"); + xmlSettings.AppendChild(xmlElement); + + foreach (string sourceAssetSearchRelativePath in m_SourceAssetSearchRelativePaths) + { + XmlElement xmlElementInner = xmlDocument.CreateElement("SourceAssetSearchPath"); + xmlAttribute = xmlDocument.CreateAttribute("RelativePath"); + xmlAttribute.Value = sourceAssetSearchRelativePath; + xmlElementInner.Attributes.SetNamedItem(xmlAttribute); + xmlElement.AppendChild(xmlElementInner); + } + + xmlElement = xmlDocument.CreateElement("SourceAssetUnionTypeFilter"); + xmlElement.InnerText = SourceAssetUnionTypeFilter ?? string.Empty; + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("SourceAssetUnionLabelFilter"); + xmlElement.InnerText = SourceAssetUnionLabelFilter ?? string.Empty; + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("SourceAssetExceptTypeFilter"); + xmlElement.InnerText = SourceAssetExceptTypeFilter ?? string.Empty; + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("SourceAssetExceptLabelFilter"); + xmlElement.InnerText = SourceAssetExceptLabelFilter ?? string.Empty; + xmlSettings.AppendChild(xmlElement); + xmlElement = xmlDocument.CreateElement("AssetSorter"); + xmlElement.InnerText = AssetSorter.ToString(); + xmlSettings.AppendChild(xmlElement); + + string configurationDirectoryName = Path.GetDirectoryName(m_ConfigurationPath); + if (!Directory.Exists(configurationDirectoryName)) + { + Directory.CreateDirectory(configurationDirectoryName); + } + + xmlDocument.Save(m_ConfigurationPath); + AssetDatabase.Refresh(); + } + catch + { + if (File.Exists(m_ConfigurationPath)) + { + File.Delete(m_ConfigurationPath); + } + + return false; + } + + return m_ResourceCollection.Save(); + } + + public Resource[] GetResources() + { + return m_ResourceCollection.GetResources(); + } + + public Resource GetResource(string name, string variant) + { + return m_ResourceCollection.GetResource(name, variant); + } + + public bool HasResource(string name, string variant) + { + return m_ResourceCollection.HasResource(name, variant); + } + + public bool AddResource(string name, string variant, string fileSystem, LoadType loadType, bool packed, string defaultResourceGroup) + { + return m_ResourceCollection.AddResource(name, variant, fileSystem, loadType, packed, new string[] { defaultResourceGroup }); + } + + public bool RenameResource(string oldName, string oldVariant, string newName, string newVariant) + { + return m_ResourceCollection.RenameResource(oldName, oldVariant, newName, newVariant); + } + + public bool RemoveResource(string name, string variant) + { + Asset[] assetsToRemove = m_ResourceCollection.GetAssets(name, variant); + if (m_ResourceCollection.RemoveResource(name, variant)) + { + List unassignedSourceAssets = new List(); + foreach (Asset asset in assetsToRemove) + { + SourceAsset sourceAsset = GetSourceAsset(asset.Guid); + if (sourceAsset != null) + { + unassignedSourceAssets.Add(sourceAsset); + } + } + + if (OnAssetUnassigned != null) + { + OnAssetUnassigned(unassignedSourceAssets.ToArray()); + } + + return true; + } + + return false; + } + + public bool SetResourceLoadType(string name, string variant, LoadType loadType) + { + return m_ResourceCollection.SetResourceLoadType(name, variant, loadType); + } + + public bool SetResourcePacked(string name, string variant, bool packed) + { + return m_ResourceCollection.SetResourcePacked(name, variant, packed); + } + + public int RemoveUnusedResources() + { + List resources = new List(m_ResourceCollection.GetResources()); + List removeResources = resources.FindAll(resource => GetAssets(resource.Name, resource.Variant).Length <= 0); + foreach (Resource removeResource in removeResources) + { + m_ResourceCollection.RemoveResource(removeResource.Name, removeResource.Variant); + } + + return removeResources.Count; + } + + public Asset[] GetAssets(string name, string variant) + { + List assets = new List(m_ResourceCollection.GetAssets(name, variant)); + switch (AssetSorter) + { + case AssetSorterType.Path: + assets.Sort(AssetPathComparer); + break; + + case AssetSorterType.Name: + assets.Sort(AssetNameComparer); + break; + + case AssetSorterType.Guid: + assets.Sort(AssetGuidComparer); + break; + } + + return assets.ToArray(); + } + + public Asset GetAsset(string guid) + { + return m_ResourceCollection.GetAsset(guid); + } + + public bool AssignAsset(string guid, string name, string variant) + { + if (m_ResourceCollection.AssignAsset(guid, name, variant)) + { + if (OnAssetAssigned != null) + { + OnAssetAssigned(new SourceAsset[] { GetSourceAsset(guid) }); + } + + return true; + } + + return false; + } + + public bool UnassignAsset(string guid) + { + if (m_ResourceCollection.UnassignAsset(guid)) + { + SourceAsset sourceAsset = GetSourceAsset(guid); + if (sourceAsset != null) + { + if (OnAssetUnassigned != null) + { + OnAssetUnassigned(new SourceAsset[] { sourceAsset }); + } + } + + return true; + } + + return false; + } + + public int RemoveUnknownAssets() + { + List assets = new List(m_ResourceCollection.GetAssets()); + List removeAssets = assets.FindAll(asset => GetSourceAsset(asset.Guid) == null); + foreach (Asset asset in removeAssets) + { + m_ResourceCollection.UnassignAsset(asset.Guid); + } + + return removeAssets.Count; + } + + public SourceAsset[] GetSourceAssets() + { + int count = 0; + SourceAsset[] sourceAssets = new SourceAsset[m_SourceAssets.Count]; + foreach (KeyValuePair sourceAsset in m_SourceAssets) + { + sourceAssets[count++] = sourceAsset.Value; + } + + return sourceAssets; + } + + public SourceAsset GetSourceAsset(string guid) + { + if (string.IsNullOrEmpty(guid)) + { + return null; + } + + SourceAsset sourceAsset = null; + if (m_SourceAssets.TryGetValue(guid, out sourceAsset)) + { + return sourceAsset; + } + + return null; + } + + public void ScanSourceAssets() + { + m_SourceAssets.Clear(); + m_SourceAssetRoot.Clear(); + + string[] sourceAssetSearchPaths = m_SourceAssetSearchPaths.ToArray(); + HashSet tempGuids = new HashSet(); + tempGuids.UnionWith(AssetDatabase.FindAssets(SourceAssetUnionTypeFilter, sourceAssetSearchPaths)); + tempGuids.UnionWith(AssetDatabase.FindAssets(SourceAssetUnionLabelFilter, sourceAssetSearchPaths)); + tempGuids.ExceptWith(AssetDatabase.FindAssets(SourceAssetExceptTypeFilter, sourceAssetSearchPaths)); + tempGuids.ExceptWith(AssetDatabase.FindAssets(SourceAssetExceptLabelFilter, sourceAssetSearchPaths)); + + string[] guids = new List(tempGuids).ToArray(); + foreach (string guid in guids) + { + string fullPath = AssetDatabase.GUIDToAssetPath(guid); + if (AssetDatabase.IsValidFolder(fullPath)) + { + // Skip folder. + continue; + } + + string assetPath = fullPath.Substring(SourceAssetRootPath.Length + 1); + string[] splitedPath = assetPath.Split('/'); + SourceFolder folder = m_SourceAssetRoot; + for (int i = 0; i < splitedPath.Length - 1; i++) + { + SourceFolder subFolder = folder.GetFolder(splitedPath[i]); + folder = subFolder == null ? folder.AddFolder(splitedPath[i]) : subFolder; + } + + SourceAsset asset = folder.AddAsset(guid, fullPath, splitedPath[splitedPath.Length - 1]); + m_SourceAssets.Add(asset.Guid, asset); + } + } + + private void RefreshSourceAssetSearchPaths() + { + m_SourceAssetSearchPaths.Clear(); + + if (string.IsNullOrEmpty(m_SourceAssetRootPath)) + { + SourceAssetRootPath = DefaultSourceAssetRootPath; + } + + if (m_SourceAssetSearchRelativePaths.Count > 0) + { + foreach (string sourceAssetSearchRelativePath in m_SourceAssetSearchRelativePaths) + { + m_SourceAssetSearchPaths.Add(Utility.Path.GetRegularPath(Path.Combine(m_SourceAssetRootPath, sourceAssetSearchRelativePath))); + } + } + else + { + m_SourceAssetSearchPaths.Add(m_SourceAssetRootPath); + } + } + + private int AssetPathComparer(Asset a, Asset b) + { + SourceAsset sourceAssetA = GetSourceAsset(a.Guid); + SourceAsset sourceAssetB = GetSourceAsset(b.Guid); + + if (sourceAssetA != null && sourceAssetB != null) + { + return sourceAssetA.Path.CompareTo(sourceAssetB.Path); + } + + if (sourceAssetA == null && sourceAssetB == null) + { + return a.Guid.CompareTo(b.Guid); + } + + if (sourceAssetA == null) + { + return -1; + } + + if (sourceAssetB == null) + { + return 1; + } + + return 0; + } + + private int AssetNameComparer(Asset a, Asset b) + { + SourceAsset sourceAssetA = GetSourceAsset(a.Guid); + SourceAsset sourceAssetB = GetSourceAsset(b.Guid); + + if (sourceAssetA != null && sourceAssetB != null) + { + return sourceAssetA.Name.CompareTo(sourceAssetB.Name); + } + + if (sourceAssetA == null && sourceAssetB == null) + { + return a.Guid.CompareTo(b.Guid); + } + + if (sourceAssetA == null) + { + return -1; + } + + if (sourceAssetB == null) + { + return 1; + } + + return 0; + } + + private int AssetGuidComparer(Asset a, Asset b) + { + SourceAsset sourceAssetA = GetSourceAsset(a.Guid); + SourceAsset sourceAssetB = GetSourceAsset(b.Guid); + + if (sourceAssetA != null && sourceAssetB != null || sourceAssetA == null && sourceAssetB == null) + { + return a.Guid.CompareTo(b.Guid); + } + + if (sourceAssetA == null) + { + return -1; + } + + if (sourceAssetB == null) + { + return 1; + } + + return 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditorController.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditorController.cs.meta new file mode 100644 index 0000000..71601b3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/ResourceEditorController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7c8c042eb5e752f49920cfc09aff81c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/SourceAsset.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/SourceAsset.cs new file mode 100644 index 0000000..1684a59 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/SourceAsset.cs @@ -0,0 +1,85 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed class SourceAsset + { + private Texture m_CachedIcon; + + public SourceAsset(string guid, string path, string name, SourceFolder folder) + { + if (folder == null) + { + throw new GameFrameworkException("Source asset folder is invalid."); + } + + Guid = guid; + Path = path; + Name = name; + Folder = folder; + m_CachedIcon = null; + } + + public string Guid + { + get; + private set; + } + + public string Path + { + get; + private set; + } + + public string Name + { + get; + private set; + } + + public SourceFolder Folder + { + get; + private set; + } + + public string FromRootPath + { + get + { + return Folder.Folder == null ? Name : Utility.Text.Format("{0}/{1}", Folder.FromRootPath, Name); + } + } + + public int Depth + { + get + { + return Folder != null ? Folder.Depth + 1 : 0; + } + } + + public Texture Icon + { + get + { + if (m_CachedIcon == null) + { + m_CachedIcon = AssetDatabase.GetCachedIcon(Path); + } + + return m_CachedIcon; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/SourceAsset.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/SourceAsset.cs.meta new file mode 100644 index 0000000..684ff15 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/SourceAsset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ded5a7d9ccd4b2a409ec840ba3df0b18 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/SourceFolder.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/SourceFolder.cs new file mode 100644 index 0000000..69d974b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/SourceFolder.cs @@ -0,0 +1,172 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed class SourceFolder + { + private static Texture s_CachedIcon = null; + + private readonly List m_Folders; + private readonly List m_Assets; + + public SourceFolder(string name, SourceFolder folder) + { + m_Folders = new List(); + m_Assets = new List(); + + Name = name; + Folder = folder; + } + + public string Name + { + get; + private set; + } + + public SourceFolder Folder + { + get; + private set; + } + + public string FromRootPath + { + get + { + return Folder == null ? string.Empty : (Folder.Folder == null ? Name : Utility.Text.Format("{0}/{1}", Folder.FromRootPath, Name)); + } + } + + public int Depth + { + get + { + return Folder != null ? Folder.Depth + 1 : 0; + } + } + + public static Texture Icon + { + get + { + if (s_CachedIcon == null) + { + s_CachedIcon = AssetDatabase.GetCachedIcon("Assets"); + } + + return s_CachedIcon; + } + } + + public void Clear() + { + m_Folders.Clear(); + m_Assets.Clear(); + } + + public SourceFolder[] GetFolders() + { + return m_Folders.ToArray(); + } + + public SourceFolder GetFolder(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Source folder name is invalid."); + } + + foreach (SourceFolder folder in m_Folders) + { + if (folder.Name == name) + { + return folder; + } + } + + return null; + } + + public SourceFolder AddFolder(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Source folder name is invalid."); + } + + SourceFolder folder = GetFolder(name); + if (folder != null) + { + throw new GameFrameworkException("Source folder is already exist."); + } + + folder = new SourceFolder(name, this); + m_Folders.Add(folder); + + return folder; + } + + public SourceAsset[] GetAssets() + { + return m_Assets.ToArray(); + } + + public SourceAsset GetAsset(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Source asset name is invalid."); + } + + foreach (SourceAsset asset in m_Assets) + { + if (asset.Name == name) + { + return asset; + } + } + + return null; + } + + public SourceAsset AddAsset(string guid, string path, string name) + { + if (string.IsNullOrEmpty(guid)) + { + throw new GameFrameworkException("Source asset guid is invalid."); + } + + if (string.IsNullOrEmpty(path)) + { + throw new GameFrameworkException("Source asset path is invalid."); + } + + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Source asset name is invalid."); + } + + SourceAsset asset = GetAsset(name); + if (asset != null) + { + throw new GameFrameworkException(Utility.Text.Format("Source asset '{0}' is already exist.", name)); + } + + asset = new SourceAsset(guid, path, name, this); + m_Assets.Add(asset); + + return asset; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/SourceFolder.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/SourceFolder.cs.meta new file mode 100644 index 0000000..2732159 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceEditor/SourceFolder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bcb967b558b5d254fb96db1fc5ed808b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder.meta new file mode 100644 index 0000000..c737e64 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3564da2c360cfdb46acffa4b7f42d275 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder/ResourcePackBuilder.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder/ResourcePackBuilder.cs new file mode 100644 index 0000000..60afb3c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder/ResourcePackBuilder.cs @@ -0,0 +1,487 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// 资源包生成器。 + /// + internal sealed class ResourcePackBuilder : EditorWindow + { + private static readonly string[] PlatformForDisplay = new string[] { "Windows", "Windows x64", "macOS", "Linux", "iOS", "Android", "Windows Store", "WebGL" }; + private static readonly int[] LengthLimit = new int[] { 0, 128, 256, 512, 1024, 2048, 4096 }; + private static readonly string[] LengthLimitForDisplay = new string[] { "", "128 MB", "256 MB", "512 MB", "1 GB", "2 GB", "4 GB", "" }; + + private ResourcePackBuilderController m_Controller = null; + private string[] m_VersionNames = null; + private string[] m_VersionNamesForTargetDisplay = null; + private string[] m_VersionNamesForSourceDisplay = null; + private int m_PlatformIndex = 0; + private int m_CompressionHelperTypeNameIndex = 0; + private int m_LengthLimitIndex = 0; + private int m_TargetVersionIndex = 0; + private bool[] m_SourceVersionIndexes = null; + private int m_SourceVersionCount = 0; + + [MenuItem("Game Framework/Resource Tools/Resource Pack Builder", false, 43)] + private static void Open() + { + ResourcePackBuilder window = GetWindow("Resource Pack Builder", true); + window.minSize = new Vector2(800f, 400f); + } + + private void OnEnable() + { + m_Controller = new ResourcePackBuilderController(); + m_Controller.OnBuildResourcePacksStarted += OnBuildResourcePacksStarted; + m_Controller.OnBuildResourcePacksCompleted += OnBuildResourcePacksCompleted; + m_Controller.OnBuildResourcePackSuccess += OnBuildResourcePackSuccess; + m_Controller.OnBuildResourcePackFailure += OnBuildResourcePackFailure; + + m_Controller.Load(); + RefreshVersionNames(); + + m_CompressionHelperTypeNameIndex = 0; + string[] compressionHelperTypeNames = m_Controller.GetCompressionHelperTypeNames(); + for (int i = 0; i < compressionHelperTypeNames.Length; i++) + { + if (m_Controller.CompressionHelperTypeName == compressionHelperTypeNames[i]) + { + m_CompressionHelperTypeNameIndex = i; + break; + } + } + + m_Controller.RefreshCompressionHelper(); + } + + private void Update() + { + } + + private void OnGUI() + { + EditorGUILayout.BeginVertical(GUILayout.Width(position.width), GUILayout.Height(position.height)); + { + GUILayout.Space(5f); + EditorGUILayout.LabelField("Environment Information", EditorStyles.boldLabel); + EditorGUILayout.BeginVertical("box"); + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Product Name", GUILayout.Width(160f)); + EditorGUILayout.LabelField(m_Controller.ProductName); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Company Name", GUILayout.Width(160f)); + EditorGUILayout.LabelField(m_Controller.CompanyName); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Game Identifier", GUILayout.Width(160f)); + EditorGUILayout.LabelField(m_Controller.GameIdentifier); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Game Framework Version", GUILayout.Width(160f)); + EditorGUILayout.LabelField(m_Controller.GameFrameworkVersion); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Unity Version", GUILayout.Width(160f)); + EditorGUILayout.LabelField(m_Controller.UnityVersion); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Applicable Game Version", GUILayout.Width(160f)); + EditorGUILayout.LabelField(m_Controller.ApplicableGameVersion); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + GUILayout.Space(5f); + EditorGUILayout.LabelField("Build", EditorStyles.boldLabel); + EditorGUILayout.BeginVertical("box"); + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Working Directory", GUILayout.Width(160f)); + string directory = EditorGUILayout.TextField(m_Controller.WorkingDirectory); + if (m_Controller.WorkingDirectory != directory) + { + m_Controller.WorkingDirectory = directory; + RefreshVersionNames(); + } + if (GUILayout.Button("Browse...", GUILayout.Width(80f))) + { + BrowseWorkingDirectory(); + RefreshVersionNames(); + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Platform", GUILayout.Width(160f)); + int platformIndex = EditorGUILayout.Popup(m_PlatformIndex, PlatformForDisplay); + if (m_PlatformIndex != platformIndex) + { + m_PlatformIndex = platformIndex; + m_Controller.Platform = (Platform)(1 << platformIndex); + RefreshVersionNames(); + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Compression Helper", GUILayout.Width(160f)); + string[] names = m_Controller.GetCompressionHelperTypeNames(); + int selectedIndex = EditorGUILayout.Popup(m_CompressionHelperTypeNameIndex, names); + if (selectedIndex != m_CompressionHelperTypeNameIndex) + { + m_CompressionHelperTypeNameIndex = selectedIndex; + m_Controller.CompressionHelperTypeName = selectedIndex <= 0 ? string.Empty : names[selectedIndex]; + if (m_Controller.RefreshCompressionHelper()) + { + Debug.Log("Set compression helper success."); + } + else + { + Debug.LogWarning("Set compression helper failure."); + } + } + } + EditorGUILayout.EndHorizontal(); + if (m_Controller.Platform == Platform.Undefined || string.IsNullOrEmpty(m_Controller.CompressionHelperTypeName) || !m_Controller.IsValidWorkingDirectory) + { + string message = string.Empty; + if (!m_Controller.IsValidWorkingDirectory) + { + if (!string.IsNullOrEmpty(message)) + { + message += Environment.NewLine; + } + + message += "Working directory is invalid."; + } + + if (m_Controller.Platform == Platform.Undefined) + { + if (!string.IsNullOrEmpty(message)) + { + message += Environment.NewLine; + } + + message += "Platform is invalid."; + } + + if (string.IsNullOrEmpty(m_Controller.CompressionHelperTypeName)) + { + if (!string.IsNullOrEmpty(message)) + { + message += Environment.NewLine; + } + + message += "Compression helper is invalid."; + } + + EditorGUILayout.HelpBox(message, MessageType.Error); + } + else if (m_VersionNamesForTargetDisplay.Length <= 0) + { + EditorGUILayout.HelpBox("No version was found in the specified working directory and platform.", MessageType.Warning); + } + else + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Source Path", GUILayout.Width(160f)); + GUILayout.Label(m_Controller.SourcePathForDisplay); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Output Path", GUILayout.Width(160f)); + GUILayout.Label(m_Controller.OutputPath); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Backup Diff", GUILayout.Width(160f)); + m_Controller.BackupDiff = EditorGUILayout.Toggle(m_Controller.BackupDiff); + } + EditorGUILayout.EndHorizontal(); + if (m_Controller.BackupDiff) + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Backup Version", GUILayout.Width(160f)); + m_Controller.BackupVersion = EditorGUILayout.Toggle(m_Controller.BackupVersion); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Length Limit", GUILayout.Width(160f)); + EditorGUILayout.BeginVertical(); + { + int lengthLimitIndex = EditorGUILayout.Popup(m_LengthLimitIndex, LengthLimitForDisplay); + if (m_LengthLimitIndex != lengthLimitIndex) + { + m_LengthLimitIndex = lengthLimitIndex; + if (m_LengthLimitIndex < LengthLimit.Length) + { + m_Controller.LengthLimit = LengthLimit[m_LengthLimitIndex]; + } + } + + if (m_LengthLimitIndex >= LengthLimit.Length) + { + EditorGUILayout.BeginHorizontal(); + { + m_Controller.LengthLimit = EditorGUILayout.IntField(m_Controller.LengthLimit); + if (m_Controller.LengthLimit < 0) + { + m_Controller.LengthLimit = 0; + } + + GUILayout.Label(" MB", GUILayout.Width(30f)); + } + EditorGUILayout.EndHorizontal(); + } + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Target Version", GUILayout.Width(160f)); + int value = EditorGUILayout.Popup(m_TargetVersionIndex, m_VersionNamesForTargetDisplay); + if (m_TargetVersionIndex != value) + { + m_TargetVersionIndex = value; + RefreshSourceVersionCount(); + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField("Source Version", GUILayout.Width(160f)); + EditorGUILayout.BeginVertical(); + { + EditorGUILayout.BeginHorizontal(); + { + EditorGUILayout.LabelField(m_SourceVersionCount.ToString() + (m_SourceVersionCount > 1 ? " items" : " item") + " selected."); + if (GUILayout.Button("Select All Except ", GUILayout.Width(180f))) + { + m_SourceVersionIndexes[0] = false; + for (int i = 1; i < m_SourceVersionIndexes.Length; i++) + { + m_SourceVersionIndexes[i] = true; + } + + RefreshSourceVersionCount(); + } + if (GUILayout.Button("Select All", GUILayout.Width(100f))) + { + for (int i = 0; i < m_SourceVersionIndexes.Length; i++) + { + m_SourceVersionIndexes[i] = true; + } + + RefreshSourceVersionCount(); + } + if (GUILayout.Button("Select None", GUILayout.Width(100f))) + { + for (int i = 0; i < m_SourceVersionIndexes.Length; i++) + { + m_SourceVersionIndexes[i] = false; + } + + RefreshSourceVersionCount(); + } + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + { + int count = m_VersionNamesForSourceDisplay.Length; + int column = 5; + int row = (count - 1) / column + 1; + for (int i = 0; i < column && i < count; i++) + { + EditorGUILayout.BeginVertical(); + { + for (int j = 0; j < row; j++) + { + int index = j * column + i; + if (index < count) + { + bool isTarget = index - 1 == m_TargetVersionIndex; + EditorGUI.BeginDisabledGroup(isTarget); + { + bool selected = GUILayout.Toggle(m_SourceVersionIndexes[index], isTarget ? m_VersionNamesForSourceDisplay[index] + " [Target]" : m_VersionNamesForSourceDisplay[index], "button"); + if (m_SourceVersionIndexes[index] != selected) + { + m_SourceVersionIndexes[index] = selected; + RefreshSourceVersionCount(); + } + } + EditorGUI.EndDisabledGroup(); + } + } + } + EditorGUILayout.EndVertical(); + } + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + } + EditorGUILayout.EndHorizontal(); + } + GUILayout.Space(2f); + } + EditorGUILayout.EndVertical(); + GUILayout.Space(2f); + EditorGUILayout.BeginHorizontal(); + { + EditorGUI.BeginDisabledGroup(m_Controller.Platform == Platform.Undefined || string.IsNullOrEmpty(m_Controller.CompressionHelperTypeName) || !m_Controller.IsValidWorkingDirectory || m_SourceVersionCount <= 0); + { + if (GUILayout.Button("Start Build Resource Packs")) + { + string[] sourceVersions = new string[m_SourceVersionCount]; + int count = 0; + for (int i = 0; i < m_SourceVersionIndexes.Length; i++) + { + if (m_SourceVersionIndexes[i]) + { + sourceVersions[count++] = i > 0 ? m_VersionNames[i - 1] : null; + } + } + + m_Controller.BuildResourcePacks(sourceVersions, m_VersionNames[m_TargetVersionIndex]); + } + } + EditorGUI.EndDisabledGroup(); + } + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndVertical(); + } + + private void BrowseWorkingDirectory() + { + string directory = EditorUtility.OpenFolderPanel("Select Working Directory", m_Controller.WorkingDirectory, string.Empty); + if (!string.IsNullOrEmpty(directory)) + { + m_Controller.WorkingDirectory = directory; + } + } + + private void RefreshVersionNames() + { + m_VersionNames = m_Controller.GetVersionNames(); + m_VersionNamesForTargetDisplay = new string[m_VersionNames.Length]; + m_VersionNamesForSourceDisplay = new string[m_VersionNames.Length + 1]; + m_VersionNamesForSourceDisplay[0] = ""; + for (int i = 0; i < m_VersionNames.Length; i++) + { + string versionNameForDisplay = GetVersionNameForDisplay(m_VersionNames[i]); + m_VersionNamesForTargetDisplay[i] = versionNameForDisplay; + m_VersionNamesForSourceDisplay[i + 1] = versionNameForDisplay; + } + + m_TargetVersionIndex = m_VersionNames.Length - 1; + m_SourceVersionIndexes = new bool[m_VersionNames.Length + 1]; + m_SourceVersionCount = 0; + } + + private void RefreshSourceVersionCount() + { + m_SourceVersionIndexes[m_TargetVersionIndex + 1] = false; + m_SourceVersionCount = 0; + if (m_SourceVersionIndexes == null) + { + return; + } + + for (int i = 0; i < m_SourceVersionIndexes.Length; i++) + { + if (m_SourceVersionIndexes[i]) + { + m_SourceVersionCount++; + } + } + } + + private string GetVersionNameForDisplay(string versionName) + { + if (string.IsNullOrEmpty(versionName)) + { + return ""; + } + + string[] splitedVersionNames = versionName.Split('_'); + if (splitedVersionNames.Length < 2) + { + return null; + } + + string text = splitedVersionNames[0]; + for (int i = 1; i < splitedVersionNames.Length - 1; i++) + { + text += "." + splitedVersionNames[i]; + } + + return Utility.Text.Format("{0} ({1})", text, splitedVersionNames[splitedVersionNames.Length - 1]); + } + + private void OnBuildResourcePacksStarted(int count) + { + Debug.Log(Utility.Text.Format("Build resource packs started, '{0}' items to be built.", count)); + EditorUtility.DisplayProgressBar("Build Resource Packs", Utility.Text.Format("Build resource packs, {0} items to be built.", count), 0f); + } + + private void OnBuildResourcePacksCompleted(int successCount, int count) + { + int failureCount = count - successCount; + string str = Utility.Text.Format("Build resource packs completed, '{0}' items, '{1}' success, '{2}' failure.", count, successCount, failureCount); + if (failureCount > 0) + { + Debug.LogWarning(str); + } + else + { + Debug.Log(str); + } + + EditorUtility.ClearProgressBar(); + } + + private void OnBuildResourcePackSuccess(int index, int count, string sourceVersion, string targetVersion) + { + Debug.Log(Utility.Text.Format("Build resource packs success, source version '{0}', target version '{1}'.", GetVersionNameForDisplay(sourceVersion), GetVersionNameForDisplay(targetVersion))); + EditorUtility.DisplayProgressBar("Build Resource Packs", Utility.Text.Format("Build resource packs, {0}/{1} completed.", index + 1, count), (float)index / count); + } + + private void OnBuildResourcePackFailure(int index, int count, string sourceVersion, string targetVersion) + { + Debug.LogWarning(Utility.Text.Format("Build resource packs failure, source version '{0}', target version '{1}'.", GetVersionNameForDisplay(sourceVersion), GetVersionNameForDisplay(targetVersion))); + EditorUtility.DisplayProgressBar("Build Resource Packs", Utility.Text.Format("Build resource packs, {0}/{1} completed.", index + 1, count), (float)index / count); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder/ResourcePackBuilder.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder/ResourcePackBuilder.cs.meta new file mode 100644 index 0000000..8cbf15a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder/ResourcePackBuilder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e260afdf322bd1f4897314c0d2c777d7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder/ResourcePackBuilderController.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder/ResourcePackBuilderController.cs new file mode 100644 index 0000000..477d73f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder/ResourcePackBuilderController.cs @@ -0,0 +1,558 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Resource; +using System; +using System.Collections.Generic; +using System.IO; +using System.Xml; +using UnityEditor; +using UnityEngine; +using UnityGameFramework.Runtime; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed class ResourcePackBuilderController + { + private const string DefaultResourcePackName = "GameFrameworkResourcePack"; + private const string DefaultExtension = "dat"; + private const string NoneOptionName = ""; + private static readonly string[] EmptyStringArray = new string[0]; + private static readonly UpdatableVersionList.Resource[] EmptyResourceArray = new UpdatableVersionList.Resource[0]; + + private readonly string m_ConfigurationPath; + private readonly List m_CompressionHelperTypeNames; + private readonly UpdatableVersionListSerializer m_UpdatableVersionListSerializer; + private readonly ResourcePackVersionListSerializer m_ResourcePackVersionListSerializer; + + public ResourcePackBuilderController() + { + m_ConfigurationPath = Type.GetConfigurationPath() ?? Utility.Path.GetRegularPath(Path.Combine(Application.dataPath, "GameFramework/Configs/ResourceBuilder.xml")); + + m_UpdatableVersionListSerializer = new UpdatableVersionListSerializer(); + m_UpdatableVersionListSerializer.RegisterDeserializeCallback(0, BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback_V0); + m_UpdatableVersionListSerializer.RegisterDeserializeCallback(1, BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback_V1); + m_UpdatableVersionListSerializer.RegisterDeserializeCallback(2, BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback_V2); + + m_ResourcePackVersionListSerializer = new ResourcePackVersionListSerializer(); + m_ResourcePackVersionListSerializer.RegisterSerializeCallback(0, BuiltinVersionListSerializer.ResourcePackVersionListSerializeCallback_V0); + + m_CompressionHelperTypeNames = new List + { + NoneOptionName + }; + + m_CompressionHelperTypeNames.AddRange(Type.GetRuntimeOrEditorTypeNames(typeof(Utility.Compression.ICompressionHelper))); + + Platform = Platform.Windows; + CompressionHelperTypeName = string.Empty; + } + + public string ProductName + { + get + { + return PlayerSettings.productName; + } + } + + public string CompanyName + { + get + { + return PlayerSettings.companyName; + } + } + + public string GameIdentifier + { + get + { +#if UNITY_5_6_OR_NEWER + return PlayerSettings.applicationIdentifier; +#else + return PlayerSettings.bundleIdentifier; +#endif + } + } + + public string GameFrameworkVersion + { + get + { + return GameFramework.Version.GameFrameworkVersion; + } + } + + public string UnityVersion + { + get + { + return Application.unityVersion; + } + } + + public string ApplicableGameVersion + { + get + { + return Application.version; + } + } + + public string WorkingDirectory + { + get; + set; + } + + public Platform Platform + { + get; + set; + } + + public string CompressionHelperTypeName + { + get; + set; + } + + public bool BackupDiff + { + get; + set; + } + + public bool BackupVersion + { + get; + set; + } + + public int LengthLimit + { + get; + set; + } + + public bool IsValidWorkingDirectory + { + get + { + if (string.IsNullOrEmpty(WorkingDirectory)) + { + return false; + } + + if (!Directory.Exists(WorkingDirectory)) + { + return false; + } + + return true; + } + } + + public string SourcePath + { + get + { + if (!IsValidWorkingDirectory) + { + return string.Empty; + } + + return Utility.Path.GetRegularPath(new DirectoryInfo(Utility.Text.Format("{0}/Full/", WorkingDirectory)).FullName); + } + } + + public string SourcePathForDisplay + { + get + { + if (!IsValidWorkingDirectory) + { + return string.Empty; + } + + return Utility.Path.GetRegularPath(new DirectoryInfo(Utility.Text.Format("{0}/Full/*/{1}/", WorkingDirectory, Platform)).FullName); + } + } + + public string OutputPath + { + get + { + if (!IsValidWorkingDirectory) + { + return string.Empty; + } + + return Utility.Path.GetRegularPath(new DirectoryInfo(Utility.Text.Format("{0}/ResourcePack/{1}/", WorkingDirectory, Platform)).FullName); + } + } + + public event GameFrameworkAction OnBuildResourcePacksStarted = null; + + public event GameFrameworkAction OnBuildResourcePacksCompleted = null; + + public event GameFrameworkAction OnBuildResourcePackSuccess = null; + + public event GameFrameworkAction OnBuildResourcePackFailure = null; + + public bool Load() + { + if (!File.Exists(m_ConfigurationPath)) + { + return false; + } + + try + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load(m_ConfigurationPath); + XmlNode xmlRoot = xmlDocument.SelectSingleNode("UnityGameFramework"); + XmlNode xmlEditor = xmlRoot.SelectSingleNode("ResourceBuilder"); + XmlNode xmlSettings = xmlEditor.SelectSingleNode("Settings"); + + XmlNodeList xmlNodeList = null; + XmlNode xmlNode = null; + + xmlNodeList = xmlSettings.ChildNodes; + for (int i = 0; i < xmlNodeList.Count; i++) + { + xmlNode = xmlNodeList.Item(i); + switch (xmlNode.Name) + { + case "CompressionHelperTypeName": + CompressionHelperTypeName = xmlNode.InnerText; + break; + + case "OutputDirectory": + WorkingDirectory = xmlNode.InnerText; + break; + } + } + } + catch + { + return false; + } + + return true; + } + + public string[] GetCompressionHelperTypeNames() + { + return m_CompressionHelperTypeNames.ToArray(); + } + + public string[] GetVersionNames() + { + if (Platform == Platform.Undefined || !IsValidWorkingDirectory) + { + return EmptyStringArray; + } + + string platformName = Platform.ToString(); + DirectoryInfo sourceDirectoryInfo = new DirectoryInfo(SourcePath); + if (!sourceDirectoryInfo.Exists) + { + return EmptyStringArray; + } + + List versionNames = new List(); + foreach (DirectoryInfo directoryInfo in sourceDirectoryInfo.GetDirectories()) + { + string[] splitedVersionNames = directoryInfo.Name.Split('_'); + if (splitedVersionNames.Length < 2) + { + continue; + } + + bool invalid = false; + int value = 0; + for (int i = 0; i < splitedVersionNames.Length; i++) + { + if (!int.TryParse(splitedVersionNames[i], out value)) + { + invalid = true; + break; + } + } + + if (invalid) + { + continue; + } + + DirectoryInfo platformDirectoryInfo = new DirectoryInfo(Path.Combine(directoryInfo.FullName, platformName)); + if (!platformDirectoryInfo.Exists) + { + continue; + } + + FileInfo[] versionListFiles = platformDirectoryInfo.GetFiles("GameFrameworkVersion.*.dat", SearchOption.TopDirectoryOnly); + if (versionListFiles.Length != 1) + { + continue; + } + + versionNames.Add(directoryInfo.Name); + } + + versionNames.Sort((x, y) => + { + return int.Parse(x.Substring(x.LastIndexOf('_') + 1)).CompareTo(int.Parse(y.Substring(y.LastIndexOf('_') + 1))); + }); + + return versionNames.ToArray(); + } + + public bool RefreshCompressionHelper() + { + bool retVal = false; + if (!string.IsNullOrEmpty(CompressionHelperTypeName) && m_CompressionHelperTypeNames.Contains(CompressionHelperTypeName)) + { + System.Type compressionHelperType = Utility.Assembly.GetType(CompressionHelperTypeName); + if (compressionHelperType != null) + { + Utility.Compression.ICompressionHelper compressionHelper = (Utility.Compression.ICompressionHelper)Activator.CreateInstance(compressionHelperType); + if (compressionHelper != null) + { + Utility.Compression.SetCompressionHelper(compressionHelper); + return true; + } + } + } + else + { + retVal = true; + } + + CompressionHelperTypeName = string.Empty; + Utility.Compression.SetCompressionHelper(null); + return retVal; + } + + public void BuildResourcePacks(string[] sourceVersions, string targetVersion) + { + int count = sourceVersions.Length; + if (OnBuildResourcePacksStarted != null) + { + OnBuildResourcePacksStarted(count); + } + + int successCount = 0; + for (int i = 0; i < count; i++) + { + if (BuildResourcePack(sourceVersions[i], targetVersion)) + { + successCount++; + if (OnBuildResourcePackSuccess != null) + { + OnBuildResourcePackSuccess(i, count, sourceVersions[i], targetVersion); + } + } + else + { + if (OnBuildResourcePackFailure != null) + { + OnBuildResourcePackFailure(i, count, sourceVersions[i], targetVersion); + } + } + } + + if (OnBuildResourcePacksCompleted != null) + { + OnBuildResourcePacksCompleted(successCount, count); + } + } + + public bool BuildResourcePack(string sourceVersion, string targetVersion) + { + try + { + if (!Directory.Exists(OutputPath)) + { + Directory.CreateDirectory(OutputPath); + } + + string defaultBackupDiffPath = Path.Combine(OutputPath, DefaultResourcePackName); + string defaultResourcePackName = Utility.Text.Format("{0}.{1}", defaultBackupDiffPath, DefaultExtension); + if (File.Exists(defaultResourcePackName)) + { + File.Delete(defaultResourcePackName); + } + + if (BackupDiff) + { + if (Directory.Exists(defaultBackupDiffPath)) + { + Directory.Delete(defaultBackupDiffPath, true); + } + + Directory.CreateDirectory(defaultBackupDiffPath); + } + + UpdatableVersionList sourceUpdatableVersionList = default(UpdatableVersionList); + if (sourceVersion != null) + { + DirectoryInfo sourceDirectoryInfo = new DirectoryInfo(Path.Combine(Path.Combine(SourcePath, sourceVersion), Platform.ToString())); + FileInfo[] sourceVersionListFiles = sourceDirectoryInfo.GetFiles("GameFrameworkVersion.*.dat", SearchOption.TopDirectoryOnly); + byte[] sourceVersionListBytes = File.ReadAllBytes(sourceVersionListFiles[0].FullName); + sourceVersionListBytes = Utility.Compression.Decompress(sourceVersionListBytes); + using (Stream stream = new MemoryStream(sourceVersionListBytes)) + { + sourceUpdatableVersionList = m_UpdatableVersionListSerializer.Deserialize(stream); + } + } + + UpdatableVersionList targetUpdatableVersionList = default(UpdatableVersionList); + DirectoryInfo targetDirectoryInfo = new DirectoryInfo(Path.Combine(Path.Combine(SourcePath, targetVersion), Platform.ToString())); + FileInfo[] targetVersionListFiles = targetDirectoryInfo.GetFiles("GameFrameworkVersion.*.dat", SearchOption.TopDirectoryOnly); + byte[] targetVersionListBytes = File.ReadAllBytes(targetVersionListFiles[0].FullName); + targetVersionListBytes = Utility.Compression.Decompress(targetVersionListBytes); + using (Stream stream = new MemoryStream(targetVersionListBytes)) + { + targetUpdatableVersionList = m_UpdatableVersionListSerializer.Deserialize(stream); + } + + List resources = new List(); + UpdatableVersionList.Resource[] sourceResources = sourceUpdatableVersionList.IsValid ? sourceUpdatableVersionList.GetResources() : EmptyResourceArray; + UpdatableVersionList.Resource[] targetResources = targetUpdatableVersionList.GetResources(); + long offset = 0L; + foreach (UpdatableVersionList.Resource targetResource in targetResources) + { + bool ready = false; + foreach (UpdatableVersionList.Resource sourceResource in sourceResources) + { + if (sourceResource.Name != targetResource.Name || sourceResource.Variant != targetResource.Variant || sourceResource.Extension != targetResource.Extension) + { + continue; + } + + if (sourceResource.LoadType == targetResource.LoadType && sourceResource.Length == targetResource.Length && sourceResource.HashCode == targetResource.HashCode) + { + ready = true; + } + + break; + } + + if (!ready) + { + resources.Add(new ResourcePackVersionList.Resource(targetResource.Name, targetResource.Variant, targetResource.Extension, targetResource.LoadType, offset, targetResource.Length, targetResource.HashCode, targetResource.CompressedLength, targetResource.CompressedHashCode)); + offset += targetResource.CompressedLength; + } + } + + ResourcePackVersionList.Resource[] resourceArray = resources.ToArray(); + using (FileStream fileStream = new FileStream(defaultResourcePackName, FileMode.Create, FileAccess.Write)) + { + if (!m_ResourcePackVersionListSerializer.Serialize(fileStream, new ResourcePackVersionList(0, 0L, 0, resourceArray))) + { + return false; + } + } + + int position = 0; + int hashCode = 0; + string targetDirectoryPath = targetDirectoryInfo.FullName; + using (FileStream fileStream = new FileStream(defaultResourcePackName, FileMode.Open, FileAccess.ReadWrite)) + { + position = (int)fileStream.Length; + fileStream.Position = position; + foreach (ResourcePackVersionList.Resource resource in resourceArray) + { + string resourceName = Path.Combine(targetDirectoryPath, GetResourceFullName(resource.Name, resource.Variant, resource.HashCode)); + if (!File.Exists(resourceName)) + { + return false; + } + + byte[] resourceBytes = File.ReadAllBytes(resourceName); + fileStream.Write(resourceBytes, 0, resourceBytes.Length); + if (BackupDiff) + { + string backupDiffName = Path.Combine(defaultBackupDiffPath, GetResourceFullName(resource.Name, resource.Variant, resource.HashCode)); + string directoryName = Path.GetDirectoryName(backupDiffName); + if (!Directory.Exists(directoryName)) + { + Directory.CreateDirectory(directoryName); + } + + File.WriteAllBytes(backupDiffName, resourceBytes); + } + } + + if (fileStream.Position - position != offset) + { + return false; + } + + fileStream.Position = position; + hashCode = Utility.Verifier.GetCrc32(fileStream); + + fileStream.Position = 0L; + if (!m_ResourcePackVersionListSerializer.Serialize(fileStream, new ResourcePackVersionList(position, offset, hashCode, resourceArray))) + { + return false; + } + } + + string backupDiffPath = Path.Combine(OutputPath, Utility.Text.Format("{0}-{1}-{2}", DefaultResourcePackName, sourceVersion ?? GetNoneVersion(targetVersion), targetVersion)); + string resourcePackName = Utility.Text.Format("{0}.{1:x8}.{2}", backupDiffPath, hashCode, DefaultExtension); + if (File.Exists(resourcePackName)) + { + File.Delete(resourcePackName); + } + + File.Move(defaultResourcePackName, resourcePackName); + + if (BackupDiff) + { + if (BackupVersion) + { + File.Copy(targetVersionListFiles[0].FullName, Path.Combine(defaultBackupDiffPath, Path.GetFileName(targetVersionListFiles[0].FullName))); + } + + if (Directory.Exists(backupDiffPath)) + { + Directory.Delete(backupDiffPath, true); + } + + Directory.Move(defaultBackupDiffPath, backupDiffPath); + } + + return true; + } + catch + { + return false; + } + } + + private string GetNoneVersion(string targetVersion) + { + string[] splitedVersionNames = targetVersion.Split('_'); + for (int i = 0; i < splitedVersionNames.Length; i++) + { + splitedVersionNames[i] = "0"; + } + + return string.Join("_", splitedVersionNames); + } + + private string GetResourceFullName(string name, string variant, int hashCode) + { + return !string.IsNullOrEmpty(variant) ? Utility.Text.Format("{0}.{1}.{2:x8}.{3}", name, variant, hashCode, DefaultExtension) : Utility.Text.Format("{0}.{1:x8}.{2}", name, hashCode, DefaultExtension); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder/ResourcePackBuilderController.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder/ResourcePackBuilderController.cs.meta new file mode 100644 index 0000000..ddf0964 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourcePackBuilder/ResourcePackBuilderController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 886e7d3c19662474caeb030f5b2d9a4e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor.meta new file mode 100644 index 0000000..41a0c4a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3982ac755082c4942a88de7da90a7884 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditor.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditor.cs new file mode 100644 index 0000000..6d00d2e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditor.cs @@ -0,0 +1,803 @@ +using GameFramework; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEditor.Callbacks; +using UnityEditorInternal; +using UnityEngine; +using UnityGameFramework.Editor.ResourceTools; +using static UnityEditor.UIElements.ToolbarMenu; +using GFResource = UnityGameFramework.Editor.ResourceTools.Resource; + +namespace StarForce.Editor.ResourceTools +{ + /// + /// Resource 规则编辑器,支持按规则配置自动生成 ResourceCollection.xml + /// + public class ResourceRuleEditor : EditorWindow + { + private readonly string m_NormalConfigurationPath = "Assets/GameMain/Configs/ResourceRuleEditor.asset"; + private ResourceRuleEditorData m_Configuration; + private ResourceCollection m_ResourceCollection; + + private ReorderableList m_RuleList; + private Vector2 m_ScrollPosition = Vector2.zero; + + private string m_SourceAssetExceptTypeFilter = "t:Script"; + private string[] m_SourceAssetExceptTypeFilterGUIDArray; + + private string m_SourceAssetExceptLabelFilter = "l:ResourceExclusive"; + private string[] m_SourceAssetExceptLabelFilterGUIDArray; + + [MenuItem("Game Framework/Resource Tools/Resource Rule Editor", false, 50)] + static void Open() + { + ResourceRuleEditor window = GetWindow(true, "Resource Rule Editor", true); + window.minSize = new Vector2(1555f, 420f); + } + + [OnOpenAsset] + public static bool OnOpenAsset (int instanceID, int line) + { + var config = EditorUtility.InstanceIDToObject (instanceID) as ResourceRuleEditorData; + if (config != null) + { + ResourceRuleEditor window = GetWindow(true, "Resource Rule Editor", true); + window.minSize = new Vector2(1555f, 420f); + window.m_CurrentConfigPath = AssetDatabase.GetAssetPath(config); + window.Load(); + return true; + } + return false; // we did not handle the open + } + void OnSelectionChange () + { + var config = Selection.activeObject as ResourceRuleEditorData; + if (config != null && config != m_Configuration) + { + m_CurrentConfigPath = AssetDatabase.GetAssetPath(config); + Load(); + GetWindow().Focus(); + } + } + + private void OnGUI() + { + if (m_Configuration == null) + { + Load(); + } + + if (m_RuleList == null) + { + InitRuleListDrawer(); + } + + GUILayout.BeginHorizontal(EditorStyles.toolbar); + { + if (GUILayout.Button("Add", EditorStyles.toolbarButton)) + { + Add(); + } + + if (GUILayout.Button("Save", EditorStyles.toolbarButton)) + { + Save(); + } + + if (GUILayout.Button("Refresh ResourceCollection.xml", EditorStyles.toolbarButton)) + { + RefreshResourceCollection(); + } + } + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + { + GUILayout.Space(10); + OnListElementLabelGUI(); + } + GUILayout.EndHorizontal(); + + + GUILayout.BeginVertical(); + { + GUILayout.Space(30); + + m_ScrollPosition = GUILayout.BeginScrollView(m_ScrollPosition); + { + m_RuleList.DoLayoutList(); + } + GUILayout.EndScrollView(); + } + GUILayout.EndVertical(); + + if (GUI.changed) + EditorUtility.SetDirty(m_Configuration); + } + + private void Load() + { + m_AllConfigPaths = AssetDatabase.FindAssets("t:ResourceRuleEditorData").Select(AssetDatabase.GUIDToAssetPath).ToList(); + m_ConfigNames = m_AllConfigPaths.Select(Path.GetFileNameWithoutExtension).ToArray(); + + m_Configuration = LoadAssetAtPath(m_CurrentConfigPath); + if (m_Configuration == null) + { + if (m_AllConfigPaths.Count == 0) + { + m_Configuration = ScriptableObject.CreateInstance(); + m_CurrentConfigPath = m_NormalConfigurationPath; + m_AllConfigPaths = new List() { m_NormalConfigurationPath }; + m_ConfigNames = new [] { Path.GetFileNameWithoutExtension(m_NormalConfigurationPath) }; + } + else + { + m_Configuration = LoadAssetAtPath(m_AllConfigPaths[m_CurrentConfigIndex]); + } + m_CurrentConfigIndex = 0; + } + else + { + m_CurrentConfigIndex = m_AllConfigPaths.ToList().FindIndex(0, _ => string.Equals(m_CurrentConfigPath, _)); + } + m_RuleList = null; + } + + private T LoadAssetAtPath(string path) where T : Object + { +#if UNITY_5 + return AssetDatabase.LoadAssetAtPath(path); +#else + return (T) AssetDatabase.LoadAssetAtPath(path, typeof(T)); +#endif + } + + private void InitRuleListDrawer() + { + m_RuleList = new ReorderableList(m_Configuration.rules, typeof(ResourceRule)); + m_RuleList.drawElementCallback = OnListElementGUI; + m_RuleList.drawHeaderCallback = OnListHeaderGUI; + m_RuleList.draggable = true; + m_RuleList.elementHeight = 22; + m_RuleList.onAddCallback = (list) => Add(); + } + + private void Add() + { + string path = SelectFolder(); + if (!string.IsNullOrEmpty(path)) + { + var rule = new ResourceRule(); + rule.assetsDirectoryPath = path; + m_Configuration.rules.Add(rule); + } + } + + private void OnListElementGUI(Rect rect, int index, bool isactive, bool isfocused) + { + if (index>=m_Configuration.rules.Count) + { + return; + } + const float GAP = 5; + + ResourceRule rule = m_Configuration.rules[index]; + rect.y++; + + Rect r = rect; + r.width = 16; + r.height = 18; + rule.valid = EditorGUI.Toggle(r, rule.valid); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMax + 425; + float assetBundleNameLength = r.width; + rule.name = EditorGUI.TextField(r, rule.name); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 100; + rule.loadType = (LoadType) EditorGUI.EnumPopup(r, rule.loadType); + + r.xMin = r.xMax + GAP + 15; + r.xMax = r.xMin + 30; + rule.packed = EditorGUI.Toggle(r, rule.packed); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 85; + rule.fileSystem = EditorGUI.TextField(r, rule.fileSystem); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 85; + rule.groups = EditorGUI.TextField(r, rule.groups); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 85; + rule.variant = EditorGUI.TextField(r, rule.variant); + if (!string.IsNullOrEmpty(rule.variant)) + { + rule.variant = rule.variant.ToLower(); + } + + r.xMin = r.xMax + GAP; + r.width = assetBundleNameLength - 15; + GUI.enabled = false; + rule.assetsDirectoryPath = EditorGUI.TextField(r, rule.assetsDirectoryPath); + GUI.enabled = true; + + r.xMin = r.xMax + GAP; + r.width = 50; + if (GUI.Button(r, "Select")) + { + var path = SelectFolder(); + if (path != null) + rule.assetsDirectoryPath = path; + } + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 85; + rule.filterType = (ResourceFilterType) EditorGUI.EnumPopup(r, rule.filterType); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 120; + rule.searchPatterns = EditorGUI.TextField(r, rule.searchPatterns); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 120; + rule.filePatterns = EditorGUI.TextField(r, rule.filePatterns); + + r.xMin = r.xMax + GAP; + r.xMax = rect.xMax; + rule.folderPatterns = EditorGUI.TextField(r, rule.folderPatterns); + } + + private string SelectFolder() + { + string dataPath = Application.dataPath; + string selectedPath = EditorUtility.OpenFolderPanel("Path", dataPath, ""); + if (!string.IsNullOrEmpty(selectedPath)) + { + if (selectedPath.StartsWith(dataPath)) + { + return "Assets/" + selectedPath.Substring(dataPath.Length + 1); + } + else + { +#if UNITY_2019_1_OR_NEWER + ShowNotification(new GUIContent("Can not be outside of 'Assets/'!"), 2); +#else + ShowNotification(new GUIContent("Can not be outside of 'Assets/'!")); +#endif + } + } + + return null; + } + + private int m_CurrentConfigIndex; + [SerializeField] private string m_CurrentConfigPath; + private List m_AllConfigPaths; + private string[] m_ConfigNames; + + private void OnListHeaderGUI(Rect rect) + { + Rect rules = new Rect(rect.x, rect.y, 100, rect.height); + EditorGUI.LabelField(rules, "Rules"); + Rect configLabel = new Rect(rect.x + rules.width, rect.y, 90, rect.height); + EditorGUI.LabelField(configLabel, "CurrentConfig:"); + Rect configs = new Rect(rect.x + rules.width + configLabel.width, rect.y, 200, rect.height); + m_CurrentConfigIndex = EditorGUI.Popup(configs, m_CurrentConfigIndex, m_ConfigNames); + if (m_CurrentConfigPath != m_AllConfigPaths[m_CurrentConfigIndex]) + { + m_CurrentConfigPath = m_AllConfigPaths[m_CurrentConfigIndex]; + m_Configuration = LoadAssetAtPath(m_CurrentConfigPath); + m_RuleList = null; + } + + Rect reload = new Rect(rect.width-100, rect.y, 100, rect.height); + if (GUI.Button(reload,"Reload")) + { + Load(); + } + } + + private void OnListElementLabelGUI() + { + Rect rect = new Rect(); + const float GAP = 5; + GUI.enabled = false; + + Rect r = new Rect(0, 20, rect.width, rect.height); + r.width = 45; + r.height = 18; + EditorGUI.TextField(r, "Active"); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMax + 415; + float assetBundleNameLength = r.width; + EditorGUI.TextField(r, "Name"); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 100; + EditorGUI.TextField(r, "Load Type"); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 50; + EditorGUI.TextField(r, "Packed"); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 85; + EditorGUI.TextField(r, "File System"); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 85; + EditorGUI.TextField(r, "Groups"); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 85; + EditorGUI.TextField(r, "Variant"); + + r.xMin = r.xMax + GAP; + r.width = assetBundleNameLength + 50; + EditorGUI.TextField(r, "AssetDirectory"); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 85; + EditorGUI.TextField(r, "Filter Type"); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 120; + EditorGUI.TextField(r, "Search Patterns"); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 120; + EditorGUI.TextField(r, "File Patterns"); + + r.xMin = r.xMax + GAP; + r.xMax = r.xMin + 120; + EditorGUI.TextField(r, "Folder Patterns"); + GUI.enabled = true; + } + + private void Save() + { + if (LoadAssetAtPath(m_CurrentConfigPath) == null) + { + AssetDatabase.CreateAsset(m_Configuration, m_CurrentConfigPath); + } + else + { + EditorUtility.SetDirty(m_Configuration); + } + } + + #region Refresh ResourceCollection.xml + + public void RefreshResourceCollection() + { + if (m_Configuration == null) + { + Load(); + } + m_SourceAssetExceptTypeFilterGUIDArray = AssetDatabase.FindAssets(m_SourceAssetExceptTypeFilter); + m_SourceAssetExceptLabelFilterGUIDArray = AssetDatabase.FindAssets(m_SourceAssetExceptLabelFilter); + AnalysisResourceFilters(); + if (SaveCollection()) + { + Debug.Log("Refresh ResourceCollection.xml success"); + } + else + { + Debug.Log("Refresh ResourceCollection.xml fail"); + } + } + public void RefreshResourceCollection(string configPath) + { + if (m_Configuration == null || !m_CurrentConfigPath.Equals(configPath)) + { + m_CurrentConfigPath = configPath; + Load(); + } + + m_SourceAssetExceptTypeFilterGUIDArray = AssetDatabase.FindAssets(m_SourceAssetExceptTypeFilter); + m_SourceAssetExceptLabelFilterGUIDArray = AssetDatabase.FindAssets(m_SourceAssetExceptLabelFilter); + AnalysisResourceFilters(); + if (SaveCollection()) + { + Debug.Log("Refresh ResourceCollection.xml success"); + } + else + { + Debug.Log("Refresh ResourceCollection.xml fail"); + } + } + + private GFResource[] GetResources() + { + return m_ResourceCollection.GetResources(); + } + + private bool HasResource(string name, string variant) + { + return m_ResourceCollection.HasResource(name, variant); + } + + private bool AddResource(string name, string variant,string fileSystem, + LoadType loadType, bool packed, string[] resourceGroups) + { + return m_ResourceCollection.AddResource(name, variant, fileSystem,loadType, + packed, resourceGroups); + } + + private bool RenameResource(string oldName, string oldVariant, + string newName, string newVariant) + { + return m_ResourceCollection.RenameResource(oldName, oldVariant, + newName, newVariant); + } + + private bool AssignAsset(string assetGuid, string resourceName, string resourceVariant) + { + if (m_ResourceCollection.AssignAsset(assetGuid, resourceName, resourceVariant)) + { + return true; + } + + return false; + } + + private void AnalysisResourceFilters() + { + m_ResourceCollection = new ResourceCollection(); + List signedAssetBundleList = new List(); + + foreach (ResourceRule resourceRule in m_Configuration.rules) + { + if (resourceRule.variant == "") + resourceRule.variant = null; + + if (resourceRule.valid) + { + switch (resourceRule.filterType) + { + case ResourceFilterType.Root: + { + if (string.IsNullOrEmpty(resourceRule.name)) + { + string relativeDirectoryName = + resourceRule.assetsDirectoryPath.Replace("Assets/", ""); + ApplyResourceFilter(ref signedAssetBundleList, resourceRule, + Utility.Path.GetRegularPath(relativeDirectoryName)); + } + else + { + ApplyResourceFilter(ref signedAssetBundleList, resourceRule, + resourceRule.name); + } + } + break; + + case ResourceFilterType.Children: + { + string[] patterns = resourceRule.searchPatterns.Split(';', ',', '|'); + for (int i = 0; i < patterns.Length; i++) + { + FileInfo[] assetFiles = + new DirectoryInfo(resourceRule.assetsDirectoryPath).GetFiles(patterns[i], + SearchOption.AllDirectories); + foreach (FileInfo file in assetFiles) + { + if (file.Extension.Contains("meta")) + continue; + + // 检查文件名是否匹配 filePatterns + if (!string.IsNullOrEmpty(resourceRule.filePatterns) && !MatchFilePattern(file.Name, resourceRule.filePatterns)) + continue; + + // 检查文件夹是否匹配 folderPatterns + if (!string.IsNullOrEmpty(resourceRule.folderPatterns) && !MatchFolderPattern(file.DirectoryName, resourceRule.folderPatterns)) + continue; + + string relativeAssetName = file.FullName.Substring(Application.dataPath.Length + 1); + string relativeAssetNameWithoutExtension = + Utility.Path.GetRegularPath( + relativeAssetName.Substring(0, relativeAssetName.IndexOf('.'))); + + string assetName = Path.Combine("Assets", relativeAssetName); + string assetGUID = AssetDatabase.AssetPathToGUID(assetName); + + if (!m_SourceAssetExceptTypeFilterGUIDArray.Contains(assetGUID) && !m_SourceAssetExceptLabelFilterGUIDArray.Contains(assetGUID)) + { + ApplyResourceFilter(ref signedAssetBundleList, resourceRule, + relativeAssetNameWithoutExtension, assetGUID); + } + } + } + } + break; + + case ResourceFilterType.ChildrenFoldersOnly: + { + DirectoryInfo[] assetDirectories = + new DirectoryInfo(resourceRule.assetsDirectoryPath).GetDirectories(); + foreach (DirectoryInfo directory in assetDirectories) + { + // 检查文件夹是否匹配 folderPatterns + if (!string.IsNullOrEmpty(resourceRule.folderPatterns) && !MatchFolderPattern(directory.Name, resourceRule.folderPatterns)) + continue; + + string relativeDirectoryName = + directory.FullName.Substring(Application.dataPath.Length + 1); + + ApplyResourceFilter(ref signedAssetBundleList, resourceRule, + Utility.Path.GetRegularPath(relativeDirectoryName), string.Empty, + directory.FullName); + } + } + break; + + case ResourceFilterType.ChildrenFilesOnly: + { + DirectoryInfo[] assetDirectories = + new DirectoryInfo(resourceRule.assetsDirectoryPath).GetDirectories(); + foreach (DirectoryInfo directory in assetDirectories) + { + // 检查文件夹是否匹配 folderPatterns + if (!string.IsNullOrEmpty(resourceRule.folderPatterns) && !MatchFolderPattern(directory.Name, resourceRule.folderPatterns)) + continue; + + string[] patterns = resourceRule.searchPatterns.Split(';', ',', '|'); + for (int i = 0; i < patterns.Length; i++) + { + FileInfo[] assetFiles = + new DirectoryInfo(directory.FullName).GetFiles(patterns[i], + SearchOption.AllDirectories); + foreach (FileInfo file in assetFiles) + { + if (file.Extension.Contains("meta")) + continue; + + // 检查文件名是否匹配 filePatterns + if (!string.IsNullOrEmpty(resourceRule.filePatterns) && !MatchFilePattern(file.Name, resourceRule.filePatterns)) + continue; + // 检查文件所在文件夹是否匹配 folderPatterns + if (!string.IsNullOrEmpty(resourceRule.folderPatterns) && !MatchFolderPattern(file.DirectoryName, resourceRule.folderPatterns)) + continue; + + string relativeAssetName = + file.FullName.Substring(Application.dataPath.Length + 1); + string relativeAssetNameWithoutExtension = + Utility.Path.GetRegularPath( + relativeAssetName.Substring(0, relativeAssetName.IndexOf('.'))); + + string assetName = Path.Combine("Assets", relativeAssetName); + string assetGUID = AssetDatabase.AssetPathToGUID(assetName); + + if (!m_SourceAssetExceptTypeFilterGUIDArray.Contains(assetGUID) && !m_SourceAssetExceptLabelFilterGUIDArray.Contains(assetGUID)) + { + ApplyResourceFilter(ref signedAssetBundleList, resourceRule, + relativeAssetNameWithoutExtension, assetGUID); + } + } + } + } + } + break; + } + } + } + + var old_ResourceCollection = new ResourceCollection(); + old_ResourceCollection.Load(); + foreach(var resource in old_ResourceCollection.GetResources()) + { + if(!m_ResourceCollection.HasResource(resource.Name, resource.Variant)) + { + m_ResourceCollection.AddResource(resource.Name, resource.Variant, resource.FileSystem, resource.LoadType, resource.Packed, resource.GetResourceGroups()); + foreach (var asset in resource.GetAssets()) + { + m_ResourceCollection.AssignAsset(asset.Guid, resource.Name, resource.Variant); + } + } + } + } + + private void ApplyResourceFilter(ref List signedResourceList, ResourceRule resourceRule, + string resourceName, string singleAssetGUID = "", string childDirectoryPath = "") + { + if (!signedResourceList.Contains(Path.Combine(resourceRule.assetsDirectoryPath, resourceName))) + { + signedResourceList.Add(Path.Combine(resourceRule.assetsDirectoryPath, resourceName)); + + foreach (GFResource oldResource in GetResources()) + { + if (oldResource.Name == resourceName && string.IsNullOrEmpty(oldResource.Variant)) + { + RenameResource(oldResource.Name, oldResource.Variant, + resourceName, resourceRule.variant); + break; + } + } + + if (!HasResource(resourceName, resourceRule.variant)) + { + + if (string.IsNullOrEmpty(resourceRule.fileSystem)) + { + resourceRule.fileSystem = null; + } + + AddResource(resourceName, resourceRule.variant,resourceRule.fileSystem, + resourceRule.loadType, resourceRule.packed, + resourceRule.groups.Split(';', ',', '|')); + } + + switch (resourceRule.filterType) + { + case ResourceFilterType.Root: + case ResourceFilterType.ChildrenFoldersOnly: + string[] patterns = resourceRule.searchPatterns.Split(';', ',', '|'); + if (childDirectoryPath == "") + { + childDirectoryPath = resourceRule.assetsDirectoryPath; + } + + for (int i = 0; i < patterns.Length; i++) + { + FileInfo[] assetFiles = + new DirectoryInfo(childDirectoryPath).GetFiles(patterns[i], + SearchOption.AllDirectories); + foreach (FileInfo file in assetFiles) + { + if (file.Extension.Contains("meta")) + continue; + + // 检查文件名是否匹配 filePatterns + if (!string.IsNullOrEmpty(resourceRule.filePatterns) && !MatchFilePattern(file.Name, resourceRule.filePatterns)) + continue; + // 检查文件所在文件夹是否匹配 folderPatterns + if (!string.IsNullOrEmpty(resourceRule.folderPatterns) && !MatchFolderPattern(file.DirectoryName, resourceRule.folderPatterns)) + continue; + + string assetName = Path.Combine("Assets", + file.FullName.Substring(Application.dataPath.Length + 1)); + + string assetGUID = AssetDatabase.AssetPathToGUID(assetName); + + if (!m_SourceAssetExceptTypeFilterGUIDArray.Contains(assetGUID) && !m_SourceAssetExceptLabelFilterGUIDArray.Contains(assetGUID)) + { + AssignAsset(assetGUID, resourceName, + resourceRule.variant); + } + } + } + + break; + + case ResourceFilterType.Children: + case ResourceFilterType.ChildrenFilesOnly: + { + AssignAsset(singleAssetGUID, resourceName, + resourceRule.variant); + } + break; + } + } + } + + private bool SaveCollection() + { + return m_ResourceCollection.Save(); + } + + /// + /// 检查文件名是否匹配指定的模式 + /// + private bool MatchFilePattern(string fileName, string patterns) + { + if (string.IsNullOrEmpty(patterns)) + return true; + + string[] patternArray = patterns.Split(';', ',', '|'); + + bool hasIncludePattern = false; + bool includeMatched = false; + + foreach (string pattern in patternArray) + { + string trimmedPattern = pattern.Trim(); + if (string.IsNullOrEmpty(trimmedPattern)) + continue; + + if (trimmedPattern.StartsWith("!")) + { + // 排除模式:如果文件名为排除关键字,直接返回 false + string excludePattern = trimmedPattern.Substring(1).ToLower(); + if (fileName.ToLower().Equals(excludePattern)) + return false; + } + else + { + // 包含模式 + hasIncludePattern = true; + if (MatchWildcard(fileName, trimmedPattern)) + { + includeMatched = true; + } + } + } + + // 如果有包含模式,需要匹配到才返回 true + // 如果只有排除模式,默认返回 true(除非上面已经被排除) + if (hasIncludePattern) + return includeMatched; + else + return true; + } + + /// + /// 检查文件夹路径是否匹配指定的模式 + /// + private bool MatchFolderPattern(string folderPath, string patterns) + { + if (string.IsNullOrEmpty(patterns)) + return true; + + string[] patternArray = patterns.Split(';', ',', '|'); + string folderName = Path.GetFileName(folderPath); + + bool hasIncludePattern = false; + bool includeMatched = false; + + foreach (string pattern in patternArray) + { + string trimmedPattern = pattern.Trim(); + if (string.IsNullOrEmpty(trimmedPattern)) + continue; + + if (trimmedPattern.StartsWith("!")) + { + // 排除模式:如果路径包含排除关键字,直接返回 false + string excludePattern = trimmedPattern.Substring(1).ToLower(); + if (folderPath.ToLower().Contains(excludePattern)) + return false; + } + else + { + // 包含模式 + hasIncludePattern = true; + if (MatchWildcard(folderName, trimmedPattern)) + { + includeMatched = true; + } + } + } + + // 如果有包含模式,需要匹配到才返回 true + // 如果只有排除模式,默认返回 true(除非上面已经被排除) + if (hasIncludePattern) + return includeMatched; + else + return true; + } + + /// + /// 通配符匹配 + /// + private bool MatchWildcard(string text, string pattern) + { + if (pattern == "*" || pattern == "*.*") + return true; + + pattern = "^" + System.Text.RegularExpressions.Regex.Escape(pattern) + .Replace("\\*", ".*") + .Replace("\\?", ".") + "$"; + + return System.Text.RegularExpressions.Regex.IsMatch(text, pattern, + System.Text.RegularExpressions.RegexOptions.IgnoreCase); + } + + #endregion + } +} \ No newline at end of file diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditor.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditor.cs.meta new file mode 100644 index 0000000..43c5be4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bda74163d55bec4478f7fb5031ca9be3 +timeCreated: 1505217637 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditorData.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditorData.cs new file mode 100644 index 0000000..73d9347 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditorData.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Serialization; +using UnityGameFramework.Editor.ResourceTools; + +namespace StarForce.Editor.ResourceTools +{ + public class ResourceRuleEditorData : ScriptableObject + { + public List rules = new List(); + } + + [System.Serializable] + public class ResourceRule + { + public bool valid = true; + public string name = string.Empty; + public string variant = null; + public string fileSystem = string.Empty; + public string groups = string.Empty; + public string assetsDirectoryPath = string.Empty; + public LoadType loadType = LoadType.LoadFromFile; + public bool packed = true; + public ResourceFilterType filterType = ResourceFilterType.Root; + public string searchPatterns = "*.*"; + public string filePatterns = "*.*"; + public string folderPatterns = "*.*"; + } + + public enum ResourceFilterType + { + Root, + Children, + ChildrenFoldersOnly, + ChildrenFilesOnly, + } +} \ No newline at end of file diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditorData.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditorData.cs.meta new file mode 100644 index 0000000..344351a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditorData.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 99b93107d7bc31740838a156d99e161c +timeCreated: 1505983325 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditorUtility.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditorUtility.cs new file mode 100644 index 0000000..2ef53d4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditorUtility.cs @@ -0,0 +1,18 @@ +using UnityEngine; + +namespace StarForce.Editor.ResourceTools +{ + public static class ResourceRuleEditorUtility + { + public static void RefreshResourceCollection() + { + ResourceRuleEditor ruleEditor = ScriptableObject.CreateInstance(); + ruleEditor.RefreshResourceCollection(); + } + public static void RefreshResourceCollection(string configPath) + { + ResourceRuleEditor ruleEditor = ScriptableObject.CreateInstance(); + ruleEditor.RefreshResourceCollection(configPath); + } + } +} \ No newline at end of file diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditorUtility.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditorUtility.cs.meta new file mode 100644 index 0000000..7bb0744 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceRuleEditor/ResourceRuleEditorUtility.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c3c48b963ba34de697e11a2130a8182d +timeCreated: 1646032356 \ No newline at end of file diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools.meta new file mode 100644 index 0000000..78f6e43 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3d96add3948f44049bb53f4207cdee15 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools/ResourceSyncTools.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools/ResourceSyncTools.cs new file mode 100644 index 0000000..9a0d9bb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools/ResourceSyncTools.cs @@ -0,0 +1,115 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEditor; +using UnityEngine; + +namespace UnityGameFramework.Editor.ResourceTools +{ + /// + /// 资源同步工具。 + /// + internal sealed class ResourceSyncTools : EditorWindow + { + private const float ButtonHeight = 60f; + private const float ButtonSpace = 5f; + private ResourceSyncToolsController m_Controller = null; + + [MenuItem("Game Framework/Resource Tools/Resource Sync Tools", false, 44)] + private static void Open() + { + ResourceSyncTools window = GetWindow("Resource Sync Tools", true); +#if UNITY_2019_3_OR_NEWER + window.minSize = new Vector2(400, 195f); +#else + window.minSize = new Vector2(400, 205f); +#endif + } + + private void OnEnable() + { + m_Controller = new ResourceSyncToolsController(); + m_Controller.OnLoadingResource += OnLoadingResource; + m_Controller.OnLoadingAsset += OnLoadingAsset; + m_Controller.OnCompleted += OnCompleted; + m_Controller.OnResourceDataChanged += OnResourceDataChanged; + } + + private void OnGUI() + { + EditorGUILayout.BeginVertical(GUILayout.Width(position.width), GUILayout.Height(position.height)); + { + GUILayout.Space(ButtonSpace); + if (GUILayout.Button("Remove All Asset Bundle Names in Project", GUILayout.Height(ButtonHeight))) + { + if (!m_Controller.RemoveAllAssetBundleNames()) + { + Debug.LogWarning("Remove All Asset Bundle Names in Project failure."); + } + else + { + Debug.Log("Remove All Asset Bundle Names in Project completed."); + } + + AssetDatabase.Refresh(); + } + + GUILayout.Space(ButtonSpace); + if (GUILayout.Button("Sync ResourceCollection.xml to Project", GUILayout.Height(ButtonHeight))) + { + if (!m_Controller.SyncToProject()) + { + Debug.LogWarning("Sync ResourceCollection.xml to Project failure."); + } + else + { + Debug.Log("Sync ResourceCollection.xml to Project completed."); + } + + AssetDatabase.Refresh(); + } + + GUILayout.Space(ButtonSpace); + if (GUILayout.Button("Sync ResourceCollection.xml from Project", GUILayout.Height(ButtonHeight))) + { + if (!m_Controller.SyncFromProject()) + { + Debug.LogWarning("Sync Project to ResourceCollection.xml failure."); + } + else + { + Debug.Log("Sync Project to ResourceCollection.xml completed."); + } + + AssetDatabase.Refresh(); + } + } + EditorGUILayout.EndVertical(); + } + + private void OnLoadingResource(int index, int count) + { + EditorUtility.DisplayProgressBar("Loading Resources", Utility.Text.Format("Loading resources, {0}/{1} loaded.", index, count), (float)index / count); + } + + private void OnLoadingAsset(int index, int count) + { + EditorUtility.DisplayProgressBar("Loading Assets", Utility.Text.Format("Loading assets, {0}/{1} loaded.", index, count), (float)index / count); + } + + private void OnCompleted() + { + EditorUtility.ClearProgressBar(); + } + + private void OnResourceDataChanged(int index, int count, string assetName) + { + EditorUtility.DisplayProgressBar("Processing Assets", Utility.Text.Format("({0}/{1}) {2}", index, count, assetName), (float)index / count); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools/ResourceSyncTools.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools/ResourceSyncTools.cs.meta new file mode 100644 index 0000000..72a8983 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools/ResourceSyncTools.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d691ed24af244ff41a3012f66ca3ef80 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools/ResourceSyncToolsController.cs b/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools/ResourceSyncToolsController.cs new file mode 100644 index 0000000..12c5287 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools/ResourceSyncToolsController.cs @@ -0,0 +1,229 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; + +namespace UnityGameFramework.Editor.ResourceTools +{ + public sealed class ResourceSyncToolsController + { + public ResourceSyncToolsController() + { + } + + public event GameFrameworkAction OnLoadingResource = null; + + public event GameFrameworkAction OnLoadingAsset = null; + + public event GameFrameworkAction OnCompleted = null; + + public event GameFrameworkAction OnResourceDataChanged = null; + + public string[] GetAllAssetBundleNames() + { + return AssetDatabase.GetAllAssetBundleNames(); + } + + public string[] GetUsedAssetBundleNames() + { + HashSet hashSet = new HashSet(GetAllAssetBundleNames()); + hashSet.ExceptWith(GetUnusedAssetBundleNames()); + return hashSet.ToArray(); + } + + public string[] GetUnusedAssetBundleNames() + { + return AssetDatabase.GetUnusedAssetBundleNames(); + } + + public string[] GetAssetPathsFromAssetBundle(string assetBundleName) + { + return AssetDatabase.GetAssetPathsFromAssetBundle(assetBundleName); + } + + public string[] GetAssetPathsFromAssetBundleAndAssetName(string assetBundleName, string assetName) + { + return AssetDatabase.GetAssetPathsFromAssetBundleAndAssetName(assetBundleName, assetName); + } + + public bool RemoveAssetBundleName(string assetBundleName, bool forceRemove) + { + return AssetDatabase.RemoveAssetBundleName(assetBundleName, forceRemove); + } + + public void RemoveUnusedAssetBundleNames() + { + AssetDatabase.RemoveUnusedAssetBundleNames(); + } + + public bool RemoveAllAssetBundleNames() + { + HashSet allAssetNames = new HashSet(); + string[] assetBundleNames = GetUsedAssetBundleNames(); + foreach (string assetBundleName in assetBundleNames) + { + string[] assetNames = GetAssetPathsFromAssetBundle(assetBundleName); + foreach (string assetName in assetNames) + { + allAssetNames.Add(assetName); + } + } + + int assetIndex = 0; + int assetCount = allAssetNames.Count; + foreach (string assetName in allAssetNames) + { + AssetImporter assetImporter = AssetImporter.GetAtPath(assetName); + if (assetImporter == null) + { + if (OnCompleted != null) + { + OnCompleted(); + } + + return false; + } + + assetImporter.assetBundleVariant = null; + assetImporter.assetBundleName = null; + assetImporter.SaveAndReimport(); + + if (OnResourceDataChanged != null) + { + OnResourceDataChanged(++assetIndex, assetCount, assetName); + } + } + + RemoveUnusedAssetBundleNames(); + + if (OnCompleted != null) + { + OnCompleted(); + } + + return true; + } + + public bool SyncToProject() + { + ResourceCollection resourceCollection = new ResourceCollection(); + + resourceCollection.OnLoadingResource += delegate (int index, int count) + { + if (OnLoadingResource != null) + { + OnLoadingResource(index, count); + } + }; + + resourceCollection.OnLoadingAsset += delegate (int index, int count) + { + if (OnLoadingAsset != null) + { + OnLoadingAsset(index, count); + } + }; + + resourceCollection.OnLoadCompleted += delegate () + { + if (OnCompleted != null) + { + OnCompleted(); + } + }; + + if (!resourceCollection.Load()) + { + return false; + } + + int assetIndex = 0; + int assetCount = resourceCollection.AssetCount; + Resource[] resources = resourceCollection.GetResources(); + foreach (Resource resource in resources) + { + if (resource.IsLoadFromBinary) + { + continue; + } + + Asset[] assets = resource.GetAssets(); + foreach (Asset asset in assets) + { + AssetImporter assetImporter = AssetImporter.GetAtPath(asset.Name); + if (assetImporter == null) + { + if (OnCompleted != null) + { + OnCompleted(); + } + + return false; + } + + assetImporter.assetBundleName = resource.Name; + assetImporter.assetBundleVariant = resource.Variant; + assetImporter.SaveAndReimport(); + + if (OnResourceDataChanged != null) + { + OnResourceDataChanged(++assetIndex, assetCount, asset.Name); + } + } + } + + if (OnCompleted != null) + { + OnCompleted(); + } + + return true; + } + + public bool SyncFromProject() + { + ResourceCollection resourceCollection = new ResourceCollection(); + string[] assetBundleNames = GetUsedAssetBundleNames(); + foreach (string assetBundleName in assetBundleNames) + { + string name = assetBundleName; + string variant = null; + int dotPosition = assetBundleName.LastIndexOf('.'); + if (dotPosition > 0 && dotPosition < assetBundleName.Length - 1) + { + name = assetBundleName.Substring(0, dotPosition); + variant = assetBundleName.Substring(dotPosition + 1); + } + + if (!resourceCollection.AddResource(name, variant, null, LoadType.LoadFromFile, false)) + { + return false; + } + + string[] assetNames = GetAssetPathsFromAssetBundle(assetBundleName); + foreach (string assetName in assetNames) + { + string guid = AssetDatabase.AssetPathToGUID(assetName); + if (string.IsNullOrEmpty(guid)) + { + return false; + } + + if (!resourceCollection.AssignAsset(guid, name, variant)) + { + return false; + } + } + } + + return resourceCollection.Save(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools/ResourceSyncToolsController.cs.meta b/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools/ResourceSyncToolsController.cs.meta new file mode 100644 index 0000000..b3a7631 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/ResourceSyncTools/ResourceSyncToolsController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 210d0e0a522f6c540b17cf9fe64b71e4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Editor/UnityGameFramework.Editor.asmdef b/Packages/com.bywaystudios.gameframework/Editor/UnityGameFramework.Editor.asmdef new file mode 100644 index 0000000..80d8abf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/UnityGameFramework.Editor.asmdef @@ -0,0 +1,19 @@ +{ + "name": "UnityGameFramework.Editor", + "rootNamespace": "", + "references": [ + "GameFramework", + "UnityGameFramework.Runtime" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.bywaystudios.gameframework/Editor/UnityGameFramework.Editor.asmdef.meta b/Packages/com.bywaystudios.gameframework/Editor/UnityGameFramework.Editor.asmdef.meta new file mode 100644 index 0000000..dc6787a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Editor/UnityGameFramework.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 93fd999929b9ace4e860eb6f24522d48 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime.meta b/Packages/com.bywaystudios.gameframework/Runtime.meta new file mode 100644 index 0000000..ef60277 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: da99d8863a05d124393540b57b7d3889 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework.meta new file mode 100644 index 0000000..778ae56 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 69984e46e21e29440971553e088f73fd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base.meta new file mode 100644 index 0000000..ba6c159 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b4e69d803452d434f9861cc3b4af3253 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider.meta new file mode 100644 index 0000000..b8b7b02 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4448b6e07f805d241aaae133fb0c3715 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/DataProvider.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/DataProvider.cs new file mode 100644 index 0000000..a4e82c5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/DataProvider.cs @@ -0,0 +1,500 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System; + +namespace GameFramework +{ + /// + /// 数据提供者。 + /// + /// 数据提供者的持有者的类型。 + internal sealed class DataProvider : IDataProvider + { + private const int BlockSize = 1024 * 4; + private static byte[] s_CachedBytes = null; + + private readonly T m_Owner; + private readonly LoadAssetCallbacks m_LoadAssetCallbacks; + private readonly LoadBinaryCallbacks m_LoadBinaryCallbacks; + private IResourceManager m_ResourceManager; + private IDataProviderHelper m_DataProviderHelper; + private EventHandler m_ReadDataSuccessEventHandler; + private EventHandler m_ReadDataFailureEventHandler; + private EventHandler m_ReadDataUpdateEventHandler; + private EventHandler m_ReadDataDependencyAssetEventHandler; + + /// + /// 初始化数据提供者的新实例。 + /// + /// 数据提供者的持有者。 + public DataProvider(T owner) + { + m_Owner = owner; + m_LoadAssetCallbacks = new LoadAssetCallbacks(LoadAssetSuccessCallback, LoadAssetOrBinaryFailureCallback, LoadAssetUpdateCallback, LoadAssetDependencyAssetCallback); + m_LoadBinaryCallbacks = new LoadBinaryCallbacks(LoadBinarySuccessCallback, LoadAssetOrBinaryFailureCallback); + m_ResourceManager = null; + m_DataProviderHelper = null; + m_ReadDataSuccessEventHandler = null; + m_ReadDataFailureEventHandler = null; + m_ReadDataUpdateEventHandler = null; + m_ReadDataDependencyAssetEventHandler = null; + } + + /// + /// 获取缓冲二进制流的大小。 + /// + public static int CachedBytesSize + { + get + { + return s_CachedBytes != null ? s_CachedBytes.Length : 0; + } + } + + /// + /// 读取数据成功事件。 + /// + public event EventHandler ReadDataSuccess + { + add + { + m_ReadDataSuccessEventHandler += value; + } + remove + { + m_ReadDataSuccessEventHandler -= value; + } + } + + /// + /// 读取数据失败事件。 + /// + public event EventHandler ReadDataFailure + { + add + { + m_ReadDataFailureEventHandler += value; + } + remove + { + m_ReadDataFailureEventHandler -= value; + } + } + + /// + /// 读取数据更新事件。 + /// + public event EventHandler ReadDataUpdate + { + add + { + m_ReadDataUpdateEventHandler += value; + } + remove + { + m_ReadDataUpdateEventHandler -= value; + } + } + + /// + /// 读取数据时加载依赖资源事件。 + /// + public event EventHandler ReadDataDependencyAsset + { + add + { + m_ReadDataDependencyAssetEventHandler += value; + } + remove + { + m_ReadDataDependencyAssetEventHandler -= value; + } + } + + /// + /// 确保二进制流缓存分配足够大小的内存并缓存。 + /// + /// 要确保二进制流缓存分配内存的大小。 + public static void EnsureCachedBytesSize(int ensureSize) + { + if (ensureSize < 0) + { + throw new GameFrameworkException("Ensure size is invalid."); + } + + if (s_CachedBytes == null || s_CachedBytes.Length < ensureSize) + { + FreeCachedBytes(); + int size = (ensureSize - 1 + BlockSize) / BlockSize * BlockSize; + s_CachedBytes = new byte[size]; + } + } + + /// + /// 释放缓存的二进制流。 + /// + public static void FreeCachedBytes() + { + s_CachedBytes = null; + } + + /// + /// 读取数据。 + /// + /// 内容资源名称。 + public void ReadData(string dataAssetName) + { + ReadData(dataAssetName, Constant.DefaultPriority, null); + } + + /// + /// 读取数据。 + /// + /// 内容资源名称。 + /// 加载数据资源的优先级。 + public void ReadData(string dataAssetName, int priority) + { + ReadData(dataAssetName, priority, null); + } + + /// + /// 读取数据。 + /// + /// 内容资源名称。 + /// 用户自定义数据。 + public void ReadData(string dataAssetName, object userData) + { + ReadData(dataAssetName, Constant.DefaultPriority, userData); + } + + /// + /// 读取数据。 + /// + /// 内容资源名称。 + /// 加载数据资源的优先级。 + /// 用户自定义数据。 + public void ReadData(string dataAssetName, int priority, object userData) + { + if (m_ResourceManager == null) + { + throw new GameFrameworkException("You must set resource manager first."); + } + + if (m_DataProviderHelper == null) + { + throw new GameFrameworkException("You must set data provider helper first."); + } + + HasAssetResult result = m_ResourceManager.HasAsset(dataAssetName); + switch (result) + { + case HasAssetResult.AssetOnDisk: + case HasAssetResult.AssetOnFileSystem: + m_ResourceManager.LoadAsset(dataAssetName, priority, m_LoadAssetCallbacks, userData); + break; + + case HasAssetResult.BinaryOnDisk: + m_ResourceManager.LoadBinary(dataAssetName, m_LoadBinaryCallbacks, userData); + break; + + case HasAssetResult.BinaryOnFileSystem: + int dataLength = m_ResourceManager.GetBinaryLength(dataAssetName); + EnsureCachedBytesSize(dataLength); + if (dataLength != m_ResourceManager.LoadBinaryFromFileSystem(dataAssetName, s_CachedBytes)) + { + throw new GameFrameworkException(Utility.Text.Format("Load binary '{0}' from file system with internal error.", dataAssetName)); + } + + try + { + if (!m_DataProviderHelper.ReadData(m_Owner, dataAssetName, s_CachedBytes, 0, dataLength, userData)) + { + throw new GameFrameworkException(Utility.Text.Format("Load data failure in data provider helper, data asset name '{0}'.", dataAssetName)); + } + + if (m_ReadDataSuccessEventHandler != null) + { + ReadDataSuccessEventArgs loadDataSuccessEventArgs = ReadDataSuccessEventArgs.Create(dataAssetName, 0f, userData); + m_ReadDataSuccessEventHandler(this, loadDataSuccessEventArgs); + ReferencePool.Release(loadDataSuccessEventArgs); + } + } + catch (Exception exception) + { + if (m_ReadDataFailureEventHandler != null) + { + ReadDataFailureEventArgs loadDataFailureEventArgs = ReadDataFailureEventArgs.Create(dataAssetName, exception.ToString(), userData); + m_ReadDataFailureEventHandler(this, loadDataFailureEventArgs); + ReferencePool.Release(loadDataFailureEventArgs); + return; + } + + throw; + } + + break; + + default: + throw new GameFrameworkException(Utility.Text.Format("Data asset '{0}' is '{1}'.", dataAssetName, result)); + } + } + + /// + /// 解析内容。 + /// + /// 要解析的内容字符串。 + /// 是否解析内容成功。 + public bool ParseData(string dataString) + { + return ParseData(dataString, null); + } + + /// + /// 解析内容。 + /// + /// 要解析的内容字符串。 + /// 用户自定义数据。 + /// 是否解析内容成功。 + public bool ParseData(string dataString, object userData) + { + if (m_DataProviderHelper == null) + { + throw new GameFrameworkException("You must set data helper first."); + } + + if (dataString == null) + { + throw new GameFrameworkException("Data string is invalid."); + } + + try + { + return m_DataProviderHelper.ParseData(m_Owner, dataString, userData); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Utility.Text.Format("Can not parse data string with exception '{0}'.", exception), exception); + } + } + + /// + /// 解析内容。 + /// + /// 要解析的内容二进制流。 + /// 是否解析内容成功。 + public bool ParseData(byte[] dataBytes) + { + if (dataBytes == null) + { + throw new GameFrameworkException("Data bytes is invalid."); + } + + return ParseData(dataBytes, 0, dataBytes.Length, null); + } + + /// + /// 解析内容。 + /// + /// 要解析的内容二进制流。 + /// 用户自定义数据。 + /// 是否解析内容成功。 + public bool ParseData(byte[] dataBytes, object userData) + { + if (dataBytes == null) + { + throw new GameFrameworkException("Data bytes is invalid."); + } + + return ParseData(dataBytes, 0, dataBytes.Length, userData); + } + + /// + /// 解析内容。 + /// + /// 要解析的内容二进制流。 + /// 内容二进制流的起始位置。 + /// 内容二进制流的长度。 + /// 是否解析内容成功。 + public bool ParseData(byte[] dataBytes, int startIndex, int length) + { + return ParseData(dataBytes, startIndex, length, null); + } + + /// + /// 解析内容。 + /// + /// 要解析的内容二进制流。 + /// 内容二进制流的起始位置。 + /// 内容二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析内容成功。 + public bool ParseData(byte[] dataBytes, int startIndex, int length, object userData) + { + if (m_DataProviderHelper == null) + { + throw new GameFrameworkException("You must set data helper first."); + } + + if (dataBytes == null) + { + throw new GameFrameworkException("Data bytes is invalid."); + } + + if (startIndex < 0 || length < 0 || startIndex + length > dataBytes.Length) + { + throw new GameFrameworkException("Start index or length is invalid."); + } + + try + { + return m_DataProviderHelper.ParseData(m_Owner, dataBytes, startIndex, length, userData); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Utility.Text.Format("Can not parse data bytes with exception '{0}'.", exception), exception); + } + } + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + internal void SetResourceManager(IResourceManager resourceManager) + { + if (resourceManager == null) + { + throw new GameFrameworkException("Resource manager is invalid."); + } + + m_ResourceManager = resourceManager; + } + + /// + /// 设置数据提供者辅助器。 + /// + /// 数据提供者辅助器。 + internal void SetDataProviderHelper(IDataProviderHelper dataProviderHelper) + { + if (dataProviderHelper == null) + { + throw new GameFrameworkException("Data provider helper is invalid."); + } + + m_DataProviderHelper = dataProviderHelper; + } + + private void LoadAssetSuccessCallback(string dataAssetName, object dataAsset, float duration, object userData) + { + try + { + if (!m_DataProviderHelper.ReadData(m_Owner, dataAssetName, dataAsset, userData)) + { + throw new GameFrameworkException(Utility.Text.Format("Load data failure in data provider helper, data asset name '{0}'.", dataAssetName)); + } + + if (m_ReadDataSuccessEventHandler != null) + { + ReadDataSuccessEventArgs loadDataSuccessEventArgs = ReadDataSuccessEventArgs.Create(dataAssetName, duration, userData); + m_ReadDataSuccessEventHandler(this, loadDataSuccessEventArgs); + ReferencePool.Release(loadDataSuccessEventArgs); + } + } + catch (Exception exception) + { + if (m_ReadDataFailureEventHandler != null) + { + ReadDataFailureEventArgs loadDataFailureEventArgs = ReadDataFailureEventArgs.Create(dataAssetName, exception.ToString(), userData); + m_ReadDataFailureEventHandler(this, loadDataFailureEventArgs); + ReferencePool.Release(loadDataFailureEventArgs); + return; + } + + throw; + } + finally + { + m_DataProviderHelper.ReleaseDataAsset(m_Owner, dataAsset); + } + } + + private void LoadAssetOrBinaryFailureCallback(string dataAssetName, LoadResourceStatus status, string errorMessage, object userData) + { + string appendErrorMessage = Utility.Text.Format("Load data failure, data asset name '{0}', status '{1}', error message '{2}'.", dataAssetName, status, errorMessage); + if (m_ReadDataFailureEventHandler != null) + { + ReadDataFailureEventArgs loadDataFailureEventArgs = ReadDataFailureEventArgs.Create(dataAssetName, appendErrorMessage, userData); + m_ReadDataFailureEventHandler(this, loadDataFailureEventArgs); + ReferencePool.Release(loadDataFailureEventArgs); + return; + } + + throw new GameFrameworkException(appendErrorMessage); + } + + private void LoadAssetUpdateCallback(string dataAssetName, float progress, object userData) + { + if (m_ReadDataUpdateEventHandler != null) + { + ReadDataUpdateEventArgs loadDataUpdateEventArgs = ReadDataUpdateEventArgs.Create(dataAssetName, progress, userData); + m_ReadDataUpdateEventHandler(this, loadDataUpdateEventArgs); + ReferencePool.Release(loadDataUpdateEventArgs); + } + } + + private void LoadAssetDependencyAssetCallback(string dataAssetName, string dependencyAssetName, int loadedCount, int totalCount, object userData) + { + if (m_ReadDataDependencyAssetEventHandler != null) + { + ReadDataDependencyAssetEventArgs loadDataDependencyAssetEventArgs = ReadDataDependencyAssetEventArgs.Create(dataAssetName, dependencyAssetName, loadedCount, totalCount, userData); + m_ReadDataDependencyAssetEventHandler(this, loadDataDependencyAssetEventArgs); + ReferencePool.Release(loadDataDependencyAssetEventArgs); + } + } + + private void LoadBinarySuccessCallback(string dataAssetName, byte[] dataBytes, float duration, object userData) + { + try + { + if (!m_DataProviderHelper.ReadData(m_Owner, dataAssetName, dataBytes, 0, dataBytes.Length, userData)) + { + throw new GameFrameworkException(Utility.Text.Format("Load data failure in data provider helper, data asset name '{0}'.", dataAssetName)); + } + + if (m_ReadDataSuccessEventHandler != null) + { + ReadDataSuccessEventArgs loadDataSuccessEventArgs = ReadDataSuccessEventArgs.Create(dataAssetName, duration, userData); + m_ReadDataSuccessEventHandler(this, loadDataSuccessEventArgs); + ReferencePool.Release(loadDataSuccessEventArgs); + } + } + catch (Exception exception) + { + if (m_ReadDataFailureEventHandler != null) + { + ReadDataFailureEventArgs loadDataFailureEventArgs = ReadDataFailureEventArgs.Create(dataAssetName, exception.ToString(), userData); + m_ReadDataFailureEventHandler(this, loadDataFailureEventArgs); + ReferencePool.Release(loadDataFailureEventArgs); + return; + } + + throw; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/DataProvider.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/DataProvider.cs.meta new file mode 100644 index 0000000..e7b4104 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/DataProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 100ad432d7461fc479f175bf8d56023a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/DataProviderCreator.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/DataProviderCreator.cs new file mode 100644 index 0000000..269f52d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/DataProviderCreator.cs @@ -0,0 +1,77 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; + +namespace GameFramework +{ + /// + /// 数据提供者创建器。 + /// + public static class DataProviderCreator + { + /// + /// 获取缓冲二进制流的大小。 + /// + /// 数据提供者的持有者的类型。 + /// 缓冲二进制流的大小。 + public static int GetCachedBytesSize() + { + return DataProvider.CachedBytesSize; + } + + /// + /// 确保二进制流缓存分配足够大小的内存并缓存。 + /// + /// 数据提供者的持有者的类型。 + /// 要确保二进制流缓存分配内存的大小。 + public static void EnsureCachedBytesSize(int ensureSize) + { + DataProvider.EnsureCachedBytesSize(ensureSize); + } + + /// + /// 释放缓存的二进制流。 + /// + /// 数据提供者的持有者的类型。 + public static void FreeCachedBytes() + { + DataProvider.FreeCachedBytes(); + } + + /// + /// 创建数据提供者。 + /// + /// 数据提供者的持有者的类型。 + /// 数据提供者的持有者。 + /// 资源管理器。 + /// 数据提供者辅助器。 + /// 创建的数据提供者。 + public static IDataProvider Create(T owner, IResourceManager resourceManager, IDataProviderHelper dataProviderHelper) + { + if (owner == null) + { + throw new GameFrameworkException("Owner is invalid."); + } + + if (resourceManager == null) + { + throw new GameFrameworkException("Resource manager is invalid."); + } + + if (dataProviderHelper == null) + { + throw new GameFrameworkException("Data provider helper is invalid."); + } + + DataProvider dataProvider = new DataProvider(owner); + dataProvider.SetResourceManager(resourceManager); + dataProvider.SetDataProviderHelper(dataProviderHelper); + return dataProvider; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/DataProviderCreator.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/DataProviderCreator.cs.meta new file mode 100644 index 0000000..c194bab --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/DataProviderCreator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 86d79fd2539ca384f99a0384ee89c072 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/IDataProvider.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/IDataProvider.cs new file mode 100644 index 0000000..0560bc4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/IDataProvider.cs @@ -0,0 +1,115 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework +{ + /// + /// 数据提供者接口。 + /// + /// 数据提供者的持有者的类型。 + public interface IDataProvider + { + /// + /// 读取数据成功事件。 + /// + event EventHandler ReadDataSuccess; + + /// + /// 读取数据失败事件。 + /// + event EventHandler ReadDataFailure; + + /// + /// 读取数据更新事件。 + /// + event EventHandler ReadDataUpdate; + + /// + /// 读取数据时加载依赖资源事件。 + /// + event EventHandler ReadDataDependencyAsset; + + /// + /// 读取数据。 + /// + /// 内容资源名称。 + void ReadData(string dataAssetName); + + /// + /// 读取数据。 + /// + /// 内容资源名称。 + /// 加载数据资源的优先级。 + void ReadData(string dataAssetName, int priority); + + /// + /// 读取数据。 + /// + /// 内容资源名称。 + /// 用户自定义数据。 + void ReadData(string dataAssetName, object userData); + + /// + /// 读取数据。 + /// + /// 内容资源名称。 + /// 加载数据资源的优先级。 + /// 用户自定义数据。 + void ReadData(string dataAssetName, int priority, object userData); + + /// + /// 解析内容。 + /// + /// 要解析的内容字符串。 + /// 是否解析内容成功。 + bool ParseData(string dataString); + + /// + /// 解析内容。 + /// + /// 要解析的内容字符串。 + /// 用户自定义数据。 + /// 是否解析内容成功。 + bool ParseData(string dataString, object userData); + + /// + /// 解析内容。 + /// + /// 要解析的内容二进制流。 + /// 是否解析内容成功。 + bool ParseData(byte[] dataBytes); + + /// + /// 解析内容。 + /// + /// 要解析的内容二进制流。 + /// 用户自定义数据。 + /// 是否解析内容成功。 + bool ParseData(byte[] dataBytes, object userData); + + /// + /// 解析内容。 + /// + /// 要解析的内容二进制流。 + /// 内容二进制流的起始位置。 + /// 内容二进制流的长度。 + /// 是否解析内容成功。 + bool ParseData(byte[] dataBytes, int startIndex, int length); + + /// + /// 解析内容。 + /// + /// 要解析的内容二进制流。 + /// 内容二进制流的起始位置。 + /// 内容二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析内容成功。 + bool ParseData(byte[] dataBytes, int startIndex, int length, object userData); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/IDataProvider.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/IDataProvider.cs.meta new file mode 100644 index 0000000..a0044c6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/IDataProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d93a81f4f7f5873448dc35e9bb34cd21 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/IDataProviderHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/IDataProviderHelper.cs new file mode 100644 index 0000000..a748aea --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/IDataProviderHelper.cs @@ -0,0 +1,64 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 数据提供者辅助器接口。 + /// + public interface IDataProviderHelper + { + /// + /// 读取数据。 + /// + /// 数据提供者的持有者。 + /// 内容资源名称。 + /// 内容资源。 + /// 用户自定义数据。 + /// 是否读取数据成功。 + bool ReadData(T dataProviderOwner, string dataAssetName, object dataAsset, object userData); + + /// + /// 读取数据。 + /// + /// 数据提供者的持有者。 + /// 内容资源名称。 + /// 内容二进制流。 + /// 内容二进制流的起始位置。 + /// 内容二进制流的长度。 + /// 用户自定义数据。 + /// 是否读取数据成功。 + bool ReadData(T dataProviderOwner, string dataAssetName, byte[] dataBytes, int startIndex, int length, object userData); + + /// + /// 解析内容。 + /// + /// 数据提供者的持有者。 + /// 要解析的内容字符串。 + /// 用户自定义数据。 + /// 是否解析内容成功。 + bool ParseData(T dataProviderOwner, string dataString, object userData); + + /// + /// 解析内容。 + /// + /// 数据提供者的持有者。 + /// 要解析的内容二进制流。 + /// 内容二进制流的起始位置。 + /// 内容二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析内容成功。 + bool ParseData(T dataProviderOwner, byte[] dataBytes, int startIndex, int length, object userData); + + /// + /// 释放内容资源。 + /// + /// 数据提供者的持有者。 + /// 要释放的内容资源。 + void ReleaseDataAsset(T dataProviderOwner, object dataAsset); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/IDataProviderHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/IDataProviderHelper.cs.meta new file mode 100644 index 0000000..32270fa --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/IDataProviderHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 705044b0129127f479cd2a6b984f9d71 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataDependencyAssetEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataDependencyAssetEventArgs.cs new file mode 100644 index 0000000..1fd5657 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataDependencyAssetEventArgs.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 读取数据时加载依赖资源事件。 + /// + public sealed class ReadDataDependencyAssetEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化读取数据时加载依赖资源事件的新实例。 + /// + public ReadDataDependencyAssetEventArgs() + { + DataAssetName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + + /// + /// 获取内容资源名称。 + /// + public string DataAssetName + { + get; + private set; + } + + /// + /// 获取被加载的依赖资源名称。 + /// + public string DependencyAssetName + { + get; + private set; + } + + /// + /// 获取当前已加载依赖资源数量。 + /// + public int LoadedCount + { + get; + private set; + } + + /// + /// 获取总共加载依赖资源数量。 + /// + public int TotalCount + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建读取数据时加载依赖资源事件。 + /// + /// 内容资源名称。 + /// 被加载的依赖资源名称。 + /// 当前已加载依赖资源数量。 + /// 总共加载依赖资源数量。 + /// 用户自定义数据。 + /// 创建的读取数据时加载依赖资源事件。 + public static ReadDataDependencyAssetEventArgs Create(string dataAssetName, string dependencyAssetName, int loadedCount, int totalCount, object userData) + { + ReadDataDependencyAssetEventArgs loadDataDependencyAssetEventArgs = ReferencePool.Acquire(); + loadDataDependencyAssetEventArgs.DataAssetName = dataAssetName; + loadDataDependencyAssetEventArgs.DependencyAssetName = dependencyAssetName; + loadDataDependencyAssetEventArgs.LoadedCount = loadedCount; + loadDataDependencyAssetEventArgs.TotalCount = totalCount; + loadDataDependencyAssetEventArgs.UserData = userData; + return loadDataDependencyAssetEventArgs; + } + + /// + /// 清理读取数据时加载依赖资源事件。 + /// + public override void Clear() + { + DataAssetName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataDependencyAssetEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataDependencyAssetEventArgs.cs.meta new file mode 100644 index 0000000..d531093 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataDependencyAssetEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 30266aa250a6daa4a990dbb9ef3242ba +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataFailureEventArgs.cs new file mode 100644 index 0000000..d7ee6b2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataFailureEventArgs.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 读取数据失败事件。 + /// + public sealed class ReadDataFailureEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化读取数据失败事件的新实例。 + /// + public ReadDataFailureEventArgs() + { + DataAssetName = null; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取内容资源名称。 + /// + public string DataAssetName + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建读取数据失败事件。 + /// + /// 内容资源名称。 + /// 错误信息。 + /// 用户自定义数据。 + /// 创建的读取数据失败事件。 + public static ReadDataFailureEventArgs Create(string dataAssetName, string errorMessage, object userData) + { + ReadDataFailureEventArgs loadDataFailureEventArgs = ReferencePool.Acquire(); + loadDataFailureEventArgs.DataAssetName = dataAssetName; + loadDataFailureEventArgs.ErrorMessage = errorMessage; + loadDataFailureEventArgs.UserData = userData; + return loadDataFailureEventArgs; + } + + /// + /// 清理读取数据失败事件。 + /// + public override void Clear() + { + DataAssetName = null; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataFailureEventArgs.cs.meta new file mode 100644 index 0000000..8b6b37e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8704035784c1e0b40a4db20b58dbca74 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataSuccessEventArgs.cs new file mode 100644 index 0000000..3ca54ef --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataSuccessEventArgs.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 读取数据成功事件。 + /// + public sealed class ReadDataSuccessEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化读取数据成功事件的新实例。 + /// + public ReadDataSuccessEventArgs() + { + DataAssetName = null; + Duration = 0f; + UserData = null; + } + + /// + /// 获取内容资源名称。 + /// + public string DataAssetName + { + get; + private set; + } + + /// + /// 获取加载持续时间。 + /// + public float Duration + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建读取数据成功事件。 + /// + /// 内容资源名称。 + /// 加载持续时间。 + /// 用户自定义数据。 + /// 创建的读取数据成功事件。 + public static ReadDataSuccessEventArgs Create(string dataAssetName, float duration, object userData) + { + ReadDataSuccessEventArgs loadDataSuccessEventArgs = ReferencePool.Acquire(); + loadDataSuccessEventArgs.DataAssetName = dataAssetName; + loadDataSuccessEventArgs.Duration = duration; + loadDataSuccessEventArgs.UserData = userData; + return loadDataSuccessEventArgs; + } + + /// + /// 清理读取数据成功事件。 + /// + public override void Clear() + { + DataAssetName = null; + Duration = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataSuccessEventArgs.cs.meta new file mode 100644 index 0000000..9b4c1b9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5d919bf628cea6c4c8d4326a63b9e661 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataUpdateEventArgs.cs new file mode 100644 index 0000000..dc68a18 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataUpdateEventArgs.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 读取数据更新事件。 + /// + public sealed class ReadDataUpdateEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化读取数据更新事件的新实例。 + /// + public ReadDataUpdateEventArgs() + { + DataAssetName = null; + Progress = 0f; + UserData = null; + } + + /// + /// 获取内容资源名称。 + /// + public string DataAssetName + { + get; + private set; + } + + /// + /// 获取读取数据进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建读取数据更新事件。 + /// + /// 内容资源名称。 + /// 读取数据进度。 + /// 用户自定义数据。 + /// 创建的读取数据更新事件。 + public static ReadDataUpdateEventArgs Create(string dataAssetName, float progress, object userData) + { + ReadDataUpdateEventArgs loadDataUpdateEventArgs = ReferencePool.Acquire(); + loadDataUpdateEventArgs.DataAssetName = dataAssetName; + loadDataUpdateEventArgs.Progress = progress; + loadDataUpdateEventArgs.UserData = userData; + return loadDataUpdateEventArgs; + } + + /// + /// 清理读取数据更新事件。 + /// + public override void Clear() + { + DataAssetName = null; + Progress = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataUpdateEventArgs.cs.meta new file mode 100644 index 0000000..93adb34 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataProvider/ReadDataUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 609c081e8e6872e4aa1f177d3ae866b2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataStruct.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataStruct.meta new file mode 100644 index 0000000..62d5729 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataStruct.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8c64bdecb6c506d4386144e1dd28f923 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataStruct/TypeNamePair.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataStruct/TypeNamePair.cs new file mode 100644 index 0000000..8900242 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataStruct/TypeNamePair.cs @@ -0,0 +1,135 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Runtime.InteropServices; + +namespace GameFramework +{ + /// + /// 类型和名称的组合值。 + /// + [StructLayout(LayoutKind.Auto)] + internal struct TypeNamePair : IEquatable + { + private readonly Type m_Type; + private readonly string m_Name; + + /// + /// 初始化类型和名称的组合值的新实例。 + /// + /// 类型。 + public TypeNamePair(Type type) + : this(type, string.Empty) + { + } + + /// + /// 初始化类型和名称的组合值的新实例。 + /// + /// 类型。 + /// 名称。 + public TypeNamePair(Type type, string name) + { + if (type == null) + { + throw new GameFrameworkException("Type is invalid."); + } + + m_Type = type; + m_Name = name ?? string.Empty; + } + + /// + /// 获取类型。 + /// + public Type Type + { + get + { + return m_Type; + } + } + + /// + /// 获取名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取类型和名称的组合值字符串。 + /// + /// 类型和名称的组合值字符串。 + public override string ToString() + { + if (m_Type == null) + { + throw new GameFrameworkException("Type is invalid."); + } + + string typeName = m_Type.FullName; + return string.IsNullOrEmpty(m_Name) ? typeName : Utility.Text.Format("{0}.{1}", typeName, m_Name); + } + + /// + /// 获取对象的哈希值。 + /// + /// 对象的哈希值。 + public override int GetHashCode() + { + return m_Type.GetHashCode() ^ m_Name.GetHashCode(); + } + + /// + /// 比较对象是否与自身相等。 + /// + /// 要比较的对象。 + /// 被比较的对象是否与自身相等。 + public override bool Equals(object obj) + { + return obj is TypeNamePair && Equals((TypeNamePair)obj); + } + + /// + /// 比较对象是否与自身相等。 + /// + /// 要比较的对象。 + /// 被比较的对象是否与自身相等。 + public bool Equals(TypeNamePair value) + { + return m_Type == value.m_Type && m_Name == value.m_Name; + } + + /// + /// 判断两个对象是否相等。 + /// + /// 值 a。 + /// 值 b。 + /// 两个对象是否相等。 + public static bool operator ==(TypeNamePair a, TypeNamePair b) + { + return a.Equals(b); + } + + /// + /// 判断两个对象是否不相等。 + /// + /// 值 a。 + /// 值 b。 + /// 两个对象是否不相等。 + public static bool operator !=(TypeNamePair a, TypeNamePair b) + { + return !(a == b); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataStruct/TypeNamePair.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataStruct/TypeNamePair.cs.meta new file mode 100644 index 0000000..faae6a8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/DataStruct/TypeNamePair.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4a84a487fb5393b44bf3ccfcf59b4e27 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool.meta new file mode 100644 index 0000000..bf95a0b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7d83cb404c446b44184c3bb71c70dd10 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/BaseEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/BaseEventArgs.cs new file mode 100644 index 0000000..eb7eec6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/BaseEventArgs.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 事件基类。 + /// + public abstract class BaseEventArgs : GameFrameworkEventArgs + { + /// + /// 获取类型编号。 + /// + public abstract int Id + { + get; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/BaseEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/BaseEventArgs.cs.meta new file mode 100644 index 0000000..8f88d99 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/BaseEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 239b76603858e804791214feecfec459 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPool.Event.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPool.Event.cs new file mode 100644 index 0000000..1748012 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPool.Event.cs @@ -0,0 +1,57 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + internal sealed partial class EventPool where T : BaseEventArgs + { + /// + /// 事件结点。 + /// + private sealed class Event : IReference + { + private object m_Sender; + private T m_EventArgs; + + public Event() + { + m_Sender = null; + m_EventArgs = null; + } + + public object Sender + { + get + { + return m_Sender; + } + } + + public T EventArgs + { + get + { + return m_EventArgs; + } + } + + public static Event Create(object sender, T e) + { + Event eventNode = ReferencePool.Acquire(); + eventNode.m_Sender = sender; + eventNode.m_EventArgs = e; + return eventNode; + } + + public void Clear() + { + m_Sender = null; + m_EventArgs = null; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPool.Event.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPool.Event.cs.meta new file mode 100644 index 0000000..f35fa9f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPool.Event.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 570346b27b0057a409776a0643b70ad7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPool.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPool.cs new file mode 100644 index 0000000..296c73e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPool.cs @@ -0,0 +1,285 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework +{ + /// + /// 事件池。 + /// + /// 事件类型。 + internal sealed partial class EventPool where T : BaseEventArgs + { + private readonly GameFrameworkMultiDictionary> m_EventHandlers; + private readonly Queue m_Events; + private readonly Dictionary>> m_CachedNodes; + private readonly Dictionary>> m_TempNodes; + private readonly EventPoolMode m_EventPoolMode; + private EventHandler m_DefaultHandler; + + /// + /// 初始化事件池的新实例。 + /// + /// 事件池模式。 + public EventPool(EventPoolMode mode) + { + m_EventHandlers = new GameFrameworkMultiDictionary>(); + m_Events = new Queue(); + m_CachedNodes = new Dictionary>>(); + m_TempNodes = new Dictionary>>(); + m_EventPoolMode = mode; + m_DefaultHandler = null; + } + + /// + /// 获取事件处理函数的数量。 + /// + public int EventHandlerCount + { + get + { + return m_EventHandlers.Count; + } + } + + /// + /// 获取事件数量。 + /// + public int EventCount + { + get + { + return m_Events.Count; + } + } + + /// + /// 事件池轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void Update(float elapseSeconds, float realElapseSeconds) + { + lock (m_Events) + { + while (m_Events.Count > 0) + { + Event eventNode = m_Events.Dequeue(); + HandleEvent(eventNode.Sender, eventNode.EventArgs); + ReferencePool.Release(eventNode); + } + } + } + + /// + /// 关闭并清理事件池。 + /// + public void Shutdown() + { + Clear(); + m_EventHandlers.Clear(); + m_CachedNodes.Clear(); + m_TempNodes.Clear(); + m_DefaultHandler = null; + } + + /// + /// 清理事件。 + /// + public void Clear() + { + lock (m_Events) + { + m_Events.Clear(); + } + } + + /// + /// 获取事件处理函数的数量。 + /// + /// 事件类型编号。 + /// 事件处理函数的数量。 + public int Count(int id) + { + GameFrameworkLinkedListRange> range = default(GameFrameworkLinkedListRange>); + if (m_EventHandlers.TryGetValue(id, out range)) + { + return range.Count; + } + + return 0; + } + + /// + /// 检查是否存在事件处理函数。 + /// + /// 事件类型编号。 + /// 要检查的事件处理函数。 + /// 是否存在事件处理函数。 + public bool Check(int id, EventHandler handler) + { + if (handler == null) + { + throw new GameFrameworkException("Event handler is invalid."); + } + + return m_EventHandlers.Contains(id, handler); + } + + /// + /// 订阅事件处理函数。 + /// + /// 事件类型编号。 + /// 要订阅的事件处理函数。 + public void Subscribe(int id, EventHandler handler) + { + if (handler == null) + { + throw new GameFrameworkException("Event handler is invalid."); + } + + if (!m_EventHandlers.Contains(id)) + { + m_EventHandlers.Add(id, handler); + } + else if ((m_EventPoolMode & EventPoolMode.AllowMultiHandler) != EventPoolMode.AllowMultiHandler) + { + throw new GameFrameworkException(Utility.Text.Format("Event '{0}' not allow multi handler.", id)); + } + else if ((m_EventPoolMode & EventPoolMode.AllowDuplicateHandler) != EventPoolMode.AllowDuplicateHandler && Check(id, handler)) + { + throw new GameFrameworkException(Utility.Text.Format("Event '{0}' not allow duplicate handler.", id)); + } + else + { + m_EventHandlers.Add(id, handler); + } + } + + /// + /// 取消订阅事件处理函数。 + /// + /// 事件类型编号。 + /// 要取消订阅的事件处理函数。 + public void Unsubscribe(int id, EventHandler handler) + { + if (handler == null) + { + throw new GameFrameworkException("Event handler is invalid."); + } + + if (m_CachedNodes.Count > 0) + { + foreach (KeyValuePair>> cachedNode in m_CachedNodes) + { + if (cachedNode.Value != null && cachedNode.Value.Value == handler) + { + m_TempNodes.Add(cachedNode.Key, cachedNode.Value.Next); + } + } + + if (m_TempNodes.Count > 0) + { + foreach (KeyValuePair>> cachedNode in m_TempNodes) + { + m_CachedNodes[cachedNode.Key] = cachedNode.Value; + } + + m_TempNodes.Clear(); + } + } + + if (!m_EventHandlers.Remove(id, handler)) + { + throw new GameFrameworkException(Utility.Text.Format("Event '{0}' not exists specified handler.", id)); + } + } + + /// + /// 设置默认事件处理函数。 + /// + /// 要设置的默认事件处理函数。 + public void SetDefaultHandler(EventHandler handler) + { + m_DefaultHandler = handler; + } + + /// + /// 抛出事件,这个操作是线程安全的,即使不在主线程中抛出,也可保证在主线程中回调事件处理函数,但事件会在抛出后的下一帧分发。 + /// + /// 事件源。 + /// 事件参数。 + public void Fire(object sender, T e) + { + if (e == null) + { + throw new GameFrameworkException("Event is invalid."); + } + + Event eventNode = Event.Create(sender, e); + lock (m_Events) + { + m_Events.Enqueue(eventNode); + } + } + + /// + /// 抛出事件立即模式,这个操作不是线程安全的,事件会立刻分发。 + /// + /// 事件源。 + /// 事件参数。 + public void FireNow(object sender, T e) + { + if (e == null) + { + throw new GameFrameworkException("Event is invalid."); + } + + HandleEvent(sender, e); + } + + /// + /// 处理事件结点。 + /// + /// 事件源。 + /// 事件参数。 + private void HandleEvent(object sender, T e) + { + bool noHandlerException = false; + GameFrameworkLinkedListRange> range = default(GameFrameworkLinkedListRange>); + if (m_EventHandlers.TryGetValue(e.Id, out range)) + { + LinkedListNode> current = range.First; + while (current != null && current != range.Terminal) + { + m_CachedNodes[e] = current.Next != range.Terminal ? current.Next : null; + current.Value(sender, e); + current = m_CachedNodes[e]; + } + + m_CachedNodes.Remove(e); + } + else if (m_DefaultHandler != null) + { + m_DefaultHandler(sender, e); + } + else if ((m_EventPoolMode & EventPoolMode.AllowNoHandler) == 0) + { + noHandlerException = true; + } + + ReferencePool.Release(e); + + if (noHandlerException) + { + throw new GameFrameworkException(Utility.Text.Format("Event '{0}' not allow no handler.", e.Id)); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPool.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPool.cs.meta new file mode 100644 index 0000000..c59eb8f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6b0e963fa2c93564a95dfb0577edd37e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPoolMode.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPoolMode.cs new file mode 100644 index 0000000..46622b0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPoolMode.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework +{ + /// + /// 事件池模式。 + /// + [Flags] + internal enum EventPoolMode : byte + { + /// + /// 默认事件池模式,即必须存在有且只有一个事件处理函数。 + /// + Default = 0, + + /// + /// 允许不存在事件处理函数。 + /// + AllowNoHandler = 1, + + /// + /// 允许存在多个事件处理函数。 + /// + AllowMultiHandler = 2, + + /// + /// 允许存在重复的事件处理函数。 + /// + AllowDuplicateHandler = 4 + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPoolMode.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPoolMode.cs.meta new file mode 100644 index 0000000..2fecdc9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/EventPool/EventPoolMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6f64a26418a084d46b260d8a36b28ff9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkAction.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkAction.cs new file mode 100644 index 0000000..18c10ed --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkAction.cs @@ -0,0 +1,366 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 封装一个方法,该方法不具有参数并且不返回值。 + /// + public delegate void GameFrameworkAction(); + + /// + /// 封装一个方法,该方法只有一个参数并且不返回值。 + /// + /// 此委托封装的方法的参数类型。 + /// 此委托封装的方法的参数。 + public delegate void GameFrameworkAction(T obj); + + /// + /// 封装一个方法,该方法具有两个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2); + + /// + /// 封装一个方法,该方法具有三个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3); + + /// + /// 封装一个方法,该方法具有四个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4); + + /// + /// 封装一个方法,该方法具有五个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); + + /// + /// 封装一个方法,该方法具有六个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); + + /// + /// 封装一个方法,该方法具有七个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); + + /// + /// 封装一个方法,该方法具有八个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); + + /// + /// 封装一个方法,该方法具有九个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); + + /// + /// 封装一个方法,该方法具有十个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); + + /// + /// 封装一个方法,该方法具有十一个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第十一个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的第十一个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); + + /// + /// 封装一个方法,该方法具有十二个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第十一个参数的类型。 + /// 此委托封装的方法的第十二个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的第十一个参数。 + /// 此委托封装的方法的第十二个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); + + /// + /// 封装一个方法,该方法具有十三个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第十一个参数的类型。 + /// 此委托封装的方法的第十二个参数的类型。 + /// 此委托封装的方法的第十三个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的第十一个参数。 + /// 此委托封装的方法的第十二个参数。 + /// 此委托封装的方法的第十三个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); + + /// + /// 封装一个方法,该方法具有十四个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第十一个参数的类型。 + /// 此委托封装的方法的第十二个参数的类型。 + /// 此委托封装的方法的第十三个参数的类型。 + /// 此委托封装的方法的第十四个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的第十一个参数。 + /// 此委托封装的方法的第十二个参数。 + /// 此委托封装的方法的第十三个参数。 + /// 此委托封装的方法的第十四个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); + + /// + /// 封装一个方法,该方法具有十五个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第十一个参数的类型。 + /// 此委托封装的方法的第十二个参数的类型。 + /// 此委托封装的方法的第十三个参数的类型。 + /// 此委托封装的方法的第十四个参数的类型。 + /// 此委托封装的方法的第十五个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的第十一个参数。 + /// 此委托封装的方法的第十二个参数。 + /// 此委托封装的方法的第十三个参数。 + /// 此委托封装的方法的第十四个参数。 + /// 此委托封装的方法的第十五个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); + + /// + /// 封装一个方法,该方法具有十六个参数并且不返回值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第十一个参数的类型。 + /// 此委托封装的方法的第十二个参数的类型。 + /// 此委托封装的方法的第十三个参数的类型。 + /// 此委托封装的方法的第十四个参数的类型。 + /// 此委托封装的方法的第十五个参数的类型。 + /// 此委托封装的方法的第十六个参数的类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的第十一个参数。 + /// 此委托封装的方法的第十二个参数。 + /// 此委托封装的方法的第十三个参数。 + /// 此委托封装的方法的第十四个参数。 + /// 此委托封装的方法的第十五个参数。 + /// 此委托封装的方法的第十六个参数。 + public delegate void GameFrameworkAction(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkAction.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkAction.cs.meta new file mode 100644 index 0000000..e2de8ea --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkAction.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 41ef6f3313a0ee94193935b3398cc707 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkEntry.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkEntry.cs new file mode 100644 index 0000000..e4ea9c2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkEntry.cs @@ -0,0 +1,133 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework +{ + /// + /// 游戏框架入口。 + /// + public static class GameFrameworkEntry + { + private static readonly GameFrameworkLinkedList s_GameFrameworkModules = new GameFrameworkLinkedList(); + + /// + /// 所有游戏框架模块轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public static void Update(float elapseSeconds, float realElapseSeconds) + { + foreach (GameFrameworkModule module in s_GameFrameworkModules) + { + module.Update(elapseSeconds, realElapseSeconds); + } + } + + /// + /// 关闭并清理所有游戏框架模块。 + /// + public static void Shutdown() + { + for (LinkedListNode current = s_GameFrameworkModules.Last; current != null; current = current.Previous) + { + current.Value.Shutdown(); + } + + s_GameFrameworkModules.Clear(); + ReferencePool.ClearAll(); + Utility.Marshal.FreeCachedHGlobal(); + GameFrameworkLog.SetLogHelper(null); + } + + /// + /// 获取游戏框架模块。 + /// + /// 要获取的游戏框架模块类型。 + /// 要获取的游戏框架模块。 + /// 如果要获取的游戏框架模块不存在,则自动创建该游戏框架模块。 + public static T GetModule() where T : class + { + Type interfaceType = typeof(T); + if (!interfaceType.IsInterface) + { + throw new GameFrameworkException(Utility.Text.Format("You must get module by interface, but '{0}' is not.", interfaceType.FullName)); + } + + if (!interfaceType.FullName.StartsWith("GameFramework.", StringComparison.Ordinal)) + { + throw new GameFrameworkException(Utility.Text.Format("You must get a Game Framework module, but '{0}' is not.", interfaceType.FullName)); + } + + string moduleName = Utility.Text.Format("{0}.{1}", interfaceType.Namespace, interfaceType.Name.Substring(1)); + Type moduleType = Type.GetType(moduleName); + if (moduleType == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find Game Framework module type '{0}'.", moduleName)); + } + + return GetModule(moduleType) as T; + } + + /// + /// 获取游戏框架模块。 + /// + /// 要获取的游戏框架模块类型。 + /// 要获取的游戏框架模块。 + /// 如果要获取的游戏框架模块不存在,则自动创建该游戏框架模块。 + private static GameFrameworkModule GetModule(Type moduleType) + { + foreach (GameFrameworkModule module in s_GameFrameworkModules) + { + if (module.GetType() == moduleType) + { + return module; + } + } + + return CreateModule(moduleType); + } + + /// + /// 创建游戏框架模块。 + /// + /// 要创建的游戏框架模块类型。 + /// 要创建的游戏框架模块。 + private static GameFrameworkModule CreateModule(Type moduleType) + { + GameFrameworkModule module = (GameFrameworkModule)Activator.CreateInstance(moduleType); + if (module == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not create module '{0}'.", moduleType.FullName)); + } + + LinkedListNode current = s_GameFrameworkModules.First; + while (current != null) + { + if (module.Priority > current.Value.Priority) + { + break; + } + + current = current.Next; + } + + if (current != null) + { + s_GameFrameworkModules.AddBefore(current, module); + } + else + { + s_GameFrameworkModules.AddLast(module); + } + + return module; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkEntry.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkEntry.cs.meta new file mode 100644 index 0000000..83aab0f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkEntry.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 82e7e350d8653c14da0eab4537c71db0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkEventArgs.cs new file mode 100644 index 0000000..5fe3a74 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkEventArgs.cs @@ -0,0 +1,29 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework +{ + /// + /// 游戏框架中包含事件数据的类的基类。 + /// + public abstract class GameFrameworkEventArgs : EventArgs, IReference + { + /// + /// 初始化游戏框架中包含事件数据的类的新实例。 + /// + public GameFrameworkEventArgs() + { + } + + /// + /// 清理引用。 + /// + public abstract void Clear(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkEventArgs.cs.meta new file mode 100644 index 0000000..3a6281f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9967f560e536794c8d6fd3f9d1002d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkException.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkException.cs new file mode 100644 index 0000000..3366404 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkException.cs @@ -0,0 +1,56 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Runtime.Serialization; + +namespace GameFramework +{ + /// + /// 游戏框架异常类。 + /// + [Serializable] + public class GameFrameworkException : Exception + { + /// + /// 初始化游戏框架异常类的新实例。 + /// + public GameFrameworkException() + : base() + { + } + + /// + /// 使用指定错误消息初始化游戏框架异常类的新实例。 + /// + /// 描述错误的消息。 + public GameFrameworkException(string message) + : base(message) + { + } + + /// + /// 使用指定错误消息和对作为此异常原因的内部异常的引用来初始化游戏框架异常类的新实例。 + /// + /// 解释异常原因的错误消息。 + /// 导致当前异常的异常。如果 innerException 参数不为空引用,则在处理内部异常的 catch 块中引发当前异常。 + public GameFrameworkException(string message, Exception innerException) + : base(message, innerException) + { + } + + /// + /// 用序列化数据初始化游戏框架异常类的新实例。 + /// + /// 存有有关所引发异常的序列化的对象数据。 + /// 包含有关源或目标的上下文信息。 + protected GameFrameworkException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkException.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkException.cs.meta new file mode 100644 index 0000000..b645107 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cec62ac7ce98a56499e2c171d4a22a7a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkFunc.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkFunc.cs new file mode 100644 index 0000000..2f1c0fb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkFunc.cs @@ -0,0 +1,400 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 封装一个方法,该方法不具有参数,但却返回 TResult 参数指定的类型的值。 + /// + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(); + + /// + /// 封装一个方法,该方法具有一个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的参数类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T arg); + + /// + /// 封装一个方法,该方法具有两个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2); + + /// + /// 封装一个方法,该方法具有三个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3); + + /// + /// 封装一个方法,该方法具有四个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4); + + /// + /// 封装一个方法,该方法具有五个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); + + /// + /// 封装一个方法,该方法具有六个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); + + /// + /// 封装一个方法,该方法具有七个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); + + /// + /// 封装一个方法,该方法具有八个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); + + /// + /// 封装一个方法,该方法具有九个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); + + /// + /// 封装一个方法,该方法具有十个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); + + /// + /// 封装一个方法,该方法具有十一个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第十一个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的第十一个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); + + /// + /// 封装一个方法,该方法具有十二个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第十一个参数的类型。 + /// 此委托封装的方法的第十二个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的第十一个参数。 + /// 此委托封装的方法的第十二个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); + + /// + /// 封装一个方法,该方法具有十三个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第十一个参数的类型。 + /// 此委托封装的方法的第十二个参数的类型。 + /// 此委托封装的方法的第十三个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的第十一个参数。 + /// 此委托封装的方法的第十二个参数。 + /// 此委托封装的方法的第十三个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); + + /// + /// 封装一个方法,该方法具有十四个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第十一个参数的类型。 + /// 此委托封装的方法的第十二个参数的类型。 + /// 此委托封装的方法的第十三个参数的类型。 + /// 此委托封装的方法的第十四个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的第十一个参数。 + /// 此委托封装的方法的第十二个参数。 + /// 此委托封装的方法的第十三个参数。 + /// 此委托封装的方法的第十四个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); + + /// + /// 封装一个方法,该方法具有十五个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第十一个参数的类型。 + /// 此委托封装的方法的第十二个参数的类型。 + /// 此委托封装的方法的第十三个参数的类型。 + /// 此委托封装的方法的第十四个参数的类型。 + /// 此委托封装的方法的第十五个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的第十一个参数。 + /// 此委托封装的方法的第十二个参数。 + /// 此委托封装的方法的第十三个参数。 + /// 此委托封装的方法的第十四个参数。 + /// 此委托封装的方法的第十五个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); + + /// + /// 封装一个方法,该方法具有十六个参数,并返回 TResult 参数所指定的类型的值。 + /// + /// 此委托封装的方法的第一个参数的类型。 + /// 此委托封装的方法的第二个参数的类型。 + /// 此委托封装的方法的第三个参数的类型。 + /// 此委托封装的方法的第四个参数的类型。 + /// 此委托封装的方法的第五个参数的类型。 + /// 此委托封装的方法的第六个参数的类型。 + /// 此委托封装的方法的第七个参数的类型。 + /// 此委托封装的方法的第八个参数的类型。 + /// 此委托封装的方法的第九个参数的类型。 + /// 此委托封装的方法的第十个参数的类型。 + /// 此委托封装的方法的第十一个参数的类型。 + /// 此委托封装的方法的第十二个参数的类型。 + /// 此委托封装的方法的第十三个参数的类型。 + /// 此委托封装的方法的第十四个参数的类型。 + /// 此委托封装的方法的第十五个参数的类型。 + /// 此委托封装的方法的第十六个参数的类型。 + /// 此委托封装的方法的返回值类型。 + /// 此委托封装的方法的第一个参数。 + /// 此委托封装的方法的第二个参数。 + /// 此委托封装的方法的第三个参数。 + /// 此委托封装的方法的第四个参数。 + /// 此委托封装的方法的第五个参数。 + /// 此委托封装的方法的第六个参数。 + /// 此委托封装的方法的第七个参数。 + /// 此委托封装的方法的第八个参数。 + /// 此委托封装的方法的第九个参数。 + /// 此委托封装的方法的第十个参数。 + /// 此委托封装的方法的第十一个参数。 + /// 此委托封装的方法的第十二个参数。 + /// 此委托封装的方法的第十三个参数。 + /// 此委托封装的方法的第十四个参数。 + /// 此委托封装的方法的第十五个参数。 + /// 此委托封装的方法的第十六个参数。 + /// 此委托封装的方法的返回值。 + public delegate TResult GameFrameworkFunc(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkFunc.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkFunc.cs.meta new file mode 100644 index 0000000..039d9f8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkFunc.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e2a0d9a1eb3b94540b97949e4e49754d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkLinkedList.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkLinkedList.cs new file mode 100644 index 0000000..0070534 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkLinkedList.cs @@ -0,0 +1,453 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace GameFramework +{ + /// + /// 游戏框架链表类。 + /// + /// 指定链表的元素类型。 + public sealed class GameFrameworkLinkedList : ICollection, IEnumerable, ICollection, IEnumerable + { + private readonly LinkedList m_LinkedList; + private readonly Queue> m_CachedNodes; + + /// + /// 初始化游戏框架链表类的新实例。 + /// + public GameFrameworkLinkedList() + { + m_LinkedList = new LinkedList(); + m_CachedNodes = new Queue>(); + } + + /// + /// 获取链表中实际包含的结点数量。 + /// + public int Count + { + get + { + return m_LinkedList.Count; + } + } + + /// + /// 获取链表结点缓存数量。 + /// + public int CachedNodeCount + { + get + { + return m_CachedNodes.Count; + } + } + + /// + /// 获取链表的第一个结点。 + /// + public LinkedListNode First + { + get + { + return m_LinkedList.First; + } + } + + /// + /// 获取链表的最后一个结点。 + /// + public LinkedListNode Last + { + get + { + return m_LinkedList.Last; + } + } + + /// + /// 获取一个值,该值指示 ICollection`1 是否为只读。 + /// + public bool IsReadOnly + { + get + { + return ((ICollection)m_LinkedList).IsReadOnly; + } + } + + /// + /// 获取可用于同步对 ICollection 的访问的对象。 + /// + public object SyncRoot + { + get + { + return ((ICollection)m_LinkedList).SyncRoot; + } + } + + /// + /// 获取一个值,该值指示是否同步对 ICollection 的访问(线程安全)。 + /// + public bool IsSynchronized + { + get + { + return ((ICollection)m_LinkedList).IsSynchronized; + } + } + + /// + /// 在链表中指定的现有结点后添加包含指定值的新结点。 + /// + /// 指定的现有结点。 + /// 指定值。 + /// 包含指定值的新结点。 + public LinkedListNode AddAfter(LinkedListNode node, T value) + { + LinkedListNode newNode = AcquireNode(value); + m_LinkedList.AddAfter(node, newNode); + return newNode; + } + + /// + /// 在链表中指定的现有结点后添加指定的新结点。 + /// + /// 指定的现有结点。 + /// 指定的新结点。 + public void AddAfter(LinkedListNode node, LinkedListNode newNode) + { + m_LinkedList.AddAfter(node, newNode); + } + + /// + /// 在链表中指定的现有结点前添加包含指定值的新结点。 + /// + /// 指定的现有结点。 + /// 指定值。 + /// 包含指定值的新结点。 + public LinkedListNode AddBefore(LinkedListNode node, T value) + { + LinkedListNode newNode = AcquireNode(value); + m_LinkedList.AddBefore(node, newNode); + return newNode; + } + + /// + /// 在链表中指定的现有结点前添加指定的新结点。 + /// + /// 指定的现有结点。 + /// 指定的新结点。 + public void AddBefore(LinkedListNode node, LinkedListNode newNode) + { + m_LinkedList.AddBefore(node, newNode); + } + + /// + /// 在链表的开头处添加包含指定值的新结点。 + /// + /// 指定值。 + /// 包含指定值的新结点。 + public LinkedListNode AddFirst(T value) + { + LinkedListNode node = AcquireNode(value); + m_LinkedList.AddFirst(node); + return node; + } + + /// + /// 在链表的开头处添加指定的新结点。 + /// + /// 指定的新结点。 + public void AddFirst(LinkedListNode node) + { + m_LinkedList.AddFirst(node); + } + + /// + /// 在链表的结尾处添加包含指定值的新结点。 + /// + /// 指定值。 + /// 包含指定值的新结点。 + public LinkedListNode AddLast(T value) + { + LinkedListNode node = AcquireNode(value); + m_LinkedList.AddLast(node); + return node; + } + + /// + /// 在链表的结尾处添加指定的新结点。 + /// + /// 指定的新结点。 + public void AddLast(LinkedListNode node) + { + m_LinkedList.AddLast(node); + } + + /// + /// 从链表中移除所有结点。 + /// + public void Clear() + { + LinkedListNode current = m_LinkedList.First; + while (current != null) + { + ReleaseNode(current); + current = current.Next; + } + + m_LinkedList.Clear(); + } + + /// + /// 清除链表结点缓存。 + /// + public void ClearCachedNodes() + { + m_CachedNodes.Clear(); + } + + /// + /// 确定某值是否在链表中。 + /// + /// 指定值。 + /// 某值是否在链表中。 + public bool Contains(T value) + { + return m_LinkedList.Contains(value); + } + + /// + /// 从目标数组的指定索引处开始将整个链表复制到兼容的一维数组。 + /// + /// 一维数组,它是从链表复制的元素的目标。数组必须具有从零开始的索引。 + /// array 中从零开始的索引,从此处开始复制。 + public void CopyTo(T[] array, int index) + { + m_LinkedList.CopyTo(array, index); + } + + /// + /// 从特定的 ICollection 索引开始,将数组的元素复制到一个数组中。 + /// + /// 一维数组,它是从 ICollection 复制的元素的目标。数组必须具有从零开始的索引。 + /// array 中从零开始的索引,从此处开始复制。 + public void CopyTo(Array array, int index) + { + ((ICollection)m_LinkedList).CopyTo(array, index); + } + + /// + /// 查找包含指定值的第一个结点。 + /// + /// 要查找的指定值。 + /// 包含指定值的第一个结点。 + public LinkedListNode Find(T value) + { + return m_LinkedList.Find(value); + } + + /// + /// 查找包含指定值的最后一个结点。 + /// + /// 要查找的指定值。 + /// 包含指定值的最后一个结点。 + public LinkedListNode FindLast(T value) + { + return m_LinkedList.FindLast(value); + } + + /// + /// 从链表中移除指定值的第一个匹配项。 + /// + /// 指定值。 + /// 是否移除成功。 + public bool Remove(T value) + { + LinkedListNode node = m_LinkedList.Find(value); + if (node != null) + { + m_LinkedList.Remove(node); + ReleaseNode(node); + return true; + } + + return false; + } + + /// + /// 从链表中移除指定的结点。 + /// + /// 指定的结点。 + public void Remove(LinkedListNode node) + { + m_LinkedList.Remove(node); + ReleaseNode(node); + } + + /// + /// 移除位于链表开头处的结点。 + /// + public void RemoveFirst() + { + LinkedListNode first = m_LinkedList.First; + if (first == null) + { + throw new GameFrameworkException("First is invalid."); + } + + m_LinkedList.RemoveFirst(); + ReleaseNode(first); + } + + /// + /// 移除位于链表结尾处的结点。 + /// + public void RemoveLast() + { + LinkedListNode last = m_LinkedList.Last; + if (last == null) + { + throw new GameFrameworkException("Last is invalid."); + } + + m_LinkedList.RemoveLast(); + ReleaseNode(last); + } + + /// + /// 返回循环访问集合的枚举数。 + /// + /// 循环访问集合的枚举数。 + public Enumerator GetEnumerator() + { + return new Enumerator(m_LinkedList); + } + + private LinkedListNode AcquireNode(T value) + { + LinkedListNode node = null; + if (m_CachedNodes.Count > 0) + { + node = m_CachedNodes.Dequeue(); + node.Value = value; + } + else + { + node = new LinkedListNode(value); + } + + return node; + } + + private void ReleaseNode(LinkedListNode node) + { + node.Value = default(T); + m_CachedNodes.Enqueue(node); + } + + /// + /// 将值添加到 ICollection`1 的结尾处。 + /// + /// 要添加的值。 + void ICollection.Add(T value) + { + AddLast(value); + } + + /// + /// 返回循环访问集合的枚举数。 + /// + /// 循环访问集合的枚举数。 + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// 返回循环访问集合的枚举数。 + /// + /// 循环访问集合的枚举数。 + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// 循环访问集合的枚举数。 + /// + [StructLayout(LayoutKind.Auto)] + public struct Enumerator : IEnumerator, IEnumerator + { + private LinkedList.Enumerator m_Enumerator; + + internal Enumerator(LinkedList linkedList) + { + if (linkedList == null) + { + throw new GameFrameworkException("Linked list is invalid."); + } + + m_Enumerator = linkedList.GetEnumerator(); + } + + /// + /// 获取当前结点。 + /// + public T Current + { + get + { + return m_Enumerator.Current; + } + } + + /// + /// 获取当前的枚举数。 + /// + object IEnumerator.Current + { + get + { + return m_Enumerator.Current; + } + } + + /// + /// 清理枚举数。 + /// + public void Dispose() + { + m_Enumerator.Dispose(); + } + + /// + /// 获取下一个结点。 + /// + /// 返回下一个结点。 + public bool MoveNext() + { + return m_Enumerator.MoveNext(); + } + + /// + /// 重置枚举数。 + /// + void IEnumerator.Reset() + { + ((IEnumerator)m_Enumerator).Reset(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkLinkedList.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkLinkedList.cs.meta new file mode 100644 index 0000000..bb339f9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkLinkedList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fa2b9dc9d293bcf4ab3a480914abe5fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkLinkedListRange.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkLinkedListRange.cs new file mode 100644 index 0000000..2e9dbf0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkLinkedListRange.cs @@ -0,0 +1,217 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace GameFramework +{ + /// + /// 游戏框架链表范围。 + /// + /// 指定链表范围的元素类型。 + [StructLayout(LayoutKind.Auto)] + public struct GameFrameworkLinkedListRange : IEnumerable, IEnumerable + { + private readonly LinkedListNode m_First; + private readonly LinkedListNode m_Terminal; + + /// + /// 初始化游戏框架链表范围的新实例。 + /// + /// 链表范围的开始结点。 + /// 链表范围的终结标记结点。 + public GameFrameworkLinkedListRange(LinkedListNode first, LinkedListNode terminal) + { + if (first == null || terminal == null || first == terminal) + { + throw new GameFrameworkException("Range is invalid."); + } + + m_First = first; + m_Terminal = terminal; + } + + /// + /// 获取链表范围是否有效。 + /// + public bool IsValid + { + get + { + return m_First != null && m_Terminal != null && m_First != m_Terminal; + } + } + + /// + /// 获取链表范围的开始结点。 + /// + public LinkedListNode First + { + get + { + return m_First; + } + } + + /// + /// 获取链表范围的终结标记结点。 + /// + public LinkedListNode Terminal + { + get + { + return m_Terminal; + } + } + + /// + /// 获取链表范围的结点数量。 + /// + public int Count + { + get + { + if (!IsValid) + { + return 0; + } + + int count = 0; + for (LinkedListNode current = m_First; current != null && current != m_Terminal; current = current.Next) + { + count++; + } + + return count; + } + } + + /// + /// 检查是否包含指定值。 + /// + /// 要检查的值。 + /// 是否包含指定值。 + public bool Contains(T value) + { + for (LinkedListNode current = m_First; current != null && current != m_Terminal; current = current.Next) + { + if (current.Value.Equals(value)) + { + return true; + } + } + + return false; + } + + /// + /// 返回循环访问集合的枚举数。 + /// + /// 循环访问集合的枚举数。 + public Enumerator GetEnumerator() + { + return new Enumerator(this); + } + + /// + /// 返回循环访问集合的枚举数。 + /// + /// 循环访问集合的枚举数。 + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// 返回循环访问集合的枚举数。 + /// + /// 循环访问集合的枚举数。 + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// 循环访问集合的枚举数。 + /// + [StructLayout(LayoutKind.Auto)] + public struct Enumerator : IEnumerator, IEnumerator + { + private readonly GameFrameworkLinkedListRange m_GameFrameworkLinkedListRange; + private LinkedListNode m_Current; + private T m_CurrentValue; + + internal Enumerator(GameFrameworkLinkedListRange range) + { + if (!range.IsValid) + { + throw new GameFrameworkException("Range is invalid."); + } + + m_GameFrameworkLinkedListRange = range; + m_Current = m_GameFrameworkLinkedListRange.m_First; + m_CurrentValue = default(T); + } + + /// + /// 获取当前结点。 + /// + public T Current + { + get + { + return m_CurrentValue; + } + } + + /// + /// 获取当前的枚举数。 + /// + object IEnumerator.Current + { + get + { + return m_CurrentValue; + } + } + + /// + /// 清理枚举数。 + /// + public void Dispose() + { + } + + /// + /// 获取下一个结点。 + /// + /// 返回下一个结点。 + public bool MoveNext() + { + if (m_Current == null || m_Current == m_GameFrameworkLinkedListRange.m_Terminal) + { + return false; + } + + m_CurrentValue = m_Current.Value; + m_Current = m_Current.Next; + return true; + } + + /// + /// 重置枚举数。 + /// + void IEnumerator.Reset() + { + m_Current = m_GameFrameworkLinkedListRange.m_First; + m_CurrentValue = default(T); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkLinkedListRange.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkLinkedListRange.cs.meta new file mode 100644 index 0000000..32d4bf6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkLinkedListRange.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7b51de77bba999648b187c0cda831e18 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkModule.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkModule.cs new file mode 100644 index 0000000..76f2a95 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkModule.cs @@ -0,0 +1,39 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 游戏框架模块抽象类。 + /// + internal abstract class GameFrameworkModule + { + /// + /// 获取游戏框架模块优先级。 + /// + /// 优先级较高的模块会优先轮询,并且关闭操作会后进行。 + internal virtual int Priority + { + get + { + return 0; + } + } + + /// + /// 游戏框架模块轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal abstract void Update(float elapseSeconds, float realElapseSeconds); + + /// + /// 关闭并清理游戏框架模块。 + /// + internal abstract void Shutdown(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkModule.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkModule.cs.meta new file mode 100644 index 0000000..2b48e0f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkModule.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fcae23c6b22c681439e41dc75f38fd7b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkMultiDictionary.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkMultiDictionary.cs new file mode 100644 index 0000000..3eabc0e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkMultiDictionary.cs @@ -0,0 +1,283 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace GameFramework +{ + /// + /// 游戏框架多值字典类。 + /// + /// 指定多值字典的主键类型。 + /// 指定多值字典的值类型。 + public sealed class GameFrameworkMultiDictionary : IEnumerable>>, IEnumerable + { + private readonly GameFrameworkLinkedList m_LinkedList; + private readonly Dictionary> m_Dictionary; + + /// + /// 初始化游戏框架多值字典类的新实例。 + /// + public GameFrameworkMultiDictionary() + { + m_LinkedList = new GameFrameworkLinkedList(); + m_Dictionary = new Dictionary>(); + } + + /// + /// 获取多值字典中实际包含的主键数量。 + /// + public int Count + { + get + { + return m_Dictionary.Count; + } + } + + /// + /// 获取多值字典中指定主键的范围。 + /// + /// 指定的主键。 + /// 指定主键的范围。 + public GameFrameworkLinkedListRange this[TKey key] + { + get + { + GameFrameworkLinkedListRange range = default(GameFrameworkLinkedListRange); + m_Dictionary.TryGetValue(key, out range); + return range; + } + } + + /// + /// 清理多值字典。 + /// + public void Clear() + { + m_Dictionary.Clear(); + m_LinkedList.Clear(); + } + + /// + /// 检查多值字典中是否包含指定主键。 + /// + /// 要检查的主键。 + /// 多值字典中是否包含指定主键。 + public bool Contains(TKey key) + { + return m_Dictionary.ContainsKey(key); + } + + /// + /// 检查多值字典中是否包含指定值。 + /// + /// 要检查的主键。 + /// 要检查的值。 + /// 多值字典中是否包含指定值。 + public bool Contains(TKey key, TValue value) + { + GameFrameworkLinkedListRange range = default(GameFrameworkLinkedListRange); + if (m_Dictionary.TryGetValue(key, out range)) + { + return range.Contains(value); + } + + return false; + } + + /// + /// 尝试获取多值字典中指定主键的范围。 + /// + /// 指定的主键。 + /// 指定主键的范围。 + /// 是否获取成功。 + public bool TryGetValue(TKey key, out GameFrameworkLinkedListRange range) + { + return m_Dictionary.TryGetValue(key, out range); + } + + /// + /// 向指定的主键增加指定的值。 + /// + /// 指定的主键。 + /// 指定的值。 + public void Add(TKey key, TValue value) + { + GameFrameworkLinkedListRange range = default(GameFrameworkLinkedListRange); + if (m_Dictionary.TryGetValue(key, out range)) + { + m_LinkedList.AddBefore(range.Terminal, value); + } + else + { + LinkedListNode first = m_LinkedList.AddLast(value); + LinkedListNode terminal = m_LinkedList.AddLast(default(TValue)); + m_Dictionary.Add(key, new GameFrameworkLinkedListRange(first, terminal)); + } + } + + /// + /// 从指定的主键中移除指定的值。 + /// + /// 指定的主键。 + /// 指定的值。 + /// 是否移除成功。 + public bool Remove(TKey key, TValue value) + { + GameFrameworkLinkedListRange range = default(GameFrameworkLinkedListRange); + if (m_Dictionary.TryGetValue(key, out range)) + { + for (LinkedListNode current = range.First; current != null && current != range.Terminal; current = current.Next) + { + if (current.Value.Equals(value)) + { + if (current == range.First) + { + LinkedListNode next = current.Next; + if (next == range.Terminal) + { + m_LinkedList.Remove(next); + m_Dictionary.Remove(key); + } + else + { + m_Dictionary[key] = new GameFrameworkLinkedListRange(next, range.Terminal); + } + } + + m_LinkedList.Remove(current); + return true; + } + } + } + + return false; + } + + /// + /// 从指定的主键中移除所有的值。 + /// + /// 指定的主键。 + /// 是否移除成功。 + public bool RemoveAll(TKey key) + { + GameFrameworkLinkedListRange range = default(GameFrameworkLinkedListRange); + if (m_Dictionary.TryGetValue(key, out range)) + { + m_Dictionary.Remove(key); + + LinkedListNode current = range.First; + while (current != null) + { + LinkedListNode next = current != range.Terminal ? current.Next : null; + m_LinkedList.Remove(current); + current = next; + } + + return true; + } + + return false; + } + + /// + /// 返回循环访问集合的枚举数。 + /// + /// 循环访问集合的枚举数。 + public Enumerator GetEnumerator() + { + return new Enumerator(m_Dictionary); + } + + /// + /// 返回循环访问集合的枚举数。 + /// + /// 循环访问集合的枚举数。 + IEnumerator>> IEnumerable>>.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// 返回循环访问集合的枚举数。 + /// + /// 循环访问集合的枚举数。 + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// 循环访问集合的枚举数。 + /// + [StructLayout(LayoutKind.Auto)] + public struct Enumerator : IEnumerator>>, IEnumerator + { + private Dictionary>.Enumerator m_Enumerator; + + internal Enumerator(Dictionary> dictionary) + { + if (dictionary == null) + { + throw new GameFrameworkException("Dictionary is invalid."); + } + + m_Enumerator = dictionary.GetEnumerator(); + } + + /// + /// 获取当前结点。 + /// + public KeyValuePair> Current + { + get + { + return m_Enumerator.Current; + } + } + + /// + /// 获取当前的枚举数。 + /// + object IEnumerator.Current + { + get + { + return m_Enumerator.Current; + } + } + + /// + /// 清理枚举数。 + /// + public void Dispose() + { + m_Enumerator.Dispose(); + } + + /// + /// 获取下一个结点。 + /// + /// 返回下一个结点。 + public bool MoveNext() + { + return m_Enumerator.MoveNext(); + } + + /// + /// 重置枚举数。 + /// + void IEnumerator.Reset() + { + ((IEnumerator>>)m_Enumerator).Reset(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkMultiDictionary.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkMultiDictionary.cs.meta new file mode 100644 index 0000000..cfdd6bf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkMultiDictionary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: abe0a7a28112b9c4c91e54ca4e7eae5a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkSerializer.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkSerializer.cs new file mode 100644 index 0000000..54547d0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkSerializer.cs @@ -0,0 +1,208 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; +using System.IO; + +namespace GameFramework +{ + /// + /// 游戏框架序列化器基类。 + /// + /// 要序列化的数据类型。 + public abstract class GameFrameworkSerializer + { + private readonly Dictionary m_SerializeCallbacks; + private readonly Dictionary m_DeserializeCallbacks; + private readonly Dictionary m_TryGetValueCallbacks; + private byte m_LatestSerializeCallbackVersion; + + /// + /// 初始化游戏框架序列化器基类的新实例。 + /// + public GameFrameworkSerializer() + { + m_SerializeCallbacks = new Dictionary(); + m_DeserializeCallbacks = new Dictionary(); + m_TryGetValueCallbacks = new Dictionary(); + m_LatestSerializeCallbackVersion = 0; + } + + /// + /// 序列化回调函数。 + /// + /// 目标流。 + /// 要序列化的数据。 + /// 是否序列化数据成功。 + public delegate bool SerializeCallback(Stream stream, T data); + + /// + /// 反序列化回调函数。 + /// + /// 指定流。 + /// 反序列化的数据。 + public delegate T DeserializeCallback(Stream stream); + + /// + /// 尝试从指定流获取指定键的值回调函数。 + /// + /// 指定流。 + /// 指定键。 + /// 指定键的值。 + /// 是否从指定流获取指定键的值成功。 + public delegate bool TryGetValueCallback(Stream stream, string key, out object value); + + /// + /// 注册序列化回调函数。 + /// + /// 序列化回调函数的版本。 + /// 序列化回调函数。 + public void RegisterSerializeCallback(byte version, SerializeCallback callback) + { + if (callback == null) + { + throw new GameFrameworkException("Serialize callback is invalid."); + } + + m_SerializeCallbacks[version] = callback; + if (version > m_LatestSerializeCallbackVersion) + { + m_LatestSerializeCallbackVersion = version; + } + } + + /// + /// 注册反序列化回调函数。 + /// + /// 反序列化回调函数的版本。 + /// 反序列化回调函数。 + public void RegisterDeserializeCallback(byte version, DeserializeCallback callback) + { + if (callback == null) + { + throw new GameFrameworkException("Deserialize callback is invalid."); + } + + m_DeserializeCallbacks[version] = callback; + } + + /// + /// 注册尝试从指定流获取指定键的值回调函数。 + /// + /// 尝试从指定流获取指定键的值回调函数的版本。 + /// 尝试从指定流获取指定键的值回调函数。 + public void RegisterTryGetValueCallback(byte version, TryGetValueCallback callback) + { + if (callback == null) + { + throw new GameFrameworkException("Try get value callback is invalid."); + } + + m_TryGetValueCallbacks[version] = callback; + } + + /// + /// 序列化数据到目标流中。 + /// + /// 目标流。 + /// 要序列化的数据。 + /// 是否序列化数据成功。 + public bool Serialize(Stream stream, T data) + { + if (m_SerializeCallbacks.Count <= 0) + { + throw new GameFrameworkException("No serialize callback registered."); + } + + return Serialize(stream, data, m_LatestSerializeCallbackVersion); + } + + /// + /// 序列化数据到目标流中。 + /// + /// 目标流。 + /// 要序列化的数据。 + /// 序列化回调函数的版本。 + /// 是否序列化数据成功。 + public bool Serialize(Stream stream, T data, byte version) + { + byte[] header = GetHeader(); + stream.WriteByte(header[0]); + stream.WriteByte(header[1]); + stream.WriteByte(header[2]); + stream.WriteByte(version); + SerializeCallback callback = null; + if (!m_SerializeCallbacks.TryGetValue(version, out callback)) + { + throw new GameFrameworkException(Utility.Text.Format("Serialize callback '{0}' is not exist.", version)); + } + + return callback(stream, data); + } + + /// + /// 从指定流反序列化数据。 + /// + /// 指定流。 + /// 反序列化的数据。 + public T Deserialize(Stream stream) + { + byte[] header = GetHeader(); + byte header0 = (byte)stream.ReadByte(); + byte header1 = (byte)stream.ReadByte(); + byte header2 = (byte)stream.ReadByte(); + if (header0 != header[0] || header1 != header[1] || header2 != header[2]) + { + throw new GameFrameworkException(Utility.Text.Format("Header is invalid, need '{0}{1}{2}', current '{3}{4}{5}'.", (char)header[0], (char)header[1], (char)header[2], (char)header0, (char)header1, (char)header2)); + } + + byte version = (byte)stream.ReadByte(); + DeserializeCallback callback = null; + if (!m_DeserializeCallbacks.TryGetValue(version, out callback)) + { + throw new GameFrameworkException(Utility.Text.Format("Deserialize callback '{0}' is not exist.", version)); + } + + return callback(stream); + } + + /// + /// 尝试从指定流获取指定键的值。 + /// + /// 指定流。 + /// 指定键。 + /// 指定键的值。 + /// 是否从指定流获取指定键的值成功。 + public bool TryGetValue(Stream stream, string key, out object value) + { + value = null; + byte[] header = GetHeader(); + byte header0 = (byte)stream.ReadByte(); + byte header1 = (byte)stream.ReadByte(); + byte header2 = (byte)stream.ReadByte(); + if (header0 != header[0] || header1 != header[1] || header2 != header[2]) + { + return false; + } + + byte version = (byte)stream.ReadByte(); + TryGetValueCallback callback = null; + if (!m_TryGetValueCallbacks.TryGetValue(version, out callback)) + { + return false; + } + + return callback(stream, key, out value); + } + + /// + /// 获取数据头标识。 + /// + /// 数据头标识。 + protected abstract byte[] GetHeader(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkSerializer.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkSerializer.cs.meta new file mode 100644 index 0000000..cf38f0e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/GameFrameworkSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b232b459d4e22d94dbebbadf54ee5823 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log.meta new file mode 100644 index 0000000..96ceecd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 57ee0dd2c127e484cb25be3a9537417d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLog.ILogHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLog.ILogHelper.cs new file mode 100644 index 0000000..e8cd882 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLog.ILogHelper.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + public static partial class GameFrameworkLog + { + /// + /// 游戏框架日志辅助器接口。 + /// + public interface ILogHelper + { + /// + /// 记录日志。 + /// + /// 游戏框架日志等级。 + /// 日志内容。 + void Log(GameFrameworkLogLevel level, object message); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLog.ILogHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLog.ILogHelper.cs.meta new file mode 100644 index 0000000..4d69bee --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLog.ILogHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f3f7268aab6139b48bc311889bf244fb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLog.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLog.cs new file mode 100644 index 0000000..d4d9366 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLog.cs @@ -0,0 +1,2646 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 游戏框架日志类。 + /// + public static partial class GameFrameworkLog + { + private static ILogHelper s_LogHelper = null; + + /// + /// 设置游戏框架日志辅助器。 + /// + /// 要设置的游戏框架日志辅助器。 + public static void SetLogHelper(ILogHelper logHelper) + { + s_LogHelper = logHelper; + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志内容。 + public static void Debug(object message) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, message); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志内容。 + public static void Debug(string message) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, message); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数的类型。 + /// 日志格式。 + /// 日志参数。 + public static void Debug(string format, T arg) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + public static void Debug(string format, T1 arg1, T2 arg2) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志参数 16 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 日志参数 16。 + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Debug, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志内容。 + public static void Info(object message) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, message); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志内容。 + public static void Info(string message) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, message); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数的类型。 + /// 日志格式。 + /// 日志参数。 + public static void Info(string format, T arg) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + public static void Info(string format, T1 arg1, T2 arg2) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志参数 16 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 日志参数 16。 + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Info, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志内容。 + public static void Warning(object message) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, message); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志内容。 + public static void Warning(string message) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, message); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数的类型。 + /// 日志格式。 + /// 日志参数。 + public static void Warning(string format, T arg) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + public static void Warning(string format, T1 arg1, T2 arg2) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志参数 16 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 日志参数 16。 + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Warning, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志内容。 + public static void Error(object message) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, message); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志内容。 + public static void Error(string message) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, message); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数的类型。 + /// 日志格式。 + /// 日志参数。 + public static void Error(string format, T arg) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + public static void Error(string format, T1 arg1, T2 arg2) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志参数 16 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 日志参数 16。 + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Error, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志内容。 + public static void Fatal(object message) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, message); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志内容。 + public static void Fatal(string message) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, message); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数的类型。 + /// 日志格式。 + /// 日志参数。 + public static void Fatal(string format, T arg) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + public static void Fatal(string format, T1 arg1, T2 arg2) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15)); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志参数 16 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 日志参数 16。 + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + if (s_LogHelper == null) + { + return; + } + + s_LogHelper.Log(GameFrameworkLogLevel.Fatal, Utility.Text.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLog.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLog.cs.meta new file mode 100644 index 0000000..0d558c4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLog.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 87a0237d37afaeb4488b1f110bd1bf9e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLogLevel.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLogLevel.cs new file mode 100644 index 0000000..1afe8a4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLogLevel.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 游戏框架日志等级。 + /// + public enum GameFrameworkLogLevel : byte + { + /// + /// 调试。 + /// + Debug = 0, + + /// + /// 信息。 + /// + Info, + + /// + /// 警告。 + /// + Warning, + + /// + /// 错误。 + /// + Error, + + /// + /// 严重错误。 + /// + Fatal + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLogLevel.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLogLevel.cs.meta new file mode 100644 index 0000000..83eebdd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Log/GameFrameworkLogLevel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8ec08a22e22eac54a94422909c7e9912 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool.meta new file mode 100644 index 0000000..3606766 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1838d0faa85527b4d8e2769246cf9b52 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/IReference.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/IReference.cs new file mode 100644 index 0000000..77025c5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/IReference.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 引用接口。 + /// + public interface IReference + { + /// + /// 清理引用。 + /// + void Clear(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/IReference.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/IReference.cs.meta new file mode 100644 index 0000000..7834bcf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/IReference.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f22c43c115dc0d745bf02f2e54b284d1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePool.ReferenceCollection.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePool.ReferenceCollection.cs new file mode 100644 index 0000000..72e023e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePool.ReferenceCollection.cs @@ -0,0 +1,202 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework +{ + public static partial class ReferencePool + { + private sealed class ReferenceCollection + { + private readonly Queue m_References; + private readonly Type m_ReferenceType; + private int m_UsingReferenceCount; + private int m_AcquireReferenceCount; + private int m_ReleaseReferenceCount; + private int m_AddReferenceCount; + private int m_RemoveReferenceCount; + + public ReferenceCollection(Type referenceType) + { + m_References = new Queue(); + m_ReferenceType = referenceType; + m_UsingReferenceCount = 0; + m_AcquireReferenceCount = 0; + m_ReleaseReferenceCount = 0; + m_AddReferenceCount = 0; + m_RemoveReferenceCount = 0; + } + + public Type ReferenceType + { + get + { + return m_ReferenceType; + } + } + + public int UnusedReferenceCount + { + get + { + return m_References.Count; + } + } + + public int UsingReferenceCount + { + get + { + return m_UsingReferenceCount; + } + } + + public int AcquireReferenceCount + { + get + { + return m_AcquireReferenceCount; + } + } + + public int ReleaseReferenceCount + { + get + { + return m_ReleaseReferenceCount; + } + } + + public int AddReferenceCount + { + get + { + return m_AddReferenceCount; + } + } + + public int RemoveReferenceCount + { + get + { + return m_RemoveReferenceCount; + } + } + + public T Acquire() where T : class, IReference, new() + { + if (typeof(T) != m_ReferenceType) + { + throw new GameFrameworkException("Type is invalid."); + } + + m_UsingReferenceCount++; + m_AcquireReferenceCount++; + lock (m_References) + { + if (m_References.Count > 0) + { + return (T)m_References.Dequeue(); + } + } + + m_AddReferenceCount++; + return new T(); + } + + public IReference Acquire() + { + m_UsingReferenceCount++; + m_AcquireReferenceCount++; + lock (m_References) + { + if (m_References.Count > 0) + { + return m_References.Dequeue(); + } + } + + m_AddReferenceCount++; + return (IReference)Activator.CreateInstance(m_ReferenceType); + } + + public void Release(IReference reference) + { + reference.Clear(); + lock (m_References) + { + if (m_EnableStrictCheck && m_References.Contains(reference)) + { + throw new GameFrameworkException("The reference has been released."); + } + + m_References.Enqueue(reference); + } + + m_ReleaseReferenceCount++; + m_UsingReferenceCount--; + } + + public void Add(int count) where T : class, IReference, new() + { + if (typeof(T) != m_ReferenceType) + { + throw new GameFrameworkException("Type is invalid."); + } + + lock (m_References) + { + m_AddReferenceCount += count; + while (count-- > 0) + { + m_References.Enqueue(new T()); + } + } + } + + public void Add(int count) + { + lock (m_References) + { + m_AddReferenceCount += count; + while (count-- > 0) + { + m_References.Enqueue((IReference)Activator.CreateInstance(m_ReferenceType)); + } + } + } + + public void Remove(int count) + { + lock (m_References) + { + if (count > m_References.Count) + { + count = m_References.Count; + } + + m_RemoveReferenceCount += count; + while (count-- > 0) + { + m_References.Dequeue(); + } + } + } + + public void RemoveAll() + { + lock (m_References) + { + m_RemoveReferenceCount += m_References.Count; + m_References.Clear(); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePool.ReferenceCollection.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePool.ReferenceCollection.cs.meta new file mode 100644 index 0000000..db809f9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePool.ReferenceCollection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c19eaae426d076b45987fed1300b9820 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePool.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePool.cs new file mode 100644 index 0000000..b857b2c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePool.cs @@ -0,0 +1,225 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework +{ + /// + /// 引用池。 + /// + public static partial class ReferencePool + { + private static readonly Dictionary s_ReferenceCollections = new Dictionary(); + private static bool m_EnableStrictCheck = false; + + /// + /// 获取或设置是否开启强制检查。 + /// + public static bool EnableStrictCheck + { + get + { + return m_EnableStrictCheck; + } + set + { + m_EnableStrictCheck = value; + } + } + + /// + /// 获取引用池的数量。 + /// + public static int Count + { + get + { + return s_ReferenceCollections.Count; + } + } + + /// + /// 获取所有引用池的信息。 + /// + /// 所有引用池的信息。 + public static ReferencePoolInfo[] GetAllReferencePoolInfos() + { + int index = 0; + ReferencePoolInfo[] results = null; + + lock (s_ReferenceCollections) + { + results = new ReferencePoolInfo[s_ReferenceCollections.Count]; + foreach (KeyValuePair referenceCollection in s_ReferenceCollections) + { + results[index++] = new ReferencePoolInfo(referenceCollection.Key, referenceCollection.Value.UnusedReferenceCount, referenceCollection.Value.UsingReferenceCount, referenceCollection.Value.AcquireReferenceCount, referenceCollection.Value.ReleaseReferenceCount, referenceCollection.Value.AddReferenceCount, referenceCollection.Value.RemoveReferenceCount); + } + } + + return results; + } + + /// + /// 清除所有引用池。 + /// + public static void ClearAll() + { + lock (s_ReferenceCollections) + { + foreach (KeyValuePair referenceCollection in s_ReferenceCollections) + { + referenceCollection.Value.RemoveAll(); + } + + s_ReferenceCollections.Clear(); + } + } + + /// + /// 从引用池获取引用。 + /// + /// 引用类型。 + /// 引用。 + public static T Acquire() where T : class, IReference, new() + { + return GetReferenceCollection(typeof(T)).Acquire(); + } + + /// + /// 从引用池获取引用。 + /// + /// 引用类型。 + /// 引用。 + public static IReference Acquire(Type referenceType) + { + InternalCheckReferenceType(referenceType); + return GetReferenceCollection(referenceType).Acquire(); + } + + /// + /// 将引用归还引用池。 + /// + /// 引用。 + public static void Release(IReference reference) + { + if (reference == null) + { + throw new GameFrameworkException("Reference is invalid."); + } + + Type referenceType = reference.GetType(); + InternalCheckReferenceType(referenceType); + GetReferenceCollection(referenceType).Release(reference); + } + + /// + /// 向引用池中追加指定数量的引用。 + /// + /// 引用类型。 + /// 追加数量。 + public static void Add(int count) where T : class, IReference, new() + { + GetReferenceCollection(typeof(T)).Add(count); + } + + /// + /// 向引用池中追加指定数量的引用。 + /// + /// 引用类型。 + /// 追加数量。 + public static void Add(Type referenceType, int count) + { + InternalCheckReferenceType(referenceType); + GetReferenceCollection(referenceType).Add(count); + } + + /// + /// 从引用池中移除指定数量的引用。 + /// + /// 引用类型。 + /// 移除数量。 + public static void Remove(int count) where T : class, IReference + { + GetReferenceCollection(typeof(T)).Remove(count); + } + + /// + /// 从引用池中移除指定数量的引用。 + /// + /// 引用类型。 + /// 移除数量。 + public static void Remove(Type referenceType, int count) + { + InternalCheckReferenceType(referenceType); + GetReferenceCollection(referenceType).Remove(count); + } + + /// + /// 从引用池中移除所有的引用。 + /// + /// 引用类型。 + public static void RemoveAll() where T : class, IReference + { + GetReferenceCollection(typeof(T)).RemoveAll(); + } + + /// + /// 从引用池中移除所有的引用。 + /// + /// 引用类型。 + public static void RemoveAll(Type referenceType) + { + InternalCheckReferenceType(referenceType); + GetReferenceCollection(referenceType).RemoveAll(); + } + + private static void InternalCheckReferenceType(Type referenceType) + { + if (!m_EnableStrictCheck) + { + return; + } + + if (referenceType == null) + { + throw new GameFrameworkException("Reference type is invalid."); + } + + if (!referenceType.IsClass || referenceType.IsAbstract) + { + throw new GameFrameworkException("Reference type is not a non-abstract class type."); + } + + if (!typeof(IReference).IsAssignableFrom(referenceType)) + { + throw new GameFrameworkException(Utility.Text.Format("Reference type '{0}' is invalid.", referenceType.FullName)); + } + } + + private static ReferenceCollection GetReferenceCollection(Type referenceType) + { + if (referenceType == null) + { + throw new GameFrameworkException("ReferenceType is invalid."); + } + + ReferenceCollection referenceCollection = null; + lock (s_ReferenceCollections) + { + if (!s_ReferenceCollections.TryGetValue(referenceType, out referenceCollection)) + { + referenceCollection = new ReferenceCollection(referenceType); + s_ReferenceCollections.Add(referenceType, referenceCollection); + } + } + + return referenceCollection; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePool.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePool.cs.meta new file mode 100644 index 0000000..f2d1dc6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 55fc0c6295ce30e45b1891bffb35c8e2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePoolInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePoolInfo.cs new file mode 100644 index 0000000..617d082 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePoolInfo.cs @@ -0,0 +1,125 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Runtime.InteropServices; + +namespace GameFramework +{ + /// + /// 引用池信息。 + /// + [StructLayout(LayoutKind.Auto)] + public struct ReferencePoolInfo + { + private readonly Type m_Type; + private readonly int m_UnusedReferenceCount; + private readonly int m_UsingReferenceCount; + private readonly int m_AcquireReferenceCount; + private readonly int m_ReleaseReferenceCount; + private readonly int m_AddReferenceCount; + private readonly int m_RemoveReferenceCount; + + /// + /// 初始化引用池信息的新实例。 + /// + /// 引用池类型。 + /// 未使用引用数量。 + /// 正在使用引用数量。 + /// 获取引用数量。 + /// 归还引用数量。 + /// 增加引用数量。 + /// 移除引用数量。 + public ReferencePoolInfo(Type type, int unusedReferenceCount, int usingReferenceCount, int acquireReferenceCount, int releaseReferenceCount, int addReferenceCount, int removeReferenceCount) + { + m_Type = type; + m_UnusedReferenceCount = unusedReferenceCount; + m_UsingReferenceCount = usingReferenceCount; + m_AcquireReferenceCount = acquireReferenceCount; + m_ReleaseReferenceCount = releaseReferenceCount; + m_AddReferenceCount = addReferenceCount; + m_RemoveReferenceCount = removeReferenceCount; + } + + /// + /// 获取引用池类型。 + /// + public Type Type + { + get + { + return m_Type; + } + } + + /// + /// 获取未使用引用数量。 + /// + public int UnusedReferenceCount + { + get + { + return m_UnusedReferenceCount; + } + } + + /// + /// 获取正在使用引用数量。 + /// + public int UsingReferenceCount + { + get + { + return m_UsingReferenceCount; + } + } + + /// + /// 获取获取引用数量。 + /// + public int AcquireReferenceCount + { + get + { + return m_AcquireReferenceCount; + } + } + + /// + /// 获取归还引用数量。 + /// + public int ReleaseReferenceCount + { + get + { + return m_ReleaseReferenceCount; + } + } + + /// + /// 获取增加引用数量。 + /// + public int AddReferenceCount + { + get + { + return m_AddReferenceCount; + } + } + + /// + /// 获取移除引用数量。 + /// + public int RemoveReferenceCount + { + get + { + return m_RemoveReferenceCount; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePoolInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePoolInfo.cs.meta new file mode 100644 index 0000000..334d1c8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/ReferencePool/ReferencePoolInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dddf007c667be0245b073643926ae93e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool.meta new file mode 100644 index 0000000..0df6c22 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d1db06c7ad3bddf469dc83c8ccf9cbec +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/ITaskAgent.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/ITaskAgent.cs new file mode 100644 index 0000000..3ec4861 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/ITaskAgent.cs @@ -0,0 +1,53 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 任务代理接口。 + /// + /// 任务类型。 + internal interface ITaskAgent where T : TaskBase + { + /// + /// 获取任务。 + /// + T Task + { + get; + } + + /// + /// 初始化任务代理。 + /// + void Initialize(); + + /// + /// 任务代理轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + void Update(float elapseSeconds, float realElapseSeconds); + + /// + /// 关闭并清理任务代理。 + /// + void Shutdown(); + + /// + /// 开始处理任务。 + /// + /// 要处理的任务。 + /// 开始处理任务的状态。 + StartTaskStatus Start(T task); + + /// + /// 停止正在处理的任务并重置任务代理。 + /// + void Reset(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/ITaskAgent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/ITaskAgent.cs.meta new file mode 100644 index 0000000..c51d878 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/ITaskAgent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9511646fe2a40c54cb5326bf5a78b890 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/StartTaskStatus.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/StartTaskStatus.cs new file mode 100644 index 0000000..7aea6d7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/StartTaskStatus.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 开始处理任务的状态。 + /// + public enum StartTaskStatus : byte + { + /// + /// 可以立刻处理完成此任务。 + /// + Done = 0, + + /// + /// 可以继续处理此任务。 + /// + CanResume, + + /// + /// 不能继续处理此任务,需等待其它任务执行完成。 + /// + HasToWait, + + /// + /// 不能继续处理此任务,出现未知错误。 + /// + UnknownError + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/StartTaskStatus.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/StartTaskStatus.cs.meta new file mode 100644 index 0000000..b48e1c1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/StartTaskStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed1099e3ddb8b9444b197fd468a76775 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskBase.cs new file mode 100644 index 0000000..8c1dc39 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskBase.cs @@ -0,0 +1,137 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 任务基类。 + /// + internal abstract class TaskBase : IReference + { + /// + /// 任务默认优先级。 + /// + public const int DefaultPriority = 0; + + private int m_SerialId; + private string m_Tag; + private int m_Priority; + private object m_UserData; + + private bool m_Done; + + /// + /// 初始化任务基类的新实例。 + /// + public TaskBase() + { + m_SerialId = 0; + m_Tag = null; + m_Priority = DefaultPriority; + m_Done = false; + m_UserData = null; + } + + /// + /// 获取任务的序列编号。 + /// + public int SerialId + { + get + { + return m_SerialId; + } + } + + /// + /// 获取任务的标签。 + /// + public string Tag + { + get + { + return m_Tag; + } + } + + /// + /// 获取任务的优先级。 + /// + public int Priority + { + get + { + return m_Priority; + } + } + + /// + /// 获取任务的用户自定义数据。 + /// + public object UserData + { + get + { + return m_UserData; + } + } + + /// + /// 获取或设置任务是否完成。 + /// + public bool Done + { + get + { + return m_Done; + } + set + { + m_Done = value; + } + } + + /// + /// 获取任务描述。 + /// + public virtual string Description + { + get + { + return null; + } + } + + /// + /// 初始化任务基类。 + /// + /// 任务的序列编号。 + /// 任务的标签。 + /// 任务的优先级。 + /// 任务的用户自定义数据。 + internal void Initialize(int serialId, string tag, int priority, object userData) + { + m_SerialId = serialId; + m_Tag = tag; + m_Priority = priority; + m_UserData = userData; + m_Done = false; + } + + /// + /// 清理任务基类。 + /// + public virtual void Clear() + { + m_SerialId = 0; + m_Tag = null; + m_Priority = DefaultPriority; + m_UserData = null; + m_Done = false; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskBase.cs.meta new file mode 100644 index 0000000..8227afc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 65611e2ce2f03544987efbf19294126f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskInfo.cs new file mode 100644 index 0000000..e18f8f2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskInfo.cs @@ -0,0 +1,153 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework +{ + /// + /// 任务信息。 + /// + [StructLayout(LayoutKind.Auto)] + public struct TaskInfo + { + private readonly bool m_IsValid; + private readonly int m_SerialId; + private readonly string m_Tag; + private readonly int m_Priority; + private readonly object m_UserData; + private readonly TaskStatus m_Status; + private readonly string m_Description; + + /// + /// 初始化任务信息的新实例。 + /// + /// 任务的序列编号。 + /// 任务的标签。 + /// 任务的优先级。 + /// 任务的用户自定义数据。 + /// 任务状态。 + /// 任务描述。 + public TaskInfo(int serialId, string tag, int priority, object userData, TaskStatus status, string description) + { + m_IsValid = true; + m_SerialId = serialId; + m_Tag = tag; + m_Priority = priority; + m_UserData = userData; + m_Status = status; + m_Description = description; + } + + /// + /// 获取任务信息是否有效。 + /// + public bool IsValid + { + get + { + return m_IsValid; + } + } + + /// + /// 获取任务的序列编号。 + /// + public int SerialId + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_SerialId; + } + } + + /// + /// 获取任务的标签。 + /// + public string Tag + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_Tag; + } + } + + /// + /// 获取任务的优先级。 + /// + public int Priority + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_Priority; + } + } + + /// + /// 获取任务的用户自定义数据。 + /// + public object UserData + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_UserData; + } + } + + /// + /// 获取任务状态。 + /// + public TaskStatus Status + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_Status; + } + } + + /// + /// 获取任务描述。 + /// + public string Description + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_Description; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskInfo.cs.meta new file mode 100644 index 0000000..3f4b703 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5fb34e2035663fc4f8ed986718e668a4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskPool.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskPool.cs new file mode 100644 index 0000000..eb60264 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskPool.cs @@ -0,0 +1,444 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework +{ + /// + /// 任务池。 + /// + /// 任务类型。 + internal sealed class TaskPool where T : TaskBase + { + private readonly Stack> m_FreeAgents; + private readonly GameFrameworkLinkedList> m_WorkingAgents; + private readonly GameFrameworkLinkedList m_WaitingTasks; + private bool m_Paused; + + /// + /// 初始化任务池的新实例。 + /// + public TaskPool() + { + m_FreeAgents = new Stack>(); + m_WorkingAgents = new GameFrameworkLinkedList>(); + m_WaitingTasks = new GameFrameworkLinkedList(); + m_Paused = false; + } + + /// + /// 获取或设置任务池是否被暂停。 + /// + public bool Paused + { + get + { + return m_Paused; + } + set + { + m_Paused = value; + } + } + + /// + /// 获取任务代理总数量。 + /// + public int TotalAgentCount + { + get + { + return FreeAgentCount + WorkingAgentCount; + } + } + + /// + /// 获取可用任务代理数量。 + /// + public int FreeAgentCount + { + get + { + return m_FreeAgents.Count; + } + } + + /// + /// 获取工作中任务代理数量。 + /// + public int WorkingAgentCount + { + get + { + return m_WorkingAgents.Count; + } + } + + /// + /// 获取等待任务数量。 + /// + public int WaitingTaskCount + { + get + { + return m_WaitingTasks.Count; + } + } + + /// + /// 任务池轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void Update(float elapseSeconds, float realElapseSeconds) + { + if (m_Paused) + { + return; + } + + ProcessRunningTasks(elapseSeconds, realElapseSeconds); + ProcessWaitingTasks(elapseSeconds, realElapseSeconds); + } + + /// + /// 关闭并清理任务池。 + /// + public void Shutdown() + { + RemoveAllTasks(); + + while (FreeAgentCount > 0) + { + m_FreeAgents.Pop().Shutdown(); + } + } + + /// + /// 增加任务代理。 + /// + /// 要增加的任务代理。 + public void AddAgent(ITaskAgent agent) + { + if (agent == null) + { + throw new GameFrameworkException("Task agent is invalid."); + } + + agent.Initialize(); + m_FreeAgents.Push(agent); + } + + /// + /// 根据任务的序列编号获取任务的信息。 + /// + /// 要获取信息的任务的序列编号。 + /// 任务的信息。 + public TaskInfo GetTaskInfo(int serialId) + { + foreach (ITaskAgent workingAgent in m_WorkingAgents) + { + T workingTask = workingAgent.Task; + if (workingTask.SerialId == serialId) + { + return new TaskInfo(workingTask.SerialId, workingTask.Tag, workingTask.Priority, workingTask.UserData, workingTask.Done ? TaskStatus.Done : TaskStatus.Doing, workingTask.Description); + } + } + + foreach (T waitingTask in m_WaitingTasks) + { + if (waitingTask.SerialId == serialId) + { + return new TaskInfo(waitingTask.SerialId, waitingTask.Tag, waitingTask.Priority, waitingTask.UserData, TaskStatus.Todo, waitingTask.Description); + } + } + + return default(TaskInfo); + } + + /// + /// 根据任务的标签获取任务的信息。 + /// + /// 要获取信息的任务的标签。 + /// 任务的信息。 + public TaskInfo[] GetTaskInfos(string tag) + { + List results = new List(); + GetTaskInfos(tag, results); + return results.ToArray(); + } + + /// + /// 根据任务的标签获取任务的信息。 + /// + /// 要获取信息的任务的标签。 + /// 任务的信息。 + public void GetTaskInfos(string tag, List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (ITaskAgent workingAgent in m_WorkingAgents) + { + T workingTask = workingAgent.Task; + if (workingTask.Tag == tag) + { + results.Add(new TaskInfo(workingTask.SerialId, workingTask.Tag, workingTask.Priority, workingTask.UserData, workingTask.Done ? TaskStatus.Done : TaskStatus.Doing, workingTask.Description)); + } + } + + foreach (T waitingTask in m_WaitingTasks) + { + if (waitingTask.Tag == tag) + { + results.Add(new TaskInfo(waitingTask.SerialId, waitingTask.Tag, waitingTask.Priority, waitingTask.UserData, TaskStatus.Todo, waitingTask.Description)); + } + } + } + + /// + /// 获取所有任务的信息。 + /// + /// 所有任务的信息。 + public TaskInfo[] GetAllTaskInfos() + { + int index = 0; + TaskInfo[] results = new TaskInfo[m_WorkingAgents.Count + m_WaitingTasks.Count]; + foreach (ITaskAgent workingAgent in m_WorkingAgents) + { + T workingTask = workingAgent.Task; + results[index++] = new TaskInfo(workingTask.SerialId, workingTask.Tag, workingTask.Priority, workingTask.UserData, workingTask.Done ? TaskStatus.Done : TaskStatus.Doing, workingTask.Description); + } + + foreach (T waitingTask in m_WaitingTasks) + { + results[index++] = new TaskInfo(waitingTask.SerialId, waitingTask.Tag, waitingTask.Priority, waitingTask.UserData, TaskStatus.Todo, waitingTask.Description); + } + + return results; + } + + /// + /// 获取所有任务的信息。 + /// + /// 所有任务的信息。 + public void GetAllTaskInfos(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (ITaskAgent workingAgent in m_WorkingAgents) + { + T workingTask = workingAgent.Task; + results.Add(new TaskInfo(workingTask.SerialId, workingTask.Tag, workingTask.Priority, workingTask.UserData, workingTask.Done ? TaskStatus.Done : TaskStatus.Doing, workingTask.Description)); + } + + foreach (T waitingTask in m_WaitingTasks) + { + results.Add(new TaskInfo(waitingTask.SerialId, waitingTask.Tag, waitingTask.Priority, waitingTask.UserData, TaskStatus.Todo, waitingTask.Description)); + } + } + + /// + /// 增加任务。 + /// + /// 要增加的任务。 + public void AddTask(T task) + { + LinkedListNode current = m_WaitingTasks.Last; + while (current != null) + { + if (task.Priority <= current.Value.Priority) + { + break; + } + + current = current.Previous; + } + + if (current != null) + { + m_WaitingTasks.AddAfter(current, task); + } + else + { + m_WaitingTasks.AddFirst(task); + } + } + + /// + /// 根据任务的序列编号移除任务。 + /// + /// 要移除任务的序列编号。 + /// 是否移除任务成功。 + public bool RemoveTask(int serialId) + { + foreach (T task in m_WaitingTasks) + { + if (task.SerialId == serialId) + { + m_WaitingTasks.Remove(task); + ReferencePool.Release(task); + return true; + } + } + + LinkedListNode> currentWorkingAgent = m_WorkingAgents.First; + while (currentWorkingAgent != null) + { + LinkedListNode> next = currentWorkingAgent.Next; + ITaskAgent workingAgent = currentWorkingAgent.Value; + T task = workingAgent.Task; + if (task.SerialId == serialId) + { + workingAgent.Reset(); + m_FreeAgents.Push(workingAgent); + m_WorkingAgents.Remove(currentWorkingAgent); + ReferencePool.Release(task); + return true; + } + + currentWorkingAgent = next; + } + + return false; + } + + /// + /// 根据任务的标签移除任务。 + /// + /// 要移除任务的标签。 + /// 移除任务的数量。 + public int RemoveTasks(string tag) + { + int count = 0; + + LinkedListNode currentWaitingTask = m_WaitingTasks.First; + while (currentWaitingTask != null) + { + LinkedListNode next = currentWaitingTask.Next; + T task = currentWaitingTask.Value; + if (task.Tag == tag) + { + m_WaitingTasks.Remove(currentWaitingTask); + ReferencePool.Release(task); + count++; + } + + currentWaitingTask = next; + } + + LinkedListNode> currentWorkingAgent = m_WorkingAgents.First; + while (currentWorkingAgent != null) + { + LinkedListNode> next = currentWorkingAgent.Next; + ITaskAgent workingAgent = currentWorkingAgent.Value; + T task = workingAgent.Task; + if (task.Tag == tag) + { + workingAgent.Reset(); + m_FreeAgents.Push(workingAgent); + m_WorkingAgents.Remove(currentWorkingAgent); + ReferencePool.Release(task); + count++; + } + + currentWorkingAgent = next; + } + + return count; + } + + /// + /// 移除所有任务。 + /// + /// 移除任务的数量。 + public int RemoveAllTasks() + { + int count = m_WaitingTasks.Count + m_WorkingAgents.Count; + + foreach (T task in m_WaitingTasks) + { + ReferencePool.Release(task); + } + + m_WaitingTasks.Clear(); + + foreach (ITaskAgent workingAgent in m_WorkingAgents) + { + T task = workingAgent.Task; + workingAgent.Reset(); + m_FreeAgents.Push(workingAgent); + ReferencePool.Release(task); + } + + m_WorkingAgents.Clear(); + + return count; + } + + private void ProcessRunningTasks(float elapseSeconds, float realElapseSeconds) + { + LinkedListNode> current = m_WorkingAgents.First; + while (current != null) + { + T task = current.Value.Task; + if (!task.Done) + { + current.Value.Update(elapseSeconds, realElapseSeconds); + current = current.Next; + continue; + } + + LinkedListNode> next = current.Next; + current.Value.Reset(); + m_FreeAgents.Push(current.Value); + m_WorkingAgents.Remove(current); + ReferencePool.Release(task); + current = next; + } + } + + private void ProcessWaitingTasks(float elapseSeconds, float realElapseSeconds) + { + LinkedListNode current = m_WaitingTasks.First; + while (current != null && FreeAgentCount > 0) + { + ITaskAgent agent = m_FreeAgents.Pop(); + LinkedListNode> agentNode = m_WorkingAgents.AddLast(agent); + T task = current.Value; + LinkedListNode next = current.Next; + StartTaskStatus status = agent.Start(task); + if (status == StartTaskStatus.Done || status == StartTaskStatus.HasToWait || status == StartTaskStatus.UnknownError) + { + agent.Reset(); + m_FreeAgents.Push(agent); + m_WorkingAgents.Remove(agentNode); + } + + if (status == StartTaskStatus.Done || status == StartTaskStatus.CanResume || status == StartTaskStatus.UnknownError) + { + m_WaitingTasks.Remove(current); + } + + if (status == StartTaskStatus.Done || status == StartTaskStatus.UnknownError) + { + ReferencePool.Release(task); + } + + current = next; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskPool.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskPool.cs.meta new file mode 100644 index 0000000..d365e07 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3863d99a1a6c9294bb45e43e97f09b69 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskStatus.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskStatus.cs new file mode 100644 index 0000000..e0060ab --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskStatus.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 任务状态。 + /// + public enum TaskStatus : byte + { + /// + /// 未开始。 + /// + Todo = 0, + + /// + /// 执行中。 + /// + Doing, + + /// + /// 完成。 + /// + Done + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskStatus.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskStatus.cs.meta new file mode 100644 index 0000000..3009876 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/TaskPool/TaskStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 368abbe42754cbd4e8ed2477da58e68c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable.meta new file mode 100644 index 0000000..929addb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b81306bd038bc2f4aa733baec68769ba +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable/GenericVariable.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable/GenericVariable.cs new file mode 100644 index 0000000..972cca2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable/GenericVariable.cs @@ -0,0 +1,89 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework +{ + /// + /// 变量。 + /// + /// 变量类型。 + public abstract class Variable : Variable + { + private T m_Value; + + /// + /// 初始化变量的新实例。 + /// + public Variable() + { + m_Value = default(T); + } + + /// + /// 获取变量类型。 + /// + public override Type Type + { + get + { + return typeof(T); + } + } + + /// + /// 获取或设置变量值。 + /// + public T Value + { + get + { + return m_Value; + } + set + { + m_Value = value; + } + } + + /// + /// 获取变量值。 + /// + /// 变量值。 + public override object GetValue() + { + return m_Value; + } + + /// + /// 设置变量值。 + /// + /// 变量值。 + public override void SetValue(object value) + { + m_Value = (T)value; + } + + /// + /// 清理变量值。 + /// + public override void Clear() + { + m_Value = default(T); + } + + /// + /// 获取变量字符串。 + /// + /// 变量字符串。 + public override string ToString() + { + return (m_Value != null) ? m_Value.ToString() : ""; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable/GenericVariable.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable/GenericVariable.cs.meta new file mode 100644 index 0000000..ce37e5c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable/GenericVariable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 274598fb9631cf64fa995078cb26e347 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable/Variable.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable/Variable.cs new file mode 100644 index 0000000..bd965c1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable/Variable.cs @@ -0,0 +1,49 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework +{ + /// + /// 变量。 + /// + public abstract class Variable : IReference + { + /// + /// 初始化变量的新实例。 + /// + public Variable() + { + } + + /// + /// 获取变量类型。 + /// + public abstract Type Type + { + get; + } + + /// + /// 获取变量值。 + /// + /// 变量值。 + public abstract object GetValue(); + + /// + /// 设置变量值。 + /// + /// 变量值。 + public abstract void SetValue(object value); + + /// + /// 清理变量值。 + /// + public abstract void Clear(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable/Variable.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable/Variable.cs.meta new file mode 100644 index 0000000..775ae49 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Variable/Variable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af66e8a42a11cd443b187bffea928329 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version.meta new file mode 100644 index 0000000..04e11a0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b0e6946bfd4818841bc9f458fbcdbd23 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version/Version.IVersionHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version/Version.IVersionHelper.cs new file mode 100644 index 0000000..d3fce09 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version/Version.IVersionHelper.cs @@ -0,0 +1,34 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + public static partial class Version + { + /// + /// 版本号辅助器接口。 + /// + public interface IVersionHelper + { + /// + /// 获取游戏版本号。 + /// + string GameVersion + { + get; + } + + /// + /// 获取内部游戏版本号。 + /// + int InternalGameVersion + { + get; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version/Version.IVersionHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version/Version.IVersionHelper.cs.meta new file mode 100644 index 0000000..ec49e6a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version/Version.IVersionHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: efcb7baff6aba59458c45b4308f69990 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version/Version.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version/Version.cs new file mode 100644 index 0000000..1bef04e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version/Version.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 版本号类。 + /// + public static partial class Version + { + private const string GameFrameworkVersionString = "2021.05.31"; + + private static IVersionHelper s_VersionHelper = null; + + /// + /// 获取游戏框架版本号。 + /// + public static string GameFrameworkVersion + { + get + { + return GameFrameworkVersionString; + } + } + + /// + /// 获取游戏版本号。 + /// + public static string GameVersion + { + get + { + if (s_VersionHelper == null) + { + return string.Empty; + } + + return s_VersionHelper.GameVersion; + } + } + + /// + /// 获取内部游戏版本号。 + /// + public static int InternalGameVersion + { + get + { + if (s_VersionHelper == null) + { + return 0; + } + + return s_VersionHelper.InternalGameVersion; + } + } + + /// + /// 设置版本号辅助器。 + /// + /// 要设置的版本号辅助器。 + public static void SetVersionHelper(IVersionHelper versionHelper) + { + s_VersionHelper = versionHelper; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version/Version.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version/Version.cs.meta new file mode 100644 index 0000000..69b8f5d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Base/Version/Version.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 591cfaa6702a77945ae7f94b24e67ce9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config.meta new file mode 100644 index 0000000..70fe670 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dd5efb32a44789b44adc617fe5100f37 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/ConfigManager.ConfigData.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/ConfigManager.ConfigData.cs new file mode 100644 index 0000000..1295029 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/ConfigManager.ConfigData.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Config +{ + internal sealed partial class ConfigManager : GameFrameworkModule, IConfigManager + { + [StructLayout(LayoutKind.Auto)] + private struct ConfigData + { + private readonly bool m_BoolValue; + private readonly int m_IntValue; + private readonly float m_FloatValue; + private readonly string m_StringValue; + + public ConfigData(bool boolValue, int intValue, float floatValue, string stringValue) + { + m_BoolValue = boolValue; + m_IntValue = intValue; + m_FloatValue = floatValue; + m_StringValue = stringValue; + } + + public bool BoolValue + { + get + { + return m_BoolValue; + } + } + + public int IntValue + { + get + { + return m_IntValue; + } + } + + public float FloatValue + { + get + { + return m_FloatValue; + } + } + + public string StringValue + { + get + { + return m_StringValue; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/ConfigManager.ConfigData.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/ConfigManager.ConfigData.cs.meta new file mode 100644 index 0000000..3d4a811 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/ConfigManager.ConfigData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c5168df0c645d7241b24fb73fc64ff05 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/ConfigManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/ConfigManager.cs new file mode 100644 index 0000000..7b47e18 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/ConfigManager.cs @@ -0,0 +1,487 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System; +using System.Collections.Generic; + +namespace GameFramework.Config +{ + /// + /// 全局配置管理器。 + /// + internal sealed partial class ConfigManager : GameFrameworkModule, IConfigManager + { + private readonly Dictionary m_ConfigDatas; + private readonly DataProvider m_DataProvider; + private IConfigHelper m_ConfigHelper; + + /// + /// 初始化全局配置管理器的新实例。 + /// + public ConfigManager() + { + m_ConfigDatas = new Dictionary(StringComparer.Ordinal); + m_DataProvider = new DataProvider(this); + m_ConfigHelper = null; + } + + /// + /// 获取全局配置项数量。 + /// + public int Count + { + get + { + return m_ConfigDatas.Count; + } + } + + /// + /// 获取缓冲二进制流的大小。 + /// + public int CachedBytesSize + { + get + { + return DataProvider.CachedBytesSize; + } + } + + /// + /// 读取全局配置成功事件。 + /// + public event EventHandler ReadDataSuccess + { + add + { + m_DataProvider.ReadDataSuccess += value; + } + remove + { + m_DataProvider.ReadDataSuccess -= value; + } + } + + /// + /// 读取全局配置失败事件。 + /// + public event EventHandler ReadDataFailure + { + add + { + m_DataProvider.ReadDataFailure += value; + } + remove + { + m_DataProvider.ReadDataFailure -= value; + } + } + + /// + /// 读取全局配置更新事件。 + /// + public event EventHandler ReadDataUpdate + { + add + { + m_DataProvider.ReadDataUpdate += value; + } + remove + { + m_DataProvider.ReadDataUpdate -= value; + } + } + + /// + /// 读取全局配置时加载依赖资源事件。 + /// + public event EventHandler ReadDataDependencyAsset + { + add + { + m_DataProvider.ReadDataDependencyAsset += value; + } + remove + { + m_DataProvider.ReadDataDependencyAsset -= value; + } + } + + /// + /// 全局配置管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 关闭并清理全局配置管理器。 + /// + internal override void Shutdown() + { + } + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + public void SetResourceManager(IResourceManager resourceManager) + { + m_DataProvider.SetResourceManager(resourceManager); + } + + /// + /// 设置全局配置数据提供者辅助器。 + /// + /// 全局配置数据提供者辅助器。 + public void SetDataProviderHelper(IDataProviderHelper dataProviderHelper) + { + m_DataProvider.SetDataProviderHelper(dataProviderHelper); + } + + /// + /// 设置全局配置辅助器。 + /// + /// 全局配置辅助器。 + public void SetConfigHelper(IConfigHelper configHelper) + { + if (configHelper == null) + { + throw new GameFrameworkException("Config helper is invalid."); + } + + m_ConfigHelper = configHelper; + } + + /// + /// 确保二进制流缓存分配足够大小的内存并缓存。 + /// + /// 要确保二进制流缓存分配内存的大小。 + public void EnsureCachedBytesSize(int ensureSize) + { + DataProvider.EnsureCachedBytesSize(ensureSize); + } + + /// + /// 释放缓存的二进制流。 + /// + public void FreeCachedBytes() + { + DataProvider.FreeCachedBytes(); + } + + /// + /// 读取全局配置。 + /// + /// 全局配置资源名称。 + public void ReadData(string configAssetName) + { + m_DataProvider.ReadData(configAssetName); + } + + /// + /// 读取全局配置。 + /// + /// 全局配置资源名称。 + /// 加载全局配置资源的优先级。 + public void ReadData(string configAssetName, int priority) + { + m_DataProvider.ReadData(configAssetName, priority); + } + + /// + /// 读取全局配置。 + /// + /// 全局配置资源名称。 + /// 用户自定义数据。 + public void ReadData(string configAssetName, object userData) + { + m_DataProvider.ReadData(configAssetName, userData); + } + + /// + /// 读取全局配置。 + /// + /// 全局配置资源名称。 + /// 加载全局配置资源的优先级。 + /// 用户自定义数据。 + public void ReadData(string configAssetName, int priority, object userData) + { + m_DataProvider.ReadData(configAssetName, priority, userData); + } + + /// + /// 解析全局配置。 + /// + /// 要解析的全局配置字符串。 + /// 是否解析全局配置成功。 + public bool ParseData(string configString) + { + return m_DataProvider.ParseData(configString); + } + + /// + /// 解析全局配置。 + /// + /// 要解析的全局配置字符串。 + /// 用户自定义数据。 + /// 是否解析全局配置成功。 + public bool ParseData(string configString, object userData) + { + return m_DataProvider.ParseData(configString, userData); + } + + /// + /// 解析全局配置。 + /// + /// 要解析的全局配置二进制流。 + /// 是否解析全局配置成功。 + public bool ParseData(byte[] configBytes) + { + return m_DataProvider.ParseData(configBytes); + } + + /// + /// 解析全局配置。 + /// + /// 要解析的全局配置二进制流。 + /// 用户自定义数据。 + /// 是否解析全局配置成功。 + public bool ParseData(byte[] configBytes, object userData) + { + return m_DataProvider.ParseData(configBytes, userData); + } + + /// + /// 解析全局配置。 + /// + /// 要解析的全局配置二进制流。 + /// 全局配置二进制流的起始位置。 + /// 全局配置二进制流的长度。 + /// 是否解析全局配置成功。 + public bool ParseData(byte[] configBytes, int startIndex, int length) + { + return m_DataProvider.ParseData(configBytes, startIndex, length); + } + + /// + /// 解析全局配置。 + /// + /// 要解析的全局配置二进制流。 + /// 全局配置二进制流的起始位置。 + /// 全局配置二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析全局配置成功。 + public bool ParseData(byte[] configBytes, int startIndex, int length, object userData) + { + return m_DataProvider.ParseData(configBytes, startIndex, length, userData); + } + + /// + /// 检查是否存在指定全局配置项。 + /// + /// 要检查全局配置项的名称。 + /// 指定的全局配置项是否存在。 + public bool HasConfig(string configName) + { + return GetConfigData(configName).HasValue; + } + + /// + /// 从指定全局配置项中读取布尔值。 + /// + /// 要获取全局配置项的名称。 + /// 读取的布尔值。 + public bool GetBool(string configName) + { + ConfigData? configData = GetConfigData(configName); + if (!configData.HasValue) + { + throw new GameFrameworkException(Utility.Text.Format("Config name '{0}' is not exist.", configName)); + } + + return configData.Value.BoolValue; + } + + /// + /// 从指定全局配置项中读取布尔值。 + /// + /// 要获取全局配置项的名称。 + /// 当指定的全局配置项不存在时,返回此默认值。 + /// 读取的布尔值。 + public bool GetBool(string configName, bool defaultValue) + { + ConfigData? configData = GetConfigData(configName); + return configData.HasValue ? configData.Value.BoolValue : defaultValue; + } + + /// + /// 从指定全局配置项中读取整数值。 + /// + /// 要获取全局配置项的名称。 + /// 读取的整数值。 + public int GetInt(string configName) + { + ConfigData? configData = GetConfigData(configName); + if (!configData.HasValue) + { + throw new GameFrameworkException(Utility.Text.Format("Config name '{0}' is not exist.", configName)); + } + + return configData.Value.IntValue; + } + + /// + /// 从指定全局配置项中读取整数值。 + /// + /// 要获取全局配置项的名称。 + /// 当指定的全局配置项不存在时,返回此默认值。 + /// 读取的整数值。 + public int GetInt(string configName, int defaultValue) + { + ConfigData? configData = GetConfigData(configName); + return configData.HasValue ? configData.Value.IntValue : defaultValue; + } + + /// + /// 从指定全局配置项中读取浮点数值。 + /// + /// 要获取全局配置项的名称。 + /// 读取的浮点数值。 + public float GetFloat(string configName) + { + ConfigData? configData = GetConfigData(configName); + if (!configData.HasValue) + { + throw new GameFrameworkException(Utility.Text.Format("Config name '{0}' is not exist.", configName)); + } + + return configData.Value.FloatValue; + } + + /// + /// 从指定全局配置项中读取浮点数值。 + /// + /// 要获取全局配置项的名称。 + /// 当指定的全局配置项不存在时,返回此默认值。 + /// 读取的浮点数值。 + public float GetFloat(string configName, float defaultValue) + { + ConfigData? configData = GetConfigData(configName); + return configData.HasValue ? configData.Value.FloatValue : defaultValue; + } + + /// + /// 从指定全局配置项中读取字符串值。 + /// + /// 要获取全局配置项的名称。 + /// 读取的字符串值。 + public string GetString(string configName) + { + ConfigData? configData = GetConfigData(configName); + if (!configData.HasValue) + { + throw new GameFrameworkException(Utility.Text.Format("Config name '{0}' is not exist.", configName)); + } + + return configData.Value.StringValue; + } + + /// + /// 从指定全局配置项中读取字符串值。 + /// + /// 要获取全局配置项的名称。 + /// 当指定的全局配置项不存在时,返回此默认值。 + /// 读取的字符串值。 + public string GetString(string configName, string defaultValue) + { + ConfigData? configData = GetConfigData(configName); + return configData.HasValue ? configData.Value.StringValue : defaultValue; + } + + /// + /// 增加指定全局配置项。 + /// + /// 要增加全局配置项的名称。 + /// 全局配置项的值。 + /// 是否增加全局配置项成功。 + public bool AddConfig(string configName, string configValue) + { + bool boolValue = false; + bool.TryParse(configValue, out boolValue); + + int intValue = 0; + int.TryParse(configValue, out intValue); + + float floatValue = 0f; + float.TryParse(configValue, out floatValue); + + return AddConfig(configName, boolValue, intValue, floatValue, configValue); + } + + /// + /// 增加指定全局配置项。 + /// + /// 要增加全局配置项的名称。 + /// 全局配置项布尔值。 + /// 全局配置项整数值。 + /// 全局配置项浮点数值。 + /// 全局配置项字符串值。 + /// 是否增加全局配置项成功。 + public bool AddConfig(string configName, bool boolValue, int intValue, float floatValue, string stringValue) + { + if (HasConfig(configName)) + { + return false; + } + + m_ConfigDatas.Add(configName, new ConfigData(boolValue, intValue, floatValue, stringValue)); + return true; + } + + /// + /// 移除指定全局配置项。 + /// + /// 要移除全局配置项的名称。 + public bool RemoveConfig(string configName) + { + if (!HasConfig(configName)) + { + return false; + } + + return m_ConfigDatas.Remove(configName); + } + + /// + /// 清空所有全局配置项。 + /// + public void RemoveAllConfigs() + { + m_ConfigDatas.Clear(); + } + + private ConfigData? GetConfigData(string configName) + { + if (string.IsNullOrEmpty(configName)) + { + throw new GameFrameworkException("Config name is invalid."); + } + + ConfigData configData = default(ConfigData); + if (m_ConfigDatas.TryGetValue(configName, out configData)) + { + return configData; + } + + return null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/ConfigManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/ConfigManager.cs.meta new file mode 100644 index 0000000..2e14461 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/ConfigManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f75526da79ea61447bffc03fad48ae51 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/IConfigHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/IConfigHelper.cs new file mode 100644 index 0000000..d650eea --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/IConfigHelper.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Config +{ + /// + /// 全局配置辅助器接口。 + /// + public interface IConfigHelper + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/IConfigHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/IConfigHelper.cs.meta new file mode 100644 index 0000000..ba27fa8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/IConfigHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: de11ec1c5ca73064d933b66e5671e8fe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/IConfigManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/IConfigManager.cs new file mode 100644 index 0000000..b49f541 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/IConfigManager.cs @@ -0,0 +1,160 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; + +namespace GameFramework.Config +{ + /// + /// 全局配置管理器接口。 + /// + public interface IConfigManager : IDataProvider + { + /// + /// 获取全局配置项数量。 + /// + int Count + { + get; + } + + /// + /// 获取缓冲二进制流的大小。 + /// + int CachedBytesSize + { + get; + } + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + void SetResourceManager(IResourceManager resourceManager); + + /// + /// 设置全局配置数据提供者辅助器。 + /// + /// 全局配置数据提供者辅助器。 + void SetDataProviderHelper(IDataProviderHelper dataProviderHelper); + + /// + /// 设置全局配置辅助器。 + /// + /// 全局配置辅助器。 + void SetConfigHelper(IConfigHelper configHelper); + + /// + /// 确保二进制流缓存分配足够大小的内存并缓存。 + /// + /// 要确保二进制流缓存分配内存的大小。 + void EnsureCachedBytesSize(int ensureSize); + + /// + /// 释放缓存的二进制流。 + /// + void FreeCachedBytes(); + + /// + /// 检查是否存在指定全局配置项。 + /// + /// 要检查全局配置项的名称。 + /// 指定的全局配置项是否存在。 + bool HasConfig(string configName); + + /// + /// 从指定全局配置项中读取布尔值。 + /// + /// 要获取全局配置项的名称。 + /// 读取的布尔值。 + bool GetBool(string configName); + + /// + /// 从指定全局配置项中读取布尔值。 + /// + /// 要获取全局配置项的名称。 + /// 当指定的全局配置项不存在时,返回此默认值。 + /// 读取的布尔值。 + bool GetBool(string configName, bool defaultValue); + + /// + /// 从指定全局配置项中读取整数值。 + /// + /// 要获取全局配置项的名称。 + /// 读取的整数值。 + int GetInt(string configName); + + /// + /// 从指定全局配置项中读取整数值。 + /// + /// 要获取全局配置项的名称。 + /// 当指定的全局配置项不存在时,返回此默认值。 + /// 读取的整数值。 + int GetInt(string configName, int defaultValue); + + /// + /// 从指定全局配置项中读取浮点数值。 + /// + /// 要获取全局配置项的名称。 + /// 读取的浮点数值。 + float GetFloat(string configName); + + /// + /// 从指定全局配置项中读取浮点数值。 + /// + /// 要获取全局配置项的名称。 + /// 当指定的全局配置项不存在时,返回此默认值。 + /// 读取的浮点数值。 + float GetFloat(string configName, float defaultValue); + + /// + /// 从指定全局配置项中读取字符串值。 + /// + /// 要获取全局配置项的名称。 + /// 读取的字符串值。 + string GetString(string configName); + + /// + /// 从指定全局配置项中读取字符串值。 + /// + /// 要获取全局配置项的名称。 + /// 当指定的全局配置项不存在时,返回此默认值。 + /// 读取的字符串值。 + string GetString(string configName, string defaultValue); + + /// + /// 增加指定全局配置项。 + /// + /// 要增加全局配置项的名称。 + /// 全局配置项的值。 + /// 是否增加全局配置项成功。 + bool AddConfig(string configName, string configValue); + + /// + /// 增加指定全局配置项。 + /// + /// 要增加全局配置项的名称。 + /// 全局配置项布尔值。 + /// 全局配置项整数值。 + /// 全局配置项浮点数值。 + /// 全局配置项字符串值。 + /// 是否增加全局配置项成功。 + bool AddConfig(string configName, bool boolValue, int intValue, float floatValue, string stringValue); + + /// + /// 移除指定全局配置项。 + /// + /// 要移除全局配置项的名称。 + /// 是否移除全局配置项成功。 + bool RemoveConfig(string configName); + + /// + /// 清空所有全局配置项。 + /// + void RemoveAllConfigs(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/IConfigManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/IConfigManager.cs.meta new file mode 100644 index 0000000..b849ca6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Config/IConfigManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1fdaf5e8ae7a3454ca4e25fe83094ee3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode.meta new file mode 100644 index 0000000..dfb6e95 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bc12fec61d28efd4db83843fe51f1720 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/DataNodeManager.DataNode.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/DataNodeManager.DataNode.cs new file mode 100644 index 0000000..57f36d7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/DataNodeManager.DataNode.cs @@ -0,0 +1,383 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.DataNode +{ + internal sealed partial class DataNodeManager : GameFrameworkModule, IDataNodeManager + { + /// + /// 数据结点。 + /// + private sealed class DataNode : IDataNode, IReference + { + private static readonly DataNode[] EmptyDataNodeArray = new DataNode[] { }; + + private string m_Name; + private Variable m_Data; + private DataNode m_Parent; + private List m_Childs; + + public DataNode() + { + m_Name = null; + m_Data = null; + m_Parent = null; + m_Childs = null; + } + + /// + /// 创建数据结点。 + /// + /// 数据结点名称。 + /// 父数据结点。 + /// 创建的数据结点。 + public static DataNode Create(string name, DataNode parent) + { + if (!IsValidName(name)) + { + throw new GameFrameworkException("Name of data node is invalid."); + } + + DataNode node = ReferencePool.Acquire(); + node.m_Name = name; + node.m_Parent = parent; + return node; + } + + /// + /// 获取数据结点的名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取数据结点的完整名称。 + /// + public string FullName + { + get + { + return m_Parent == null ? m_Name : Utility.Text.Format("{0}{1}{2}", m_Parent.FullName, PathSplitSeparator[0], m_Name); + } + } + + /// + /// 获取父数据结点。 + /// + public IDataNode Parent + { + get + { + return m_Parent; + } + } + + /// + /// 获取子数据结点的数量。 + /// + public int ChildCount + { + get + { + return m_Childs != null ? m_Childs.Count : 0; + } + } + + /// + /// 根据类型获取数据结点的数据。 + /// + /// 要获取的数据类型。 + /// 指定类型的数据。 + public T GetData() where T : Variable + { + return (T)m_Data; + } + + /// + /// 获取数据结点的数据。 + /// + /// 数据结点数据。 + public Variable GetData() + { + return m_Data; + } + + /// + /// 设置数据结点的数据。 + /// + /// 要设置的数据类型。 + /// 要设置的数据。 + public void SetData(T data) where T : Variable + { + SetData((Variable)data); + } + + /// + /// 设置数据结点的数据。 + /// + /// 要设置的数据。 + public void SetData(Variable data) + { + if (m_Data != null) + { + ReferencePool.Release(m_Data); + } + + m_Data = data; + } + + /// + /// 根据索引检查是否存在子数据结点。 + /// + /// 子数据结点的索引。 + /// 是否存在子数据结点。 + public bool HasChild(int index) + { + return index >= 0 && index < ChildCount; + } + + /// + /// 根据名称检查是否存在子数据结点。 + /// + /// 子数据结点名称。 + /// 是否存在子数据结点。 + public bool HasChild(string name) + { + if (!IsValidName(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + if (m_Childs == null) + { + return false; + } + + foreach (DataNode child in m_Childs) + { + if (child.Name == name) + { + return true; + } + } + + return false; + } + + /// + /// 根据索引获取子数据结点。 + /// + /// 子数据结点的索引。 + /// 指定索引的子数据结点,如果索引越界,则返回空。 + public IDataNode GetChild(int index) + { + return index >= 0 && index < ChildCount ? m_Childs[index] : null; + } + + /// + /// 根据名称获取子数据结点。 + /// + /// 子数据结点名称。 + /// 指定名称的子数据结点,如果没有找到,则返回空。 + public IDataNode GetChild(string name) + { + if (!IsValidName(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + if (m_Childs == null) + { + return null; + } + + foreach (DataNode child in m_Childs) + { + if (child.Name == name) + { + return child; + } + } + + return null; + } + + /// + /// 根据名称获取或增加子数据结点。 + /// + /// 子数据结点名称。 + /// 指定名称的子数据结点,如果对应名称的子数据结点已存在,则返回已存在的子数据结点,否则增加子数据结点。 + public IDataNode GetOrAddChild(string name) + { + DataNode node = (DataNode)GetChild(name); + if (node != null) + { + return node; + } + + node = Create(name, this); + + if (m_Childs == null) + { + m_Childs = new List(); + } + + m_Childs.Add(node); + + return node; + } + + /// + /// 获取所有子数据结点。 + /// + /// 所有子数据结点。 + public IDataNode[] GetAllChild() + { + if (m_Childs == null) + { + return EmptyDataNodeArray; + } + + return m_Childs.ToArray(); + } + + /// + /// 获取所有子数据结点。 + /// + /// 所有子数据结点。 + public void GetAllChild(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + if (m_Childs == null) + { + return; + } + + foreach (DataNode child in m_Childs) + { + results.Add(child); + } + } + + /// + /// 根据索引移除子数据结点。 + /// + /// 子数据结点的索引位置。 + public void RemoveChild(int index) + { + DataNode node = (DataNode)GetChild(index); + if (node == null) + { + return; + } + + m_Childs.Remove(node); + ReferencePool.Release(node); + } + + /// + /// 根据名称移除子数据结点。 + /// + /// 子数据结点名称。 + public void RemoveChild(string name) + { + DataNode node = (DataNode)GetChild(name); + if (node == null) + { + return; + } + + m_Childs.Remove(node); + ReferencePool.Release(node); + } + + public void Clear() + { + if (m_Data != null) + { + ReferencePool.Release(m_Data); + m_Data = null; + } + + if (m_Childs != null) + { + foreach (DataNode child in m_Childs) + { + ReferencePool.Release(child); + } + + m_Childs.Clear(); + } + } + + /// + /// 获取数据结点字符串。 + /// + /// 数据结点字符串。 + public override string ToString() + { + return Utility.Text.Format("{0}: {1}", FullName, ToDataString()); + } + + /// + /// 获取数据字符串。 + /// + /// 数据字符串。 + public string ToDataString() + { + if (m_Data == null) + { + return ""; + } + + return Utility.Text.Format("[{0}] {1}", m_Data.Type.Name, m_Data); + } + + /// + /// 检测数据结点名称是否合法。 + /// + /// 要检测的数据结点名称。 + /// 是否是合法的数据结点名称。 + private static bool IsValidName(string name) + { + if (string.IsNullOrEmpty(name)) + { + return false; + } + + foreach (string pathSplitSeparator in PathSplitSeparator) + { + if (name.Contains(pathSplitSeparator)) + { + return false; + } + } + + return true; + } + + void IReference.Clear() + { + m_Name = null; + m_Parent = null; + Clear(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/DataNodeManager.DataNode.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/DataNodeManager.DataNode.cs.meta new file mode 100644 index 0000000..14187ab --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/DataNodeManager.DataNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cb1bfec1b6dc67b428a15fa1c6c946ed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/DataNodeManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/DataNodeManager.cs new file mode 100644 index 0000000..263ce07 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/DataNodeManager.cs @@ -0,0 +1,280 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.DataNode +{ + /// + /// 数据结点管理器。 + /// + internal sealed partial class DataNodeManager : GameFrameworkModule, IDataNodeManager + { + private static readonly string[] EmptyStringArray = new string[] { }; + private static readonly string[] PathSplitSeparator = new string[] { ".", "/", "\\" }; + + private const string RootName = ""; + private DataNode m_Root; + + /// + /// 初始化数据结点管理器的新实例。 + /// + public DataNodeManager() + { + m_Root = DataNode.Create(RootName, null); + } + + /// + /// 获取根数据结点。 + /// + public IDataNode Root + { + get + { + return m_Root; + } + } + + /// + /// 数据结点管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 关闭并清理数据结点管理器。 + /// + internal override void Shutdown() + { + ReferencePool.Release(m_Root); + m_Root = null; + } + + /// + /// 根据类型获取数据结点的数据。 + /// + /// 要获取的数据类型。 + /// 相对于 node 的查找路径。 + /// 指定类型的数据。 + public T GetData(string path) where T : Variable + { + return GetData(path, null); + } + + /// + /// 获取数据结点的数据。 + /// + /// 相对于 node 的查找路径。 + /// 数据结点的数据。 + public Variable GetData(string path) + { + return GetData(path, null); + } + + /// + /// 根据类型获取数据结点的数据。 + /// + /// 要获取的数据类型。 + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + /// 指定类型的数据。 + public T GetData(string path, IDataNode node) where T : Variable + { + IDataNode current = GetNode(path, node); + if (current == null) + { + throw new GameFrameworkException(Utility.Text.Format("Data node is not exist, path '{0}', node '{1}'.", path, node != null ? node.FullName : string.Empty)); + } + + return current.GetData(); + } + + /// + /// 获取数据结点的数据。 + /// + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + /// 数据结点的数据。 + public Variable GetData(string path, IDataNode node) + { + IDataNode current = GetNode(path, node); + if (current == null) + { + throw new GameFrameworkException(Utility.Text.Format("Data node is not exist, path '{0}', node '{1}'.", path, node != null ? node.FullName : string.Empty)); + } + + return current.GetData(); + } + + /// + /// 设置数据结点的数据。 + /// + /// 要设置的数据类型。 + /// 相对于 node 的查找路径。 + /// 要设置的数据。 + public void SetData(string path, T data) where T : Variable + { + SetData(path, data, null); + } + + /// + /// 设置数据结点的数据。 + /// + /// 相对于 node 的查找路径。 + /// 要设置的数据。 + public void SetData(string path, Variable data) + { + SetData(path, data, null); + } + + /// + /// 设置数据结点的数据。 + /// + /// 要设置的数据类型。 + /// 相对于 node 的查找路径。 + /// 要设置的数据。 + /// 查找起始结点。 + public void SetData(string path, T data, IDataNode node) where T : Variable + { + IDataNode current = GetOrAddNode(path, node); + current.SetData(data); + } + + /// + /// 设置数据结点的数据。 + /// + /// 相对于 node 的查找路径。 + /// 要设置的数据。 + /// 查找起始结点。 + public void SetData(string path, Variable data, IDataNode node) + { + IDataNode current = GetOrAddNode(path, node); + current.SetData(data); + } + + /// + /// 获取数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 指定位置的数据结点,如果没有找到,则返回空。 + public IDataNode GetNode(string path) + { + return GetNode(path, null); + } + + /// + /// 获取数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + /// 指定位置的数据结点,如果没有找到,则返回空。 + public IDataNode GetNode(string path, IDataNode node) + { + IDataNode current = node ?? m_Root; + string[] splitedPath = GetSplitedPath(path); + foreach (string i in splitedPath) + { + current = current.GetChild(i); + if (current == null) + { + return null; + } + } + + return current; + } + + /// + /// 获取或增加数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 指定位置的数据结点,如果没有找到,则创建相应的数据结点。 + public IDataNode GetOrAddNode(string path) + { + return GetOrAddNode(path, null); + } + + /// + /// 获取或增加数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + /// 指定位置的数据结点,如果没有找到,则增加相应的数据结点。 + public IDataNode GetOrAddNode(string path, IDataNode node) + { + IDataNode current = node ?? m_Root; + string[] splitedPath = GetSplitedPath(path); + foreach (string i in splitedPath) + { + current = current.GetOrAddChild(i); + } + + return current; + } + + /// + /// 移除数据结点。 + /// + /// 相对于 node 的查找路径。 + public void RemoveNode(string path) + { + RemoveNode(path, null); + } + + /// + /// 移除数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + public void RemoveNode(string path, IDataNode node) + { + IDataNode current = node ?? m_Root; + IDataNode parent = current.Parent; + string[] splitedPath = GetSplitedPath(path); + foreach (string i in splitedPath) + { + parent = current; + current = current.GetChild(i); + if (current == null) + { + return; + } + } + + if (parent != null) + { + parent.RemoveChild(current.Name); + } + } + + /// + /// 移除所有数据结点。 + /// + public void Clear() + { + m_Root.Clear(); + } + + /// + /// 数据结点路径切分工具函数。 + /// + /// 要切分的数据结点路径。 + /// 切分后的字符串数组。 + private static string[] GetSplitedPath(string path) + { + if (string.IsNullOrEmpty(path)) + { + return EmptyStringArray; + } + + return path.Split(PathSplitSeparator, StringSplitOptions.RemoveEmptyEntries); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/DataNodeManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/DataNodeManager.cs.meta new file mode 100644 index 0000000..7d44506 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/DataNodeManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a5a041d45c1a42b478743b0483a1cf1c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/IDataNode.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/IDataNode.cs new file mode 100644 index 0000000..37a990b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/IDataNode.cs @@ -0,0 +1,151 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.DataNode +{ + /// + /// 数据结点接口。 + /// + public interface IDataNode + { + /// + /// 获取数据结点的名称。 + /// + string Name + { + get; + } + + /// + /// 获取数据结点的完整名称。 + /// + string FullName + { + get; + } + + /// + /// 获取父数据结点。 + /// + IDataNode Parent + { + get; + } + + /// + /// 获取子数据结点的数量。 + /// + int ChildCount + { + get; + } + + /// + /// 根据类型获取数据结点的数据。 + /// + /// 要获取的数据类型。 + /// 指定类型的数据。 + T GetData() where T : Variable; + + /// + /// 获取数据结点的数据。 + /// + /// 数据结点数据。 + Variable GetData(); + + /// + /// 设置数据结点的数据。 + /// + /// 要设置的数据类型。 + /// 要设置的数据。 + void SetData(T data) where T : Variable; + + /// + /// 设置数据结点的数据。 + /// + /// 要设置的数据。 + void SetData(Variable data); + + /// + /// 根据索引检查是否存在子数据结点。 + /// + /// 子数据结点的索引。 + /// 是否存在子数据结点。 + bool HasChild(int index); + + /// + /// 根据名称检查是否存在子数据结点。 + /// + /// 子数据结点名称。 + /// 是否存在子数据结点。 + bool HasChild(string name); + + /// + /// 根据索引获取子数据结点。 + /// + /// 子数据结点的索引。 + /// 指定索引的子数据结点,如果索引越界,则返回空。 + IDataNode GetChild(int index); + + /// + /// 根据名称获取子数据结点。 + /// + /// 子数据结点名称。 + /// 指定名称的子数据结点,如果没有找到,则返回空。 + IDataNode GetChild(string name); + + /// + /// 根据名称获取或增加子数据结点。 + /// + /// 子数据结点名称。 + /// 指定名称的子数据结点,如果对应名称的子数据结点已存在,则返回已存在的子数据结点,否则增加子数据结点。 + IDataNode GetOrAddChild(string name); + + /// + /// 获取所有子数据结点。 + /// + /// 所有子数据结点。 + IDataNode[] GetAllChild(); + + /// + /// 获取所有子数据结点。 + /// + /// 所有子数据结点。 + void GetAllChild(List results); + + /// + /// 根据索引移除子数据结点。 + /// + /// 子数据结点的索引。 + void RemoveChild(int index); + + /// + /// 根据名称移除子数据结点。 + /// + /// 子数据结点名称。 + void RemoveChild(string name); + + /// + /// 移除当前数据结点的数据和所有子数据结点。 + /// + void Clear(); + + /// + /// 获取数据结点字符串。 + /// + /// 数据结点字符串。 + string ToString(); + + /// + /// 获取数据字符串。 + /// + /// 数据字符串。 + string ToDataString(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/IDataNode.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/IDataNode.cs.meta new file mode 100644 index 0000000..48ee794 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/IDataNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2c9fc2c136a4b084c897cf4ac96829ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/IDataNodeManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/IDataNodeManager.cs new file mode 100644 index 0000000..71b7174 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/IDataNodeManager.cs @@ -0,0 +1,135 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.DataNode +{ + /// + /// 数据结点管理器接口。 + /// + public interface IDataNodeManager + { + /// + /// 获取根数据结点。 + /// + IDataNode Root + { + get; + } + + /// + /// 根据类型获取数据结点的数据。 + /// + /// 要获取的数据类型。 + /// 相对于 node 的查找路径。 + /// 指定类型的数据。 + T GetData(string path) where T : Variable; + + /// + /// 获取数据结点的数据。 + /// + /// 相对于 node 的查找路径。 + /// 数据结点的数据。 + Variable GetData(string path); + + /// + /// 根据类型获取数据结点的数据。 + /// + /// 要获取的数据类型。 + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + /// 指定类型的数据。 + T GetData(string path, IDataNode node) where T : Variable; + + /// + /// 获取数据结点的数据。 + /// + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + /// 数据结点的数据。 + Variable GetData(string path, IDataNode node); + + /// + /// 设置数据结点的数据。 + /// + /// 要设置的数据类型。 + /// 相对于 node 的查找路径。 + /// 要设置的数据。 + void SetData(string path, T data) where T : Variable; + + /// + /// 设置数据结点的数据。 + /// + /// 相对于 node 的查找路径。 + /// 要设置的数据。 + void SetData(string path, Variable data); + + /// + /// 设置数据结点的数据。 + /// + /// 要设置的数据类型。 + /// 相对于 node 的查找路径。 + /// 要设置的数据。 + /// 查找起始结点。 + void SetData(string path, T data, IDataNode node) where T : Variable; + + /// + /// 设置数据结点的数据。 + /// + /// 相对于 node 的查找路径。 + /// 要设置的数据。 + /// 查找起始结点。 + void SetData(string path, Variable data, IDataNode node); + + /// + /// 获取数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 指定位置的数据结点,如果没有找到,则返回空。 + IDataNode GetNode(string path); + + /// + /// 获取数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + /// 指定位置的数据结点,如果没有找到,则返回空。 + IDataNode GetNode(string path, IDataNode node); + + /// + /// 获取或增加数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 指定位置的数据结点,如果没有找到,则创建相应的数据结点。 + IDataNode GetOrAddNode(string path); + + /// + /// 获取或增加数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + /// 指定位置的数据结点,如果没有找到,则创建相应的数据结点。 + IDataNode GetOrAddNode(string path, IDataNode node); + + /// + /// 移除数据结点。 + /// + /// 相对于 node 的查找路径。 + void RemoveNode(string path); + + /// + /// 移除数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + void RemoveNode(string path, IDataNode node); + + /// + /// 移除所有数据结点。 + /// + void Clear(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/IDataNodeManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/IDataNodeManager.cs.meta new file mode 100644 index 0000000..f42a61d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataNode/IDataNodeManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 99b75476a861ccd4485d535c36498e22 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable.meta new file mode 100644 index 0000000..6a2d064 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 60116ee6626486142b20f1aec4f91744 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableBase.cs new file mode 100644 index 0000000..872fbdb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableBase.cs @@ -0,0 +1,304 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System; + +namespace GameFramework.DataTable +{ + /// + /// 数据表基类。 + /// + public abstract class DataTableBase : IDataProvider + { + private readonly string m_Name; + private readonly DataProvider m_DataProvider; + + /// + /// 初始化数据表基类的新实例。 + /// + public DataTableBase() + : this(null) + { + } + + /// + /// 初始化数据表基类的新实例。 + /// + /// 数据表名称。 + public DataTableBase(string name) + { + m_Name = name ?? string.Empty; + m_DataProvider = new DataProvider(this); + } + + /// + /// 获取数据表名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取数据表完整名称。 + /// + public string FullName + { + get + { + return new TypeNamePair(Type, m_Name).ToString(); + } + } + + /// + /// 获取数据表行的类型。 + /// + public abstract Type Type + { + get; + } + + /// + /// 获取数据表行数。 + /// + public abstract int Count + { + get; + } + + /// + /// 读取数据表成功事件。 + /// + public event EventHandler ReadDataSuccess + { + add + { + m_DataProvider.ReadDataSuccess += value; + } + remove + { + m_DataProvider.ReadDataSuccess -= value; + } + } + + /// + /// 读取数据表失败事件。 + /// + public event EventHandler ReadDataFailure + { + add + { + m_DataProvider.ReadDataFailure += value; + } + remove + { + m_DataProvider.ReadDataFailure -= value; + } + } + + /// + /// 读取数据表更新事件。 + /// + public event EventHandler ReadDataUpdate + { + add + { + m_DataProvider.ReadDataUpdate += value; + } + remove + { + m_DataProvider.ReadDataUpdate -= value; + } + } + + /// + /// 读取数据表时加载依赖资源事件。 + /// + public event EventHandler ReadDataDependencyAsset + { + add + { + m_DataProvider.ReadDataDependencyAsset += value; + } + remove + { + m_DataProvider.ReadDataDependencyAsset -= value; + } + } + + /// + /// 读取数据表。 + /// + /// 数据表资源名称。 + public void ReadData(string dataTableAssetName) + { + m_DataProvider.ReadData(dataTableAssetName); + } + + /// + /// 读取数据表。 + /// + /// 数据表资源名称。 + /// 加载数据表资源的优先级。 + public void ReadData(string dataTableAssetName, int priority) + { + m_DataProvider.ReadData(dataTableAssetName, priority); + } + + /// + /// 读取数据表。 + /// + /// 数据表资源名称。 + /// 用户自定义数据。 + public void ReadData(string dataTableAssetName, object userData) + { + m_DataProvider.ReadData(dataTableAssetName, userData); + } + + /// + /// 读取数据表。 + /// + /// 数据表资源名称。 + /// 加载数据表资源的优先级。 + /// 用户自定义数据。 + public void ReadData(string dataTableAssetName, int priority, object userData) + { + m_DataProvider.ReadData(dataTableAssetName, priority, userData); + } + + /// + /// 解析数据表。 + /// + /// 要解析的数据表字符串。 + /// 是否解析数据表成功。 + public bool ParseData(string dataTableString) + { + return m_DataProvider.ParseData(dataTableString); + } + + /// + /// 解析数据表。 + /// + /// 要解析的数据表字符串。 + /// 用户自定义数据。 + /// 是否解析数据表成功。 + public bool ParseData(string dataTableString, object userData) + { + return m_DataProvider.ParseData(dataTableString, userData); + } + + /// + /// 解析数据表。 + /// + /// 要解析的数据表二进制流。 + /// 是否解析数据表成功。 + public bool ParseData(byte[] dataTableBytes) + { + return m_DataProvider.ParseData(dataTableBytes); + } + + /// + /// 解析数据表。 + /// + /// 要解析的数据表二进制流。 + /// 用户自定义数据。 + /// 是否解析数据表成功。 + public bool ParseData(byte[] dataTableBytes, object userData) + { + return m_DataProvider.ParseData(dataTableBytes, userData); + } + + /// + /// 解析数据表。 + /// + /// 要解析的数据表二进制流。 + /// 数据表二进制流的起始位置。 + /// 数据表二进制流的长度。 + /// 是否解析数据表成功。 + public bool ParseData(byte[] dataTableBytes, int startIndex, int length) + { + return m_DataProvider.ParseData(dataTableBytes, startIndex, length); + } + + /// + /// 解析数据表。 + /// + /// 要解析的数据表二进制流。 + /// 数据表二进制流的起始位置。 + /// 数据表二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析数据表成功。 + public bool ParseData(byte[] dataTableBytes, int startIndex, int length, object userData) + { + return m_DataProvider.ParseData(dataTableBytes, startIndex, length, userData); + } + + /// + /// 检查是否存在数据表行。 + /// + /// 数据表行的编号。 + /// 是否存在数据表行。 + public abstract bool HasDataRow(int id); + + /// + /// 增加数据表行。 + /// + /// 要解析的数据表行字符串。 + /// 用户自定义数据。 + /// 是否增加数据表行成功。 + public abstract bool AddDataRow(string dataRowString, object userData); + + /// + /// 增加数据表行。 + /// + /// 要解析的数据表行二进制流。 + /// 数据表行二进制流的起始位置。 + /// 数据表行二进制流的长度。 + /// 用户自定义数据。 + /// 是否增加数据表行成功。 + public abstract bool AddDataRow(byte[] dataRowBytes, int startIndex, int length, object userData); + + /// + /// 移除指定数据表行。 + /// + /// 要移除数据表行的编号。 + /// 是否移除数据表行成功。 + public abstract bool RemoveDataRow(int id); + + /// + /// 清空所有数据表行。 + /// + public abstract void RemoveAllDataRows(); + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + internal void SetResourceManager(IResourceManager resourceManager) + { + m_DataProvider.SetResourceManager(resourceManager); + } + + /// + /// 设置数据提供者辅助器。 + /// + /// 数据提供者辅助器。 + internal void SetDataProviderHelper(IDataProviderHelper dataProviderHelper) + { + m_DataProvider.SetDataProviderHelper(dataProviderHelper); + } + + /// + /// 关闭并清理数据表。 + /// + internal abstract void Shutdown(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableBase.cs.meta new file mode 100644 index 0000000..6806a30 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 870439b9509ce794e92461fe9b71c385 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableManager.DataTable.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableManager.DataTable.cs new file mode 100644 index 0000000..4213651 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableManager.DataTable.cs @@ -0,0 +1,524 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace GameFramework.DataTable +{ + internal sealed partial class DataTableManager : GameFrameworkModule, IDataTableManager + { + /// + /// 数据表。 + /// + /// 数据表行的类型。 + private sealed class DataTable : DataTableBase, IDataTable where T : class, IDataRow, new() + { + private readonly Dictionary m_DataSet; + private T m_MinIdDataRow; + private T m_MaxIdDataRow; + + /// + /// 初始化数据表的新实例。 + /// + /// 数据表名称。 + public DataTable(string name) + : base(name) + { + m_DataSet = new Dictionary(); + m_MinIdDataRow = null; + m_MaxIdDataRow = null; + } + + /// + /// 获取数据表行的类型。 + /// + public override Type Type + { + get + { + return typeof(T); + } + } + + /// + /// 获取数据表行数。 + /// + public override int Count + { + get + { + return m_DataSet.Count; + } + } + + /// + /// 获取数据表行。 + /// + /// 数据表行的编号。 + /// 数据表行。 + public T this[int id] + { + get + { + return GetDataRow(id); + } + } + + /// + /// 获取编号最小的数据表行。 + /// + public T MinIdDataRow + { + get + { + return m_MinIdDataRow; + } + } + + /// + /// 获取编号最大的数据表行。 + /// + public T MaxIdDataRow + { + get + { + return m_MaxIdDataRow; + } + } + + /// + /// 检查是否存在数据表行。 + /// + /// 数据表行的编号。 + /// 是否存在数据表行。 + public override bool HasDataRow(int id) + { + return m_DataSet.ContainsKey(id); + } + + /// + /// 检查是否存在数据表行。 + /// + /// 要检查的条件。 + /// 是否存在数据表行。 + public bool HasDataRow(Predicate condition) + { + if (condition == null) + { + throw new GameFrameworkException("Condition is invalid."); + } + + foreach (KeyValuePair dataRow in m_DataSet) + { + if (condition(dataRow.Value)) + { + return true; + } + } + + return false; + } + + /// + /// 获取数据表行。 + /// + /// 数据表行的编号。 + /// 数据表行。 + public T GetDataRow(int id) + { + T dataRow = null; + if (m_DataSet.TryGetValue(id, out dataRow)) + { + return dataRow; + } + + return null; + } + + /// + /// 获取符合条件的数据表行。 + /// + /// 要检查的条件。 + /// 符合条件的数据表行。 + /// 当存在多个符合条件的数据表行时,仅返回第一个符合条件的数据表行。 + public T GetDataRow(Predicate condition) + { + if (condition == null) + { + throw new GameFrameworkException("Condition is invalid."); + } + + foreach (KeyValuePair dataRow in m_DataSet) + { + if (condition(dataRow.Value)) + { + return dataRow.Value; + } + } + + return null; + } + + /// + /// 获取符合条件的数据表行。 + /// + /// 要检查的条件。 + /// 符合条件的数据表行。 + public T[] GetDataRows(Predicate condition) + { + if (condition == null) + { + throw new GameFrameworkException("Condition is invalid."); + } + + List results = new List(); + foreach (KeyValuePair dataRow in m_DataSet) + { + if (condition(dataRow.Value)) + { + results.Add(dataRow.Value); + } + } + + return results.ToArray(); + } + + /// + /// 获取符合条件的数据表行。 + /// + /// 要检查的条件。 + /// 符合条件的数据表行。 + public void GetDataRows(Predicate condition, List results) + { + if (condition == null) + { + throw new GameFrameworkException("Condition is invalid."); + } + + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair dataRow in m_DataSet) + { + if (condition(dataRow.Value)) + { + results.Add(dataRow.Value); + } + } + } + + /// + /// 获取排序后的数据表行。 + /// + /// 要排序的条件。 + /// 排序后的数据表行。 + public T[] GetDataRows(Comparison comparison) + { + if (comparison == null) + { + throw new GameFrameworkException("Comparison is invalid."); + } + + List results = new List(); + foreach (KeyValuePair dataRow in m_DataSet) + { + results.Add(dataRow.Value); + } + + results.Sort(comparison); + return results.ToArray(); + } + + /// + /// 获取排序后的数据表行。 + /// + /// 要排序的条件。 + /// 排序后的数据表行。 + public void GetDataRows(Comparison comparison, List results) + { + if (comparison == null) + { + throw new GameFrameworkException("Comparison is invalid."); + } + + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair dataRow in m_DataSet) + { + results.Add(dataRow.Value); + } + + results.Sort(comparison); + } + + /// + /// 获取排序后的符合条件的数据表行。 + /// + /// 要检查的条件。 + /// 要排序的条件。 + /// 排序后的符合条件的数据表行。 + public T[] GetDataRows(Predicate condition, Comparison comparison) + { + if (condition == null) + { + throw new GameFrameworkException("Condition is invalid."); + } + + if (comparison == null) + { + throw new GameFrameworkException("Comparison is invalid."); + } + + List results = new List(); + foreach (KeyValuePair dataRow in m_DataSet) + { + if (condition(dataRow.Value)) + { + results.Add(dataRow.Value); + } + } + + results.Sort(comparison); + return results.ToArray(); + } + + /// + /// 获取排序后的符合条件的数据表行。 + /// + /// 要检查的条件。 + /// 要排序的条件。 + /// 排序后的符合条件的数据表行。 + public void GetDataRows(Predicate condition, Comparison comparison, List results) + { + if (condition == null) + { + throw new GameFrameworkException("Condition is invalid."); + } + + if (comparison == null) + { + throw new GameFrameworkException("Comparison is invalid."); + } + + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair dataRow in m_DataSet) + { + if (condition(dataRow.Value)) + { + results.Add(dataRow.Value); + } + } + + results.Sort(comparison); + } + + /// + /// 获取所有数据表行。 + /// + /// 所有数据表行。 + public T[] GetAllDataRows() + { + int index = 0; + T[] results = new T[m_DataSet.Count]; + foreach (KeyValuePair dataRow in m_DataSet) + { + results[index++] = dataRow.Value; + } + + return results; + } + + /// + /// 获取所有数据表行。 + /// + /// 所有数据表行。 + public void GetAllDataRows(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair dataRow in m_DataSet) + { + results.Add(dataRow.Value); + } + } + + /// + /// 增加数据表行。 + /// + /// 要解析的数据表行字符串。 + /// 用户自定义数据。 + /// 是否增加数据表行成功。 + public override bool AddDataRow(string dataRowString, object userData) + { + try + { + T dataRow = new T(); + if (!dataRow.ParseDataRow(dataRowString, userData)) + { + return false; + } + + InternalAddDataRow(dataRow); + return true; + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Utility.Text.Format("Can not parse data row string for data table '{0}' with exception '{1}'.", new TypeNamePair(typeof(T), Name), exception), exception); + } + } + + /// + /// 增加数据表行。 + /// + /// 要解析的数据表行二进制流。 + /// 数据表行二进制流的起始位置。 + /// 数据表行二进制流的长度。 + /// 用户自定义数据。 + /// 是否增加数据表行成功。 + public override bool AddDataRow(byte[] dataRowBytes, int startIndex, int length, object userData) + { + try + { + T dataRow = new T(); + if (!dataRow.ParseDataRow(dataRowBytes, startIndex, length, userData)) + { + return false; + } + + InternalAddDataRow(dataRow); + return true; + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Utility.Text.Format("Can not parse data row bytes for data table '{0}' with exception '{1}'.", new TypeNamePair(typeof(T), Name), exception), exception); + } + } + + /// + /// 移除指定数据表行。 + /// + /// 要移除数据表行的编号。 + /// 是否移除数据表行成功。 + public override bool RemoveDataRow(int id) + { + if (!HasDataRow(id)) + { + return false; + } + + if (!m_DataSet.Remove(id)) + { + return false; + } + + if (m_MinIdDataRow != null && m_MinIdDataRow.Id == id || m_MaxIdDataRow != null && m_MaxIdDataRow.Id == id) + { + m_MinIdDataRow = null; + m_MaxIdDataRow = null; + foreach (KeyValuePair dataRow in m_DataSet) + { + if (m_MinIdDataRow == null || m_MinIdDataRow.Id > dataRow.Key) + { + m_MinIdDataRow = dataRow.Value; + } + + if (m_MaxIdDataRow == null || m_MaxIdDataRow.Id < dataRow.Key) + { + m_MaxIdDataRow = dataRow.Value; + } + } + } + + return true; + } + + /// + /// 清空所有数据表行。 + /// + public override void RemoveAllDataRows() + { + m_DataSet.Clear(); + m_MinIdDataRow = null; + m_MaxIdDataRow = null; + } + + /// + /// 返回循环访问集合的枚举数。 + /// + /// 循环访问集合的枚举数。 + public IEnumerator GetEnumerator() + { + return m_DataSet.Values.GetEnumerator(); + } + + /// + /// 返回循环访问集合的枚举数。 + /// + /// 循环访问集合的枚举数。 + IEnumerator IEnumerable.GetEnumerator() + { + return m_DataSet.Values.GetEnumerator(); + } + + /// + /// 关闭并清理数据表。 + /// + internal override void Shutdown() + { + m_DataSet.Clear(); + } + + private void InternalAddDataRow(T dataRow) + { + if (m_DataSet.ContainsKey(dataRow.Id)) + { + throw new GameFrameworkException(Utility.Text.Format("Already exist '{0}' in data table '{1}'.", dataRow.Id, new TypeNamePair(typeof(T), Name))); + } + + m_DataSet.Add(dataRow.Id, dataRow); + + if (m_MinIdDataRow == null || m_MinIdDataRow.Id > dataRow.Id) + { + m_MinIdDataRow = dataRow; + } + + if (m_MaxIdDataRow == null || m_MaxIdDataRow.Id < dataRow.Id) + { + m_MaxIdDataRow = dataRow; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableManager.DataTable.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableManager.DataTable.cs.meta new file mode 100644 index 0000000..fb21573 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableManager.DataTable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7d4d09863a21c4b4cad61148995f3a6a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableManager.cs new file mode 100644 index 0000000..2120955 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableManager.cs @@ -0,0 +1,508 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System; +using System.Collections.Generic; + +namespace GameFramework.DataTable +{ + /// + /// 数据表管理器。 + /// + internal sealed partial class DataTableManager : GameFrameworkModule, IDataTableManager + { + private readonly Dictionary m_DataTables; + private IResourceManager m_ResourceManager; + private IDataProviderHelper m_DataProviderHelper; + private IDataTableHelper m_DataTableHelper; + + /// + /// 初始化数据表管理器的新实例。 + /// + public DataTableManager() + { + m_DataTables = new Dictionary(); + m_ResourceManager = null; + m_DataProviderHelper = null; + m_DataTableHelper = null; + } + + /// + /// 获取数据表数量。 + /// + public int Count + { + get + { + return m_DataTables.Count; + } + } + + /// + /// 获取缓冲二进制流的大小。 + /// + public int CachedBytesSize + { + get + { + return DataProvider.CachedBytesSize; + } + } + + /// + /// 数据表管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 关闭并清理数据表管理器。 + /// + internal override void Shutdown() + { + foreach (KeyValuePair dataTable in m_DataTables) + { + dataTable.Value.Shutdown(); + } + + m_DataTables.Clear(); + } + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + public void SetResourceManager(IResourceManager resourceManager) + { + if (resourceManager == null) + { + throw new GameFrameworkException("Resource manager is invalid."); + } + + m_ResourceManager = resourceManager; + } + + /// + /// 设置数据表数据提供者辅助器。 + /// + /// 数据表数据提供者辅助器。 + public void SetDataProviderHelper(IDataProviderHelper dataProviderHelper) + { + if (dataProviderHelper == null) + { + throw new GameFrameworkException("Data provider helper is invalid."); + } + + m_DataProviderHelper = dataProviderHelper; + } + + /// + /// 设置数据表辅助器。 + /// + /// 数据表辅助器。 + public void SetDataTableHelper(IDataTableHelper dataTableHelper) + { + if (dataTableHelper == null) + { + throw new GameFrameworkException("Data table helper is invalid."); + } + + m_DataTableHelper = dataTableHelper; + } + + /// + /// 确保二进制流缓存分配足够大小的内存并缓存。 + /// + /// 要确保二进制流缓存分配内存的大小。 + public void EnsureCachedBytesSize(int ensureSize) + { + DataProvider.EnsureCachedBytesSize(ensureSize); + } + + /// + /// 释放缓存的二进制流。 + /// + public void FreeCachedBytes() + { + DataProvider.FreeCachedBytes(); + } + + /// + /// 是否存在数据表。 + /// + /// 数据表行的类型。 + /// 是否存在数据表。 + public bool HasDataTable() where T : IDataRow + { + return InternalHasDataTable(new TypeNamePair(typeof(T))); + } + + /// + /// 是否存在数据表。 + /// + /// 数据表行的类型。 + /// 是否存在数据表。 + public bool HasDataTable(Type dataRowType) + { + if (dataRowType == null) + { + throw new GameFrameworkException("Data row type is invalid."); + } + + if (!typeof(IDataRow).IsAssignableFrom(dataRowType)) + { + throw new GameFrameworkException(Utility.Text.Format("Data row type '{0}' is invalid.", dataRowType.FullName)); + } + + return InternalHasDataTable(new TypeNamePair(dataRowType)); + } + + /// + /// 是否存在数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 是否存在数据表。 + public bool HasDataTable(string name) where T : IDataRow + { + return InternalHasDataTable(new TypeNamePair(typeof(T), name)); + } + + /// + /// 是否存在数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 是否存在数据表。 + public bool HasDataTable(Type dataRowType, string name) + { + if (dataRowType == null) + { + throw new GameFrameworkException("Data row type is invalid."); + } + + if (!typeof(IDataRow).IsAssignableFrom(dataRowType)) + { + throw new GameFrameworkException(Utility.Text.Format("Data row type '{0}' is invalid.", dataRowType.FullName)); + } + + return InternalHasDataTable(new TypeNamePair(dataRowType, name)); + } + + /// + /// 获取数据表。 + /// + /// 数据表行的类型。 + /// 要获取的数据表。 + public IDataTable GetDataTable() where T : IDataRow + { + return (IDataTable)InternalGetDataTable(new TypeNamePair(typeof(T))); + } + + /// + /// 获取数据表。 + /// + /// 数据表行的类型。 + /// 要获取的数据表。 + public DataTableBase GetDataTable(Type dataRowType) + { + if (dataRowType == null) + { + throw new GameFrameworkException("Data row type is invalid."); + } + + if (!typeof(IDataRow).IsAssignableFrom(dataRowType)) + { + throw new GameFrameworkException(Utility.Text.Format("Data row type '{0}' is invalid.", dataRowType.FullName)); + } + + return InternalGetDataTable(new TypeNamePair(dataRowType)); + } + + /// + /// 获取数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 要获取的数据表。 + public IDataTable GetDataTable(string name) where T : IDataRow + { + return (IDataTable)InternalGetDataTable(new TypeNamePair(typeof(T), name)); + } + + /// + /// 获取数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 要获取的数据表。 + public DataTableBase GetDataTable(Type dataRowType, string name) + { + if (dataRowType == null) + { + throw new GameFrameworkException("Data row type is invalid."); + } + + if (!typeof(IDataRow).IsAssignableFrom(dataRowType)) + { + throw new GameFrameworkException(Utility.Text.Format("Data row type '{0}' is invalid.", dataRowType.FullName)); + } + + return InternalGetDataTable(new TypeNamePair(dataRowType, name)); + } + + /// + /// 获取所有数据表。 + /// + /// 所有数据表。 + public DataTableBase[] GetAllDataTables() + { + int index = 0; + DataTableBase[] results = new DataTableBase[m_DataTables.Count]; + foreach (KeyValuePair dataTable in m_DataTables) + { + results[index++] = dataTable.Value; + } + + return results; + } + + /// + /// 获取所有数据表。 + /// + /// 所有数据表。 + public void GetAllDataTables(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair dataTable in m_DataTables) + { + results.Add(dataTable.Value); + } + } + + /// + /// 创建数据表。 + /// + /// 数据表行的类型。 + /// 要创建的数据表。 + public IDataTable CreateDataTable() where T : class, IDataRow, new() + { + return CreateDataTable(string.Empty); + } + + /// + /// 创建数据表。 + /// + /// 数据表行的类型。 + /// 要创建的数据表。 + public DataTableBase CreateDataTable(Type dataRowType) + { + return CreateDataTable(dataRowType, string.Empty); + } + + /// + /// 创建数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 要创建的数据表。 + public IDataTable CreateDataTable(string name) where T : class, IDataRow, new() + { + if (m_ResourceManager == null) + { + throw new GameFrameworkException("You must set resource manager first."); + } + + if (m_DataProviderHelper == null) + { + throw new GameFrameworkException("You must set data provider helper first."); + } + + TypeNamePair typeNamePair = new TypeNamePair(typeof(T), name); + if (HasDataTable(name)) + { + throw new GameFrameworkException(Utility.Text.Format("Already exist data table '{0}'.", typeNamePair)); + } + + DataTable dataTable = new DataTable(name); + dataTable.SetResourceManager(m_ResourceManager); + dataTable.SetDataProviderHelper(m_DataProviderHelper); + m_DataTables.Add(typeNamePair, dataTable); + return dataTable; + } + + /// + /// 创建数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 要创建的数据表。 + public DataTableBase CreateDataTable(Type dataRowType, string name) + { + if (m_ResourceManager == null) + { + throw new GameFrameworkException("You must set resource manager first."); + } + + if (m_DataProviderHelper == null) + { + throw new GameFrameworkException("You must set data provider helper first."); + } + + if (dataRowType == null) + { + throw new GameFrameworkException("Data row type is invalid."); + } + + if (!typeof(IDataRow).IsAssignableFrom(dataRowType)) + { + throw new GameFrameworkException(Utility.Text.Format("Data row type '{0}' is invalid.", dataRowType.FullName)); + } + + TypeNamePair typeNamePair = new TypeNamePair(dataRowType, name); + if (HasDataTable(dataRowType, name)) + { + throw new GameFrameworkException(Utility.Text.Format("Already exist data table '{0}'.", typeNamePair)); + } + + Type dataTableType = typeof(DataTable<>).MakeGenericType(dataRowType); + DataTableBase dataTable = (DataTableBase)Activator.CreateInstance(dataTableType, name); + dataTable.SetResourceManager(m_ResourceManager); + dataTable.SetDataProviderHelper(m_DataProviderHelper); + m_DataTables.Add(typeNamePair, dataTable); + return dataTable; + } + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + public bool DestroyDataTable() where T : IDataRow + { + return InternalDestroyDataTable(new TypeNamePair(typeof(T))); + } + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 是否销毁数据表成功。 + public bool DestroyDataTable(Type dataRowType) + { + if (dataRowType == null) + { + throw new GameFrameworkException("Data row type is invalid."); + } + + if (!typeof(IDataRow).IsAssignableFrom(dataRowType)) + { + throw new GameFrameworkException(Utility.Text.Format("Data row type '{0}' is invalid.", dataRowType.FullName)); + } + + return InternalDestroyDataTable(new TypeNamePair(dataRowType)); + } + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + public bool DestroyDataTable(string name) where T : IDataRow + { + return InternalDestroyDataTable(new TypeNamePair(typeof(T), name)); + } + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 是否销毁数据表成功。 + public bool DestroyDataTable(Type dataRowType, string name) + { + if (dataRowType == null) + { + throw new GameFrameworkException("Data row type is invalid."); + } + + if (!typeof(IDataRow).IsAssignableFrom(dataRowType)) + { + throw new GameFrameworkException(Utility.Text.Format("Data row type '{0}' is invalid.", dataRowType.FullName)); + } + + return InternalDestroyDataTable(new TypeNamePair(dataRowType, name)); + } + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 要销毁的数据表。 + /// 是否销毁数据表成功。 + public bool DestroyDataTable(IDataTable dataTable) where T : IDataRow + { + if (dataTable == null) + { + throw new GameFrameworkException("Data table is invalid."); + } + + return InternalDestroyDataTable(new TypeNamePair(typeof(T), dataTable.Name)); + } + + /// + /// 销毁数据表。 + /// + /// 要销毁的数据表。 + /// 是否销毁数据表成功。 + public bool DestroyDataTable(DataTableBase dataTable) + { + if (dataTable == null) + { + throw new GameFrameworkException("Data table is invalid."); + } + + return InternalDestroyDataTable(new TypeNamePair(dataTable.Type, dataTable.Name)); + } + + private bool InternalHasDataTable(TypeNamePair typeNamePair) + { + return m_DataTables.ContainsKey(typeNamePair); + } + + private DataTableBase InternalGetDataTable(TypeNamePair typeNamePair) + { + DataTableBase dataTable = null; + if (m_DataTables.TryGetValue(typeNamePair, out dataTable)) + { + return dataTable; + } + + return null; + } + + private bool InternalDestroyDataTable(TypeNamePair typeNamePair) + { + DataTableBase dataTable = null; + if (m_DataTables.TryGetValue(typeNamePair, out dataTable)) + { + dataTable.Shutdown(); + return m_DataTables.Remove(typeNamePair); + } + + return false; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableManager.cs.meta new file mode 100644 index 0000000..a49d87d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/DataTableManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ecf8ce2043cbd6d4e902b299899efa6e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataRow.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataRow.cs new file mode 100644 index 0000000..3a0fda5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataRow.cs @@ -0,0 +1,41 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.DataTable +{ + /// + /// 数据表行接口。 + /// + public interface IDataRow + { + /// + /// 获取数据表行的编号。 + /// + int Id + { + get; + } + + /// + /// 解析数据表行。 + /// + /// 要解析的数据表行字符串。 + /// 用户自定义数据。 + /// 是否解析数据表行成功。 + bool ParseDataRow(string dataRowString, object userData); + + /// + /// 解析数据表行。 + /// + /// 要解析的数据表行二进制流。 + /// 数据表行二进制流的起始位置。 + /// 数据表行二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析数据表行成功。 + bool ParseDataRow(byte[] dataRowBytes, int startIndex, int length, object userData); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataRow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataRow.cs.meta new file mode 100644 index 0000000..49ed4c4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataRow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f93da616835c170488f6cec18187a65c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTable.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTable.cs new file mode 100644 index 0000000..71031ba --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTable.cs @@ -0,0 +1,192 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.DataTable +{ + /// + /// 数据表接口。 + /// + /// 数据表行的类型。 + public interface IDataTable : IEnumerable where T : IDataRow + { + /// + /// 获取数据表名称。 + /// + string Name + { + get; + } + + /// + /// 获取数据表完整名称。 + /// + string FullName + { + get; + } + + /// + /// 获取数据表行的类型。 + /// + Type Type + { + get; + } + + /// + /// 获取数据表行数。 + /// + int Count + { + get; + } + + /// + /// 获取数据表行。 + /// + /// 数据表行的编号。 + /// 数据表行。 + T this[int id] + { + get; + } + + /// + /// 获取编号最小的数据表行。 + /// + T MinIdDataRow + { + get; + } + + /// + /// 获取编号最大的数据表行。 + /// + T MaxIdDataRow + { + get; + } + + /// + /// 检查是否存在数据表行。 + /// + /// 数据表行的编号。 + /// 是否存在数据表行。 + bool HasDataRow(int id); + + /// + /// 检查是否存在数据表行。 + /// + /// 要检查的条件。 + /// 是否存在数据表行。 + bool HasDataRow(Predicate condition); + + /// + /// 获取数据表行。 + /// + /// 数据表行的编号。 + /// 数据表行。 + T GetDataRow(int id); + + /// + /// 获取符合条件的数据表行。 + /// + /// 要检查的条件。 + /// 符合条件的数据表行。 + /// 当存在多个符合条件的数据表行时,仅返回第一个符合条件的数据表行。 + T GetDataRow(Predicate condition); + + /// + /// 获取符合条件的数据表行。 + /// + /// 要检查的条件。 + /// 符合条件的数据表行。 + T[] GetDataRows(Predicate condition); + + /// + /// 获取符合条件的数据表行。 + /// + /// 要检查的条件。 + /// 符合条件的数据表行。 + void GetDataRows(Predicate condition, List results); + + /// + /// 获取排序后的数据表行。 + /// + /// 要排序的条件。 + /// 排序后的数据表行。 + T[] GetDataRows(Comparison comparison); + + /// + /// 获取排序后的数据表行。 + /// + /// 要排序的条件。 + /// 排序后的数据表行。 + void GetDataRows(Comparison comparison, List results); + + /// + /// 获取排序后的符合条件的数据表行。 + /// + /// 要检查的条件。 + /// 要排序的条件。 + /// 排序后的符合条件的数据表行。 + T[] GetDataRows(Predicate condition, Comparison comparison); + + /// + /// 获取排序后的符合条件的数据表行。 + /// + /// 要检查的条件。 + /// 要排序的条件。 + /// 排序后的符合条件的数据表行。 + void GetDataRows(Predicate condition, Comparison comparison, List results); + + /// + /// 获取所有数据表行。 + /// + /// 所有数据表行。 + T[] GetAllDataRows(); + + /// + /// 获取所有数据表行。 + /// + /// 所有数据表行。 + void GetAllDataRows(List results); + + /// + /// 增加数据表行。 + /// + /// 要解析的数据表行字符串。 + /// 用户自定义数据。 + /// 是否增加数据表行成功。 + bool AddDataRow(string dataRowString, object userData); + + /// + /// 增加数据表行。 + /// + /// 要解析的数据表行二进制流。 + /// 数据表行二进制流的起始位置。 + /// 数据表行二进制流的长度。 + /// 用户自定义数据。 + /// 是否增加数据表行成功。 + bool AddDataRow(byte[] dataRowBytes, int startIndex, int length, object userData); + + /// + /// 移除指定数据表行。 + /// + /// 要移除数据表行的编号。 + /// 是否移除数据表行成功。 + bool RemoveDataRow(int id); + + /// + /// 清空所有数据表行。 + /// + void RemoveAllDataRows(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTable.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTable.cs.meta new file mode 100644 index 0000000..876b088 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8b1a0ef456f56d24ba07013707dfadd3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTableHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTableHelper.cs new file mode 100644 index 0000000..01e5be5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTableHelper.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.DataTable +{ + /// + /// 数据表辅助器接口。 + /// + public interface IDataTableHelper + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTableHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTableHelper.cs.meta new file mode 100644 index 0000000..3725bc0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTableHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 84b60de163506284ab39584ea19ab250 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTableManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTableManager.cs new file mode 100644 index 0000000..ebad68c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTableManager.cs @@ -0,0 +1,211 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System; +using System.Collections.Generic; + +namespace GameFramework.DataTable +{ + /// + /// 数据表管理器接口。 + /// + public interface IDataTableManager + { + /// + /// 获取数据表数量。 + /// + int Count + { + get; + } + + /// + /// 获取缓冲二进制流的大小。 + /// + int CachedBytesSize + { + get; + } + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + void SetResourceManager(IResourceManager resourceManager); + + /// + /// 设置数据表数据提供者辅助器。 + /// + /// 数据表数据提供者辅助器。 + void SetDataProviderHelper(IDataProviderHelper dataProviderHelper); + + /// + /// 设置数据表辅助器。 + /// + /// 数据表辅助器。 + void SetDataTableHelper(IDataTableHelper dataTableHelper); + + /// + /// 确保二进制流缓存分配足够大小的内存并缓存。 + /// + /// 要确保二进制流缓存分配内存的大小。 + void EnsureCachedBytesSize(int ensureSize); + + /// + /// 释放缓存的二进制流。 + /// + void FreeCachedBytes(); + + /// + /// 是否存在数据表。 + /// + /// 数据表行的类型。 + /// 是否存在数据表。 + bool HasDataTable() where T : IDataRow; + + /// + /// 是否存在数据表。 + /// + /// 数据表行的类型。 + /// 是否存在数据表。 + bool HasDataTable(Type dataRowType); + + /// + /// 是否存在数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 是否存在数据表。 + bool HasDataTable(string name) where T : IDataRow; + + /// + /// 是否存在数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 是否存在数据表。 + bool HasDataTable(Type dataRowType, string name); + + /// + /// 获取数据表。 + /// + /// 数据表行的类型。 + /// 要获取的数据表。 + IDataTable GetDataTable() where T : IDataRow; + + /// + /// 获取数据表。 + /// + /// 数据表行的类型。 + /// 要获取的数据表。 + DataTableBase GetDataTable(Type dataRowType); + + /// + /// 获取数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 要获取的数据表。 + IDataTable GetDataTable(string name) where T : IDataRow; + + /// + /// 获取数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 要获取的数据表。 + DataTableBase GetDataTable(Type dataRowType, string name); + + /// + /// 获取所有数据表。 + /// + /// 所有数据表。 + DataTableBase[] GetAllDataTables(); + + /// + /// 获取所有数据表。 + /// + /// 所有数据表。 + void GetAllDataTables(List results); + + /// + /// 创建数据表。 + /// + /// 数据表行的类型。 + /// 要创建的数据表。 + IDataTable CreateDataTable() where T : class, IDataRow, new(); + + /// + /// 创建数据表。 + /// + /// 数据表行的类型。 + /// 要创建的数据表。 + DataTableBase CreateDataTable(Type dataRowType); + + /// + /// 创建数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 要创建的数据表。 + IDataTable CreateDataTable(string name) where T : class, IDataRow, new(); + + /// + /// 创建数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 要创建的数据表。 + DataTableBase CreateDataTable(Type dataRowType, string name); + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 是否销毁数据表成功。 + bool DestroyDataTable() where T : IDataRow; + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 是否销毁数据表成功。 + bool DestroyDataTable(Type dataRowType); + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 是否销毁数据表成功。 + bool DestroyDataTable(string name) where T : IDataRow; + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 是否销毁数据表成功。 + bool DestroyDataTable(Type dataRowType, string name); + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 要销毁的数据表。 + /// 是否销毁数据表成功。 + bool DestroyDataTable(IDataTable dataTable) where T : IDataRow; + + /// + /// 销毁数据表。 + /// + /// 要销毁的数据表。 + /// 是否销毁数据表成功。 + bool DestroyDataTable(DataTableBase dataTable); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTableManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTableManager.cs.meta new file mode 100644 index 0000000..5c59aa9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/DataTable/IDataTableManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ecbc6fe55b71f0c46b2bb6fe1098272c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger.meta new file mode 100644 index 0000000..e85519a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 277c75425b5a43c4d8d51dcb0a25625f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/DebuggerManager.DebuggerWindowGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/DebuggerManager.DebuggerWindowGroup.cs new file mode 100644 index 0000000..1364f91 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/DebuggerManager.DebuggerWindowGroup.cs @@ -0,0 +1,307 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.Debugger +{ + internal sealed partial class DebuggerManager : GameFrameworkModule, IDebuggerManager + { + /// + /// 调试器窗口组。 + /// + private sealed class DebuggerWindowGroup : IDebuggerWindowGroup + { + private readonly List> m_DebuggerWindows; + private int m_SelectedIndex; + private string[] m_DebuggerWindowNames; + + public DebuggerWindowGroup() + { + m_DebuggerWindows = new List>(); + m_SelectedIndex = 0; + m_DebuggerWindowNames = null; + } + + /// + /// 获取调试器窗口数量。 + /// + public int DebuggerWindowCount + { + get + { + return m_DebuggerWindows.Count; + } + } + + /// + /// 获取或设置当前选中的调试器窗口索引。 + /// + public int SelectedIndex + { + get + { + return m_SelectedIndex; + } + set + { + m_SelectedIndex = value; + } + } + + /// + /// 获取当前选中的调试器窗口。 + /// + public IDebuggerWindow SelectedWindow + { + get + { + if (m_SelectedIndex >= m_DebuggerWindows.Count) + { + return null; + } + + return m_DebuggerWindows[m_SelectedIndex].Value; + } + } + + /// + /// 初始化调试组。 + /// + /// 初始化调试组参数。 + public void Initialize(params object[] args) + { + } + + /// + /// 关闭调试组。 + /// + public void Shutdown() + { + foreach (KeyValuePair debuggerWindow in m_DebuggerWindows) + { + debuggerWindow.Value.Shutdown(); + } + + m_DebuggerWindows.Clear(); + } + + /// + /// 进入调试器窗口。 + /// + public void OnEnter() + { + SelectedWindow.OnEnter(); + } + + /// + /// 离开调试器窗口。 + /// + public void OnLeave() + { + SelectedWindow.OnLeave(); + } + + /// + /// 调试组轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + SelectedWindow.OnUpdate(elapseSeconds, realElapseSeconds); + } + + /// + /// 调试器窗口绘制。 + /// + public void OnDraw() + { + } + + private void RefreshDebuggerWindowNames() + { + int index = 0; + m_DebuggerWindowNames = new string[m_DebuggerWindows.Count]; + foreach (KeyValuePair debuggerWindow in m_DebuggerWindows) + { + m_DebuggerWindowNames[index++] = debuggerWindow.Key; + } + } + + /// + /// 获取调试组的调试器窗口名称集合。 + /// + public string[] GetDebuggerWindowNames() + { + return m_DebuggerWindowNames; + } + + /// + /// 获取调试器窗口。 + /// + /// 调试器窗口路径。 + /// 要获取的调试器窗口。 + public IDebuggerWindow GetDebuggerWindow(string path) + { + if (string.IsNullOrEmpty(path)) + { + return null; + } + + int pos = path.IndexOf('/'); + if (pos < 0 || pos >= path.Length - 1) + { + return InternalGetDebuggerWindow(path); + } + + string debuggerWindowGroupName = path.Substring(0, pos); + string leftPath = path.Substring(pos + 1); + DebuggerWindowGroup debuggerWindowGroup = (DebuggerWindowGroup)InternalGetDebuggerWindow(debuggerWindowGroupName); + if (debuggerWindowGroup == null) + { + return null; + } + + return debuggerWindowGroup.GetDebuggerWindow(leftPath); + } + + /// + /// 选中调试器窗口。 + /// + /// 调试器窗口路径。 + /// 是否成功选中调试器窗口。 + public bool SelectDebuggerWindow(string path) + { + if (string.IsNullOrEmpty(path)) + { + return false; + } + + int pos = path.IndexOf('/'); + if (pos < 0 || pos >= path.Length - 1) + { + return InternalSelectDebuggerWindow(path); + } + + string debuggerWindowGroupName = path.Substring(0, pos); + string leftPath = path.Substring(pos + 1); + DebuggerWindowGroup debuggerWindowGroup = (DebuggerWindowGroup)InternalGetDebuggerWindow(debuggerWindowGroupName); + if (debuggerWindowGroup == null || !InternalSelectDebuggerWindow(debuggerWindowGroupName)) + { + return false; + } + + return debuggerWindowGroup.SelectDebuggerWindow(leftPath); + } + + /// + /// 注册调试器窗口。 + /// + /// 调试器窗口路径。 + /// 要注册的调试器窗口。 + public void RegisterDebuggerWindow(string path, IDebuggerWindow debuggerWindow) + { + if (string.IsNullOrEmpty(path)) + { + throw new GameFrameworkException("Path is invalid."); + } + + int pos = path.IndexOf('/'); + if (pos < 0 || pos >= path.Length - 1) + { + if (InternalGetDebuggerWindow(path) != null) + { + throw new GameFrameworkException("Debugger window has been registered."); + } + + m_DebuggerWindows.Add(new KeyValuePair(path, debuggerWindow)); + RefreshDebuggerWindowNames(); + } + else + { + string debuggerWindowGroupName = path.Substring(0, pos); + string leftPath = path.Substring(pos + 1); + DebuggerWindowGroup debuggerWindowGroup = (DebuggerWindowGroup)InternalGetDebuggerWindow(debuggerWindowGroupName); + if (debuggerWindowGroup == null) + { + if (InternalGetDebuggerWindow(debuggerWindowGroupName) != null) + { + throw new GameFrameworkException("Debugger window has been registered, can not create debugger window group."); + } + + debuggerWindowGroup = new DebuggerWindowGroup(); + m_DebuggerWindows.Add(new KeyValuePair(debuggerWindowGroupName, debuggerWindowGroup)); + RefreshDebuggerWindowNames(); + } + + debuggerWindowGroup.RegisterDebuggerWindow(leftPath, debuggerWindow); + } + } + + /// + /// 解除注册调试器窗口。 + /// + /// 调试器窗口路径。 + /// 是否解除注册调试器窗口成功。 + public bool UnregisterDebuggerWindow(string path) + { + if (string.IsNullOrEmpty(path)) + { + return false; + } + + int pos = path.IndexOf('/'); + if (pos < 0 || pos >= path.Length - 1) + { + IDebuggerWindow debuggerWindow = InternalGetDebuggerWindow(path); + bool result = m_DebuggerWindows.Remove(new KeyValuePair(path, debuggerWindow)); + debuggerWindow.Shutdown(); + RefreshDebuggerWindowNames(); + return result; + } + + string debuggerWindowGroupName = path.Substring(0, pos); + string leftPath = path.Substring(pos + 1); + DebuggerWindowGroup debuggerWindowGroup = (DebuggerWindowGroup)InternalGetDebuggerWindow(debuggerWindowGroupName); + if (debuggerWindowGroup == null) + { + return false; + } + + return debuggerWindowGroup.UnregisterDebuggerWindow(leftPath); + } + + private IDebuggerWindow InternalGetDebuggerWindow(string name) + { + foreach (KeyValuePair debuggerWindow in m_DebuggerWindows) + { + if (debuggerWindow.Key == name) + { + return debuggerWindow.Value; + } + } + + return null; + } + + private bool InternalSelectDebuggerWindow(string name) + { + for (int i = 0; i < m_DebuggerWindows.Count; i++) + { + if (m_DebuggerWindows[i].Key == name) + { + m_SelectedIndex = i; + return true; + } + } + + return false; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/DebuggerManager.DebuggerWindowGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/DebuggerManager.DebuggerWindowGroup.cs.meta new file mode 100644 index 0000000..20ba25a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/DebuggerManager.DebuggerWindowGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f885a6c2dc9abf746ae25168560f2f96 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/DebuggerManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/DebuggerManager.cs new file mode 100644 index 0000000..5623ce4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/DebuggerManager.cs @@ -0,0 +1,141 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Debugger +{ + /// + /// 调试器管理器。 + /// + internal sealed partial class DebuggerManager : GameFrameworkModule, IDebuggerManager + { + private readonly DebuggerWindowGroup m_DebuggerWindowRoot; + private bool m_ActiveWindow; + + /// + /// 初始化调试器管理器的新实例。 + /// + public DebuggerManager() + { + m_DebuggerWindowRoot = new DebuggerWindowGroup(); + m_ActiveWindow = false; + } + + /// + /// 获取游戏框架模块优先级。 + /// + /// 优先级较高的模块会优先轮询,并且关闭操作会后进行。 + internal override int Priority + { + get + { + return -1; + } + } + + /// + /// 获取或设置调试器窗口是否激活。 + /// + public bool ActiveWindow + { + get + { + return m_ActiveWindow; + } + set + { + m_ActiveWindow = value; + } + } + + /// + /// 调试器窗口根结点。 + /// + public IDebuggerWindowGroup DebuggerWindowRoot + { + get + { + return m_DebuggerWindowRoot; + } + } + + /// + /// 调试器管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + if (!m_ActiveWindow) + { + return; + } + + m_DebuggerWindowRoot.OnUpdate(elapseSeconds, realElapseSeconds); + } + + /// + /// 关闭并清理调试器管理器。 + /// + internal override void Shutdown() + { + m_ActiveWindow = false; + m_DebuggerWindowRoot.Shutdown(); + } + + /// + /// 注册调试器窗口。 + /// + /// 调试器窗口路径。 + /// 要注册的调试器窗口。 + /// 初始化调试器窗口参数。 + public void RegisterDebuggerWindow(string path, IDebuggerWindow debuggerWindow, params object[] args) + { + if (string.IsNullOrEmpty(path)) + { + throw new GameFrameworkException("Path is invalid."); + } + + if (debuggerWindow == null) + { + throw new GameFrameworkException("Debugger window is invalid."); + } + + m_DebuggerWindowRoot.RegisterDebuggerWindow(path, debuggerWindow); + debuggerWindow.Initialize(args); + } + + /// + /// 解除注册调试器窗口。 + /// + /// 调试器窗口路径。 + /// 是否解除注册调试器窗口成功。 + public bool UnregisterDebuggerWindow(string path) + { + return m_DebuggerWindowRoot.UnregisterDebuggerWindow(path); + } + + /// + /// 获取调试器窗口。 + /// + /// 调试器窗口路径。 + /// 要获取的调试器窗口。 + public IDebuggerWindow GetDebuggerWindow(string path) + { + return m_DebuggerWindowRoot.GetDebuggerWindow(path); + } + + /// + /// 选中调试器窗口。 + /// + /// 调试器窗口路径。 + /// 是否成功选中调试器窗口。 + public bool SelectDebuggerWindow(string path) + { + return m_DebuggerWindowRoot.SelectDebuggerWindow(path); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/DebuggerManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/DebuggerManager.cs.meta new file mode 100644 index 0000000..a67b1e1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/DebuggerManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 712e8a50a70e3c242a658f450cdc15f6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerManager.cs new file mode 100644 index 0000000..e3cdf76 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerManager.cs @@ -0,0 +1,61 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Debugger +{ + /// + /// 调试器管理器接口。 + /// + public interface IDebuggerManager + { + /// + /// 获取或设置调试器窗口是否激活。 + /// + bool ActiveWindow + { + get; + set; + } + + /// + /// 调试器窗口根结点。 + /// + IDebuggerWindowGroup DebuggerWindowRoot + { + get; + } + + /// + /// 注册调试器窗口。 + /// + /// 调试器窗口路径。 + /// 要注册的调试器窗口。 + /// 初始化调试器窗口参数。 + void RegisterDebuggerWindow(string path, IDebuggerWindow debuggerWindow, params object[] args); + + /// + /// 解除注册调试器窗口。 + /// + /// 调试器窗口路径。 + /// 是否解除注册调试器窗口成功。 + bool UnregisterDebuggerWindow(string path); + + /// + /// 获取调试器窗口。 + /// + /// 调试器窗口路径。 + /// 要获取的调试器窗口。 + IDebuggerWindow GetDebuggerWindow(string path); + + /// + /// 选中调试器窗口。 + /// + /// 调试器窗口路径。 + /// 是否成功选中调试器窗口。 + bool SelectDebuggerWindow(string path); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerManager.cs.meta new file mode 100644 index 0000000..bf58293 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 56d979b74c2020c4ea642480c660e235 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerWindow.cs new file mode 100644 index 0000000..5ac5525 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerWindow.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Debugger +{ + /// + /// 调试器窗口接口。 + /// + public interface IDebuggerWindow + { + /// + /// 初始化调试器窗口。 + /// + /// 初始化调试器窗口参数。 + void Initialize(params object[] args); + + /// + /// 关闭调试器窗口。 + /// + void Shutdown(); + + /// + /// 进入调试器窗口。 + /// + void OnEnter(); + + /// + /// 离开调试器窗口。 + /// + void OnLeave(); + + /// + /// 调试器窗口轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + void OnUpdate(float elapseSeconds, float realElapseSeconds); + + /// + /// 调试器窗口绘制。 + /// + void OnDraw(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerWindow.cs.meta new file mode 100644 index 0000000..6746c20 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c39cf770217b9734e84af0b3356920ff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerWindowGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerWindowGroup.cs new file mode 100644 index 0000000..d5d5a7f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerWindowGroup.cs @@ -0,0 +1,59 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Debugger +{ + /// + /// 调试器窗口组接口。 + /// + public interface IDebuggerWindowGroup : IDebuggerWindow + { + /// + /// 获取调试器窗口数量。 + /// + int DebuggerWindowCount + { + get; + } + + /// + /// 获取或设置当前选中的调试器窗口索引。 + /// + int SelectedIndex + { + get; + set; + } + + /// + /// 获取当前选中的调试器窗口。 + /// + IDebuggerWindow SelectedWindow + { + get; + } + + /// + /// 获取调试组的调试器窗口名称集合。 + /// + string[] GetDebuggerWindowNames(); + + /// + /// 获取调试器窗口。 + /// + /// 调试器窗口路径。 + /// 要获取的调试器窗口。 + IDebuggerWindow GetDebuggerWindow(string path); + + /// + /// 注册调试器窗口。 + /// + /// 调试器窗口路径。 + /// 要注册的调试器窗口。 + void RegisterDebuggerWindow(string path, IDebuggerWindow debuggerWindow); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerWindowGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerWindowGroup.cs.meta new file mode 100644 index 0000000..6b00163 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Debugger/IDebuggerWindowGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: acf16bd9312153e48a3e5137ac884cd0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download.meta new file mode 100644 index 0000000..79a4f57 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7f4de3cf9ebe31c479054c7fa840e09d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/Constant.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/Constant.cs new file mode 100644 index 0000000..63b6014 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/Constant.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + /// + /// 下载相关常量。 + /// + internal static class Constant + { + /// + /// 默认下载任务优先级。 + /// + internal const int DefaultPriority = 0; + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/Constant.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/Constant.cs.meta new file mode 100644 index 0000000..743db2f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/Constant.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1613a12eaab20454fb34c6f128cbef1c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperCompleteEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperCompleteEventArgs.cs new file mode 100644 index 0000000..3eb674d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperCompleteEventArgs.cs @@ -0,0 +1,57 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + /// + /// 下载代理辅助器完成事件。 + /// + public sealed class DownloadAgentHelperCompleteEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化下载代理辅助器完成事件的新实例。 + /// + public DownloadAgentHelperCompleteEventArgs() + { + Length = 0L; + } + + /// + /// 获取下载的数据大小。 + /// + public long Length + { + get; + private set; + } + + /// + /// 创建下载代理辅助器完成事件。 + /// + /// 下载的数据大小。 + /// 创建的下载代理辅助器完成事件。 + public static DownloadAgentHelperCompleteEventArgs Create(long length) + { + if (length < 0L) + { + throw new GameFrameworkException("Length is invalid."); + } + + DownloadAgentHelperCompleteEventArgs downloadAgentHelperCompleteEventArgs = ReferencePool.Acquire(); + downloadAgentHelperCompleteEventArgs.Length = length; + return downloadAgentHelperCompleteEventArgs; + } + + /// + /// 清理下载代理辅助器完成事件。 + /// + public override void Clear() + { + Length = 0L; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperCompleteEventArgs.cs.meta new file mode 100644 index 0000000..019e176 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperCompleteEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4076433d439b2ed46a338187582b69b4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperErrorEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperErrorEventArgs.cs new file mode 100644 index 0000000..36d2813 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperErrorEventArgs.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + /// + /// 下载代理辅助器错误事件。 + /// + public sealed class DownloadAgentHelperErrorEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化下载代理辅助器错误事件的新实例。 + /// + public DownloadAgentHelperErrorEventArgs() + { + DeleteDownloading = false; + ErrorMessage = null; + } + + /// + /// 获取是否需要删除正在下载的文件。 + /// + public bool DeleteDownloading + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 创建下载代理辅助器错误事件。 + /// + /// 是否需要删除正在下载的文件。 + /// 错误信息。 + /// 创建的下载代理辅助器错误事件。 + public static DownloadAgentHelperErrorEventArgs Create(bool deleteDownloading, string errorMessage) + { + DownloadAgentHelperErrorEventArgs downloadAgentHelperErrorEventArgs = ReferencePool.Acquire(); + downloadAgentHelperErrorEventArgs.DeleteDownloading = deleteDownloading; + downloadAgentHelperErrorEventArgs.ErrorMessage = errorMessage; + return downloadAgentHelperErrorEventArgs; + } + + /// + /// 清理下载代理辅助器错误事件。 + /// + public override void Clear() + { + DeleteDownloading = false; + ErrorMessage = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperErrorEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperErrorEventArgs.cs.meta new file mode 100644 index 0000000..c9c0c67 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperErrorEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1b96229b98c9a8642951214489743187 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperUpdateBytesEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperUpdateBytesEventArgs.cs new file mode 100644 index 0000000..3b8f4cc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperUpdateBytesEventArgs.cs @@ -0,0 +1,94 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + /// + /// 下载代理辅助器更新数据流事件。 + /// + public sealed class DownloadAgentHelperUpdateBytesEventArgs : GameFrameworkEventArgs + { + private byte[] m_Bytes; + + /// + /// 初始化下载代理辅助器更新数据流事件的新实例。 + /// + public DownloadAgentHelperUpdateBytesEventArgs() + { + m_Bytes = null; + Offset = 0; + Length = 0; + } + + /// + /// 获取数据流的偏移。 + /// + public int Offset + { + get; + private set; + } + + /// + /// 获取数据流的长度。 + /// + public int Length + { + get; + private set; + } + + /// + /// 创建下载代理辅助器更新数据流事件。 + /// + /// 下载的数据流。 + /// 数据流的偏移。 + /// 数据流的长度。 + /// 创建的下载代理辅助器更新数据流事件。 + public static DownloadAgentHelperUpdateBytesEventArgs Create(byte[] bytes, int offset, int length) + { + if (bytes == null) + { + throw new GameFrameworkException("Bytes is invalid."); + } + + if (offset < 0 || offset >= bytes.Length) + { + throw new GameFrameworkException("Offset is invalid."); + } + + if (length <= 0 || offset + length > bytes.Length) + { + throw new GameFrameworkException("Length is invalid."); + } + + DownloadAgentHelperUpdateBytesEventArgs downloadAgentHelperUpdateBytesEventArgs = ReferencePool.Acquire(); + downloadAgentHelperUpdateBytesEventArgs.m_Bytes = bytes; + downloadAgentHelperUpdateBytesEventArgs.Offset = offset; + downloadAgentHelperUpdateBytesEventArgs.Length = length; + return downloadAgentHelperUpdateBytesEventArgs; + } + + /// + /// 清理下载代理辅助器更新数据流事件。 + /// + public override void Clear() + { + m_Bytes = null; + Offset = 0; + Length = 0; + } + + /// + /// 获取下载的数据流。 + /// + public byte[] GetBytes() + { + return m_Bytes; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperUpdateBytesEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperUpdateBytesEventArgs.cs.meta new file mode 100644 index 0000000..3a45f45 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperUpdateBytesEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 383456b63d366464a98963b63bd40c08 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperUpdateLengthEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperUpdateLengthEventArgs.cs new file mode 100644 index 0000000..176c7e8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperUpdateLengthEventArgs.cs @@ -0,0 +1,57 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + /// + /// 下载代理辅助器更新数据大小事件。 + /// + public sealed class DownloadAgentHelperUpdateLengthEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化下载代理辅助器更新数据大小事件的新实例。 + /// + public DownloadAgentHelperUpdateLengthEventArgs() + { + DeltaLength = 0; + } + + /// + /// 获取下载的增量数据大小。 + /// + public int DeltaLength + { + get; + private set; + } + + /// + /// 创建下载代理辅助器更新数据大小事件。 + /// + /// 下载的增量数据大小。 + /// 创建的下载代理辅助器更新数据大小事件。 + public static DownloadAgentHelperUpdateLengthEventArgs Create(int deltaLength) + { + if (deltaLength <= 0) + { + throw new GameFrameworkException("Delta length is invalid."); + } + + DownloadAgentHelperUpdateLengthEventArgs downloadAgentHelperUpdateLengthEventArgs = ReferencePool.Acquire(); + downloadAgentHelperUpdateLengthEventArgs.DeltaLength = deltaLength; + return downloadAgentHelperUpdateLengthEventArgs; + } + + /// + /// 清理下载代理辅助器更新数据大小事件。 + /// + public override void Clear() + { + DeltaLength = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperUpdateLengthEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperUpdateLengthEventArgs.cs.meta new file mode 100644 index 0000000..201fd77 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadAgentHelperUpdateLengthEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 30e54e8d574e7024e826f011ba4aec70 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadFailureEventArgs.cs new file mode 100644 index 0000000..b552323 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadFailureEventArgs.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + /// + /// 下载失败事件。 + /// + public sealed class DownloadFailureEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化下载失败事件的新实例。 + /// + public DownloadFailureEventArgs() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取下载任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建下载失败事件。 + /// + /// 下载任务的序列编号。 + /// 下载后存放路径。 + /// 下载地址。 + /// 错误信息。 + /// 用户自定义数据。 + /// 创建的下载失败事件。 + public static DownloadFailureEventArgs Create(int serialId, string downloadPath, string downloadUri, string errorMessage, object userData) + { + DownloadFailureEventArgs downloadFailureEventArgs = ReferencePool.Acquire(); + downloadFailureEventArgs.SerialId = serialId; + downloadFailureEventArgs.DownloadPath = downloadPath; + downloadFailureEventArgs.DownloadUri = downloadUri; + downloadFailureEventArgs.ErrorMessage = errorMessage; + downloadFailureEventArgs.UserData = userData; + return downloadFailureEventArgs; + } + + /// + /// 清理下载失败事件。 + /// + public override void Clear() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadFailureEventArgs.cs.meta new file mode 100644 index 0000000..931b32d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a834668a21a639a45a85ae08c302bb82 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadAgent.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadAgent.cs new file mode 100644 index 0000000..20a38ba --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadAgent.cs @@ -0,0 +1,375 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.IO; + +namespace GameFramework.Download +{ + internal sealed partial class DownloadManager : GameFrameworkModule, IDownloadManager + { + /// + /// 下载代理。 + /// + private sealed class DownloadAgent : ITaskAgent, IDisposable + { + private readonly IDownloadAgentHelper m_Helper; + private DownloadTask m_Task; + private FileStream m_FileStream; + private int m_WaitFlushSize; + private float m_WaitTime; + private long m_StartLength; + private long m_DownloadedLength; + private long m_SavedLength; + private bool m_Disposed; + + public GameFrameworkAction DownloadAgentStart; + public GameFrameworkAction DownloadAgentUpdate; + public GameFrameworkAction DownloadAgentSuccess; + public GameFrameworkAction DownloadAgentFailure; + + /// + /// 初始化下载代理的新实例。 + /// + /// 下载代理辅助器。 + public DownloadAgent(IDownloadAgentHelper downloadAgentHelper) + { + if (downloadAgentHelper == null) + { + throw new GameFrameworkException("Download agent helper is invalid."); + } + + m_Helper = downloadAgentHelper; + m_Task = null; + m_FileStream = null; + m_WaitFlushSize = 0; + m_WaitTime = 0f; + m_StartLength = 0L; + m_DownloadedLength = 0L; + m_SavedLength = 0L; + m_Disposed = false; + + DownloadAgentStart = null; + DownloadAgentUpdate = null; + DownloadAgentSuccess = null; + DownloadAgentFailure = null; + } + + /// + /// 获取下载任务。 + /// + public DownloadTask Task + { + get + { + return m_Task; + } + } + + /// + /// 获取已经等待时间。 + /// + public float WaitTime + { + get + { + return m_WaitTime; + } + } + + /// + /// 获取开始下载时已经存在的大小。 + /// + public long StartLength + { + get + { + return m_StartLength; + } + } + + /// + /// 获取本次已经下载的大小。 + /// + public long DownloadedLength + { + get + { + return m_DownloadedLength; + } + } + + /// + /// 获取当前的大小。 + /// + public long CurrentLength + { + get + { + return m_StartLength + m_DownloadedLength; + } + } + + /// + /// 获取已经存盘的大小。 + /// + public long SavedLength + { + get + { + return m_SavedLength; + } + } + + /// + /// 初始化下载代理。 + /// + public void Initialize() + { + m_Helper.DownloadAgentHelperUpdateBytes += OnDownloadAgentHelperUpdateBytes; + m_Helper.DownloadAgentHelperUpdateLength += OnDownloadAgentHelperUpdateLength; + m_Helper.DownloadAgentHelperComplete += OnDownloadAgentHelperComplete; + m_Helper.DownloadAgentHelperError += OnDownloadAgentHelperError; + } + + /// + /// 下载代理轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void Update(float elapseSeconds, float realElapseSeconds) + { + if (m_Task.Status == DownloadTaskStatus.Doing) + { + m_WaitTime += realElapseSeconds; + if (m_WaitTime >= m_Task.Timeout) + { + DownloadAgentHelperErrorEventArgs downloadAgentHelperErrorEventArgs = DownloadAgentHelperErrorEventArgs.Create(false, "Timeout"); + OnDownloadAgentHelperError(this, downloadAgentHelperErrorEventArgs); + ReferencePool.Release(downloadAgentHelperErrorEventArgs); + } + } + } + + /// + /// 关闭并清理下载代理。 + /// + public void Shutdown() + { + Dispose(); + + m_Helper.DownloadAgentHelperUpdateBytes -= OnDownloadAgentHelperUpdateBytes; + m_Helper.DownloadAgentHelperUpdateLength -= OnDownloadAgentHelperUpdateLength; + m_Helper.DownloadAgentHelperComplete -= OnDownloadAgentHelperComplete; + m_Helper.DownloadAgentHelperError -= OnDownloadAgentHelperError; + } + + /// + /// 开始处理下载任务。 + /// + /// 要处理的下载任务。 + /// 开始处理任务的状态。 + public StartTaskStatus Start(DownloadTask task) + { + if (task == null) + { + throw new GameFrameworkException("Task is invalid."); + } + + m_Task = task; + + m_Task.Status = DownloadTaskStatus.Doing; + string downloadFile = Utility.Text.Format("{0}.download", m_Task.DownloadPath); + + try + { + if (File.Exists(downloadFile)) + { + m_FileStream = File.OpenWrite(downloadFile); + m_FileStream.Seek(0L, SeekOrigin.End); + m_StartLength = m_SavedLength = m_FileStream.Length; + m_DownloadedLength = 0L; + } + else + { + string directory = Path.GetDirectoryName(m_Task.DownloadPath); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + m_FileStream = new FileStream(downloadFile, FileMode.Create, FileAccess.Write); + m_StartLength = m_SavedLength = m_DownloadedLength = 0L; + } + + if (DownloadAgentStart != null) + { + DownloadAgentStart(this); + } + + if (m_StartLength > 0L) + { + m_Helper.Download(m_Task.DownloadUri, m_StartLength, m_Task.UserData); + } + else + { + m_Helper.Download(m_Task.DownloadUri, m_Task.UserData); + } + + return StartTaskStatus.CanResume; + } + catch (Exception exception) + { + DownloadAgentHelperErrorEventArgs downloadAgentHelperErrorEventArgs = DownloadAgentHelperErrorEventArgs.Create(false, exception.ToString()); + OnDownloadAgentHelperError(this, downloadAgentHelperErrorEventArgs); + ReferencePool.Release(downloadAgentHelperErrorEventArgs); + return StartTaskStatus.UnknownError; + } + } + + /// + /// 重置下载代理。 + /// + public void Reset() + { + m_Helper.Reset(); + + if (m_FileStream != null) + { + m_FileStream.Close(); + m_FileStream = null; + } + + m_Task = null; + m_WaitFlushSize = 0; + m_WaitTime = 0f; + m_StartLength = 0L; + m_DownloadedLength = 0L; + m_SavedLength = 0L; + } + + /// + /// 释放资源。 + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// 释放资源。 + /// + /// 释放资源标记。 + private void Dispose(bool disposing) + { + if (m_Disposed) + { + return; + } + + if (disposing) + { + if (m_FileStream != null) + { + m_FileStream.Dispose(); + m_FileStream = null; + } + } + + m_Disposed = true; + } + + private void OnDownloadAgentHelperUpdateBytes(object sender, DownloadAgentHelperUpdateBytesEventArgs e) + { + m_WaitTime = 0f; + try + { + m_FileStream.Write(e.GetBytes(), e.Offset, e.Length); + m_WaitFlushSize += e.Length; + m_SavedLength += e.Length; + + if (m_WaitFlushSize >= m_Task.FlushSize) + { + m_FileStream.Flush(); + m_WaitFlushSize = 0; + } + } + catch (Exception exception) + { + DownloadAgentHelperErrorEventArgs downloadAgentHelperErrorEventArgs = DownloadAgentHelperErrorEventArgs.Create(false, exception.ToString()); + OnDownloadAgentHelperError(this, downloadAgentHelperErrorEventArgs); + ReferencePool.Release(downloadAgentHelperErrorEventArgs); + } + } + + private void OnDownloadAgentHelperUpdateLength(object sender, DownloadAgentHelperUpdateLengthEventArgs e) + { + m_WaitTime = 0f; + m_DownloadedLength += e.DeltaLength; + if (DownloadAgentUpdate != null) + { + DownloadAgentUpdate(this, e.DeltaLength); + } + } + + private void OnDownloadAgentHelperComplete(object sender, DownloadAgentHelperCompleteEventArgs e) + { + m_WaitTime = 0f; + m_DownloadedLength = e.Length; + if (m_SavedLength != CurrentLength) + { + throw new GameFrameworkException("Internal download error."); + } + + m_Helper.Reset(); + m_FileStream.Close(); + m_FileStream = null; + + if (File.Exists(m_Task.DownloadPath)) + { + File.Delete(m_Task.DownloadPath); + } + + File.Move(Utility.Text.Format("{0}.download", m_Task.DownloadPath), m_Task.DownloadPath); + + m_Task.Status = DownloadTaskStatus.Done; + + if (DownloadAgentSuccess != null) + { + DownloadAgentSuccess(this, e.Length); + } + + m_Task.Done = true; + } + + private void OnDownloadAgentHelperError(object sender, DownloadAgentHelperErrorEventArgs e) + { + m_Helper.Reset(); + if (m_FileStream != null) + { + m_FileStream.Close(); + m_FileStream = null; + } + + if (e.DeleteDownloading) + { + File.Delete(Utility.Text.Format("{0}.download", m_Task.DownloadPath)); + } + + m_Task.Status = DownloadTaskStatus.Error; + + if (DownloadAgentFailure != null) + { + DownloadAgentFailure(this, e.ErrorMessage); + } + + m_Task.Done = true; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadAgent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadAgent.cs.meta new file mode 100644 index 0000000..2af1410 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadAgent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 013518044dc160b41b342c3a993517ef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadCounter.DownloadCounterNode.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadCounter.DownloadCounterNode.cs new file mode 100644 index 0000000..779f1d0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadCounter.DownloadCounterNode.cs @@ -0,0 +1,64 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + internal sealed partial class DownloadManager : GameFrameworkModule, IDownloadManager + { + private sealed partial class DownloadCounter + { + private sealed class DownloadCounterNode : IReference + { + private long m_DeltaLength; + private float m_ElapseSeconds; + + public DownloadCounterNode() + { + m_DeltaLength = 0L; + m_ElapseSeconds = 0f; + } + + public long DeltaLength + { + get + { + return m_DeltaLength; + } + } + + public float ElapseSeconds + { + get + { + return m_ElapseSeconds; + } + } + + public static DownloadCounterNode Create() + { + return ReferencePool.Acquire(); + } + + public void Update(float elapseSeconds, float realElapseSeconds) + { + m_ElapseSeconds += realElapseSeconds; + } + + public void AddDeltaLength(int deltaLength) + { + m_DeltaLength += deltaLength; + } + + public void Clear() + { + m_DeltaLength = 0L; + m_ElapseSeconds = 0f; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadCounter.DownloadCounterNode.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadCounter.DownloadCounterNode.cs.meta new file mode 100644 index 0000000..b458589 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadCounter.DownloadCounterNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aa316d09b8ad05240a66d6172936916a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadCounter.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadCounter.cs new file mode 100644 index 0000000..dfc9b09 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadCounter.cs @@ -0,0 +1,170 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + internal sealed partial class DownloadManager : GameFrameworkModule, IDownloadManager + { + private sealed partial class DownloadCounter + { + private readonly GameFrameworkLinkedList m_DownloadCounterNodes; + private float m_UpdateInterval; + private float m_RecordInterval; + private float m_CurrentSpeed; + private float m_Accumulator; + private float m_TimeLeft; + + public DownloadCounter(float updateInterval, float recordInterval) + { + if (updateInterval <= 0f) + { + throw new GameFrameworkException("Update interval is invalid."); + } + + if (recordInterval <= 0f) + { + throw new GameFrameworkException("Record interval is invalid."); + } + + m_DownloadCounterNodes = new GameFrameworkLinkedList(); + m_UpdateInterval = updateInterval; + m_RecordInterval = recordInterval; + Reset(); + } + + public float UpdateInterval + { + get + { + return m_UpdateInterval; + } + set + { + if (value <= 0f) + { + throw new GameFrameworkException("Update interval is invalid."); + } + + m_UpdateInterval = value; + Reset(); + } + } + + public float RecordInterval + { + get + { + return m_RecordInterval; + } + set + { + if (value <= 0f) + { + throw new GameFrameworkException("Record interval is invalid."); + } + + m_RecordInterval = value; + Reset(); + } + } + + public float CurrentSpeed + { + get + { + return m_CurrentSpeed; + } + } + + public void Shutdown() + { + Reset(); + } + + public void Update(float elapseSeconds, float realElapseSeconds) + { + if (m_DownloadCounterNodes.Count <= 0) + { + return; + } + + m_Accumulator += realElapseSeconds; + if (m_Accumulator > m_RecordInterval) + { + m_Accumulator = m_RecordInterval; + } + + m_TimeLeft -= realElapseSeconds; + foreach (DownloadCounterNode downloadCounterNode in m_DownloadCounterNodes) + { + downloadCounterNode.Update(elapseSeconds, realElapseSeconds); + } + + while (m_DownloadCounterNodes.Count > 0) + { + DownloadCounterNode downloadCounterNode = m_DownloadCounterNodes.First.Value; + if (downloadCounterNode.ElapseSeconds < m_RecordInterval) + { + break; + } + + ReferencePool.Release(downloadCounterNode); + m_DownloadCounterNodes.RemoveFirst(); + } + + if (m_DownloadCounterNodes.Count <= 0) + { + Reset(); + return; + } + + if (m_TimeLeft <= 0f) + { + long totalDeltaLength = 0L; + foreach (DownloadCounterNode downloadCounterNode in m_DownloadCounterNodes) + { + totalDeltaLength += downloadCounterNode.DeltaLength; + } + + m_CurrentSpeed = m_Accumulator > 0f ? totalDeltaLength / m_Accumulator : 0f; + m_TimeLeft += m_UpdateInterval; + } + } + + public void RecordDeltaLength(int deltaLength) + { + if (deltaLength <= 0) + { + return; + } + + DownloadCounterNode downloadCounterNode = null; + if (m_DownloadCounterNodes.Count > 0) + { + downloadCounterNode = m_DownloadCounterNodes.Last.Value; + if (downloadCounterNode.ElapseSeconds < m_UpdateInterval) + { + downloadCounterNode.AddDeltaLength(deltaLength); + return; + } + } + + downloadCounterNode = DownloadCounterNode.Create(); + downloadCounterNode.AddDeltaLength(deltaLength); + m_DownloadCounterNodes.AddLast(downloadCounterNode); + } + + private void Reset() + { + m_DownloadCounterNodes.Clear(); + m_CurrentSpeed = 0f; + m_Accumulator = 0f; + m_TimeLeft = 0f; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadCounter.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadCounter.cs.meta new file mode 100644 index 0000000..9283035 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadCounter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 666e073ec8292f24397719575dbd310f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadTask.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadTask.cs new file mode 100644 index 0000000..0132b28 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadTask.cs @@ -0,0 +1,143 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + internal sealed partial class DownloadManager : GameFrameworkModule, IDownloadManager + { + /// + /// 下载任务。 + /// + private sealed class DownloadTask : TaskBase + { + private static int s_Serial = 0; + + private DownloadTaskStatus m_Status; + private string m_DownloadPath; + private string m_DownloadUri; + private int m_FlushSize; + private float m_Timeout; + + /// + /// 初始化下载任务的新实例。 + /// + public DownloadTask() + { + m_Status = DownloadTaskStatus.Todo; + m_DownloadPath = null; + m_DownloadUri = null; + m_FlushSize = 0; + m_Timeout = 0f; + } + + /// + /// 获取或设置下载任务的状态。 + /// + public DownloadTaskStatus Status + { + get + { + return m_Status; + } + set + { + m_Status = value; + } + } + + /// + /// 获取下载后存放路径。 + /// + public string DownloadPath + { + get + { + return m_DownloadPath; + } + } + + /// + /// 获取原始下载地址。 + /// + public string DownloadUri + { + get + { + return m_DownloadUri; + } + } + + /// + /// 获取将缓冲区写入磁盘的临界大小。 + /// + public int FlushSize + { + get + { + return m_FlushSize; + } + } + + /// + /// 获取下载超时时长,以秒为单位。 + /// + public float Timeout + { + get + { + return m_Timeout; + } + } + + /// + /// 获取下载任务的描述。 + /// + public override string Description + { + get + { + return m_DownloadPath; + } + } + + /// + /// 创建下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 下载任务的优先级。 + /// 将缓冲区写入磁盘的临界大小。 + /// 下载超时时长,以秒为单位。 + /// 用户自定义数据。 + /// 创建的下载任务。 + public static DownloadTask Create(string downloadPath, string downloadUri, string tag, int priority, int flushSize, float timeout, object userData) + { + DownloadTask downloadTask = ReferencePool.Acquire(); + downloadTask.Initialize(++s_Serial, tag, priority, userData); + downloadTask.m_DownloadPath = downloadPath; + downloadTask.m_DownloadUri = downloadUri; + downloadTask.m_FlushSize = flushSize; + downloadTask.m_Timeout = timeout; + return downloadTask; + } + + /// + /// 清理下载任务。 + /// + public override void Clear() + { + base.Clear(); + m_Status = DownloadTaskStatus.Todo; + m_DownloadPath = null; + m_DownloadUri = null; + m_FlushSize = 0; + m_Timeout = 0f; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadTask.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadTask.cs.meta new file mode 100644 index 0000000..524f2fd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadTask.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 64ef3f2125c886e40b9bd0141b57756d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadTaskStatus.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadTaskStatus.cs new file mode 100644 index 0000000..4e3dc19 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadTaskStatus.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + internal sealed partial class DownloadManager : GameFrameworkModule, IDownloadManager + { + /// + /// 下载任务的状态。 + /// + private enum DownloadTaskStatus : byte + { + /// + /// 准备下载。 + /// + Todo = 0, + + /// + /// 下载中。 + /// + Doing, + + /// + /// 下载完成。 + /// + Done, + + /// + /// 下载错误。 + /// + Error + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadTaskStatus.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadTaskStatus.cs.meta new file mode 100644 index 0000000..afc8354 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.DownloadTaskStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 478002d0db913694282b3bd952bbb751 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.cs new file mode 100644 index 0000000..da8b31f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.cs @@ -0,0 +1,486 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.Download +{ + /// + /// 下载管理器。 + /// + internal sealed partial class DownloadManager : GameFrameworkModule, IDownloadManager + { + private const int OneMegaBytes = 1024 * 1024; + + private readonly TaskPool m_TaskPool; + private readonly DownloadCounter m_DownloadCounter; + private int m_FlushSize; + private float m_Timeout; + private EventHandler m_DownloadStartEventHandler; + private EventHandler m_DownloadUpdateEventHandler; + private EventHandler m_DownloadSuccessEventHandler; + private EventHandler m_DownloadFailureEventHandler; + + /// + /// 初始化下载管理器的新实例。 + /// + public DownloadManager() + { + m_TaskPool = new TaskPool(); + m_DownloadCounter = new DownloadCounter(1f, 10f); + m_FlushSize = OneMegaBytes; + m_Timeout = 30f; + m_DownloadStartEventHandler = null; + m_DownloadUpdateEventHandler = null; + m_DownloadSuccessEventHandler = null; + m_DownloadFailureEventHandler = null; + } + + /// + /// 获取游戏框架模块优先级。 + /// + /// 优先级较高的模块会优先轮询,并且关闭操作会后进行。 + internal override int Priority + { + get + { + return 5; + } + } + + /// + /// 获取或设置下载是否被暂停。 + /// + public bool Paused + { + get + { + return m_TaskPool.Paused; + } + set + { + m_TaskPool.Paused = value; + } + } + + /// + /// 获取下载代理总数量。 + /// + public int TotalAgentCount + { + get + { + return m_TaskPool.TotalAgentCount; + } + } + + /// + /// 获取可用下载代理数量。 + /// + public int FreeAgentCount + { + get + { + return m_TaskPool.FreeAgentCount; + } + } + + /// + /// 获取工作中下载代理数量。 + /// + public int WorkingAgentCount + { + get + { + return m_TaskPool.WorkingAgentCount; + } + } + + /// + /// 获取等待下载任务数量。 + /// + public int WaitingTaskCount + { + get + { + return m_TaskPool.WaitingTaskCount; + } + } + + /// + /// 获取或设置将缓冲区写入磁盘的临界大小。 + /// + public int FlushSize + { + get + { + return m_FlushSize; + } + set + { + m_FlushSize = value; + } + } + + /// + /// 获取或设置下载超时时长,以秒为单位。 + /// + public float Timeout + { + get + { + return m_Timeout; + } + set + { + m_Timeout = value; + } + } + + /// + /// 获取当前下载速度。 + /// + public float CurrentSpeed + { + get + { + return m_DownloadCounter.CurrentSpeed; + } + } + + /// + /// 下载开始事件。 + /// + public event EventHandler DownloadStart + { + add + { + m_DownloadStartEventHandler += value; + } + remove + { + m_DownloadStartEventHandler -= value; + } + } + + /// + /// 下载更新事件。 + /// + public event EventHandler DownloadUpdate + { + add + { + m_DownloadUpdateEventHandler += value; + } + remove + { + m_DownloadUpdateEventHandler -= value; + } + } + + /// + /// 下载成功事件。 + /// + public event EventHandler DownloadSuccess + { + add + { + m_DownloadSuccessEventHandler += value; + } + remove + { + m_DownloadSuccessEventHandler -= value; + } + } + + /// + /// 下载失败事件。 + /// + public event EventHandler DownloadFailure + { + add + { + m_DownloadFailureEventHandler += value; + } + remove + { + m_DownloadFailureEventHandler -= value; + } + } + + /// + /// 下载管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + m_TaskPool.Update(elapseSeconds, realElapseSeconds); + m_DownloadCounter.Update(elapseSeconds, realElapseSeconds); + } + + /// + /// 关闭并清理下载管理器。 + /// + internal override void Shutdown() + { + m_TaskPool.Shutdown(); + m_DownloadCounter.Shutdown(); + } + + /// + /// 增加下载代理辅助器。 + /// + /// 要增加的下载代理辅助器。 + public void AddDownloadAgentHelper(IDownloadAgentHelper downloadAgentHelper) + { + DownloadAgent agent = new DownloadAgent(downloadAgentHelper); + agent.DownloadAgentStart += OnDownloadAgentStart; + agent.DownloadAgentUpdate += OnDownloadAgentUpdate; + agent.DownloadAgentSuccess += OnDownloadAgentSuccess; + agent.DownloadAgentFailure += OnDownloadAgentFailure; + + m_TaskPool.AddAgent(agent); + } + + /// + /// 根据下载任务的序列编号获取下载任务的信息。 + /// + /// 要获取信息的下载任务的序列编号。 + /// 下载任务的信息。 + public TaskInfo GetDownloadInfo(int serialId) + { + return m_TaskPool.GetTaskInfo(serialId); + } + + /// + /// 根据下载任务的标签获取下载任务的信息。 + /// + /// 要获取信息的下载任务的标签。 + /// 下载任务的信息。 + public TaskInfo[] GetDownloadInfos(string tag) + { + return m_TaskPool.GetTaskInfos(tag); + } + + /// + /// 根据下载任务的标签获取下载任务的信息。 + /// + /// 要获取信息的下载任务的标签。 + /// 下载任务的信息。 + public void GetDownloadInfos(string tag, List results) + { + m_TaskPool.GetTaskInfos(tag, results); + } + + /// + /// 获取所有下载任务的信息。 + /// + /// 所有下载任务的信息。 + public TaskInfo[] GetAllDownloadInfos() + { + return m_TaskPool.GetAllTaskInfos(); + } + + /// + /// 获取所有下载任务的信息。 + /// + /// 所有下载任务的信息。 + public void GetAllDownloadInfos(List results) + { + m_TaskPool.GetAllTaskInfos(results); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri) + { + return AddDownload(downloadPath, downloadUri, null, Constant.DefaultPriority, null); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, string tag) + { + return AddDownload(downloadPath, downloadUri, tag, Constant.DefaultPriority, null); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的优先级。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, int priority) + { + return AddDownload(downloadPath, downloadUri, null, priority, null); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 用户自定义数据。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, object userData) + { + return AddDownload(downloadPath, downloadUri, null, Constant.DefaultPriority, userData); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 下载任务的优先级。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, string tag, int priority) + { + return AddDownload(downloadPath, downloadUri, tag, priority, null); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 用户自定义数据。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, string tag, object userData) + { + return AddDownload(downloadPath, downloadUri, tag, Constant.DefaultPriority, userData); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的优先级。 + /// 用户自定义数据。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, int priority, object userData) + { + return AddDownload(downloadPath, downloadUri, null, priority, userData); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 下载任务的优先级。 + /// 用户自定义数据。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, string tag, int priority, object userData) + { + if (string.IsNullOrEmpty(downloadPath)) + { + throw new GameFrameworkException("Download path is invalid."); + } + + if (string.IsNullOrEmpty(downloadUri)) + { + throw new GameFrameworkException("Download uri is invalid."); + } + + if (TotalAgentCount <= 0) + { + throw new GameFrameworkException("You must add download agent first."); + } + + DownloadTask downloadTask = DownloadTask.Create(downloadPath, downloadUri, tag, priority, m_FlushSize, m_Timeout, userData); + m_TaskPool.AddTask(downloadTask); + return downloadTask.SerialId; + } + + /// + /// 根据下载任务的序列编号移除下载任务。 + /// + /// 要移除下载任务的序列编号。 + /// 是否移除下载任务成功。 + public bool RemoveDownload(int serialId) + { + return m_TaskPool.RemoveTask(serialId); + } + + /// + /// 根据下载任务的标签移除下载任务。 + /// + /// 要移除下载任务的标签。 + /// 移除下载任务的数量。 + public int RemoveDownloads(string tag) + { + return m_TaskPool.RemoveTasks(tag); + } + + /// + /// 移除所有下载任务。 + /// + /// 移除下载任务的数量。 + public int RemoveAllDownloads() + { + return m_TaskPool.RemoveAllTasks(); + } + + private void OnDownloadAgentStart(DownloadAgent sender) + { + if (m_DownloadStartEventHandler != null) + { + DownloadStartEventArgs downloadStartEventArgs = DownloadStartEventArgs.Create(sender.Task.SerialId, sender.Task.DownloadPath, sender.Task.DownloadUri, sender.CurrentLength, sender.Task.UserData); + m_DownloadStartEventHandler(this, downloadStartEventArgs); + ReferencePool.Release(downloadStartEventArgs); + } + } + + private void OnDownloadAgentUpdate(DownloadAgent sender, int deltaLength) + { + m_DownloadCounter.RecordDeltaLength(deltaLength); + if (m_DownloadUpdateEventHandler != null) + { + DownloadUpdateEventArgs downloadUpdateEventArgs = DownloadUpdateEventArgs.Create(sender.Task.SerialId, sender.Task.DownloadPath, sender.Task.DownloadUri, sender.CurrentLength, sender.Task.UserData); + m_DownloadUpdateEventHandler(this, downloadUpdateEventArgs); + ReferencePool.Release(downloadUpdateEventArgs); + } + } + + private void OnDownloadAgentSuccess(DownloadAgent sender, long length) + { + if (m_DownloadSuccessEventHandler != null) + { + DownloadSuccessEventArgs downloadSuccessEventArgs = DownloadSuccessEventArgs.Create(sender.Task.SerialId, sender.Task.DownloadPath, sender.Task.DownloadUri, sender.CurrentLength, sender.Task.UserData); + m_DownloadSuccessEventHandler(this, downloadSuccessEventArgs); + ReferencePool.Release(downloadSuccessEventArgs); + } + } + + private void OnDownloadAgentFailure(DownloadAgent sender, string errorMessage) + { + if (m_DownloadFailureEventHandler != null) + { + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(sender.Task.SerialId, sender.Task.DownloadPath, sender.Task.DownloadUri, errorMessage, sender.Task.UserData); + m_DownloadFailureEventHandler(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.cs.meta new file mode 100644 index 0000000..dc038a1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 729fb53ec60059a40a020bea77ab2c74 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadStartEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadStartEventArgs.cs new file mode 100644 index 0000000..7f7c826 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadStartEventArgs.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + /// + /// 下载开始事件。 + /// + public sealed class DownloadStartEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化下载开始事件的新实例。 + /// + public DownloadStartEventArgs() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0L; + UserData = null; + } + + /// + /// 获取下载任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取当前大小。 + /// + public long CurrentLength + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建下载开始事件。 + /// + /// 下载任务的序列编号。 + /// 下载后存放路径。 + /// 下载地址。 + /// 当前大小。 + /// 用户自定义数据。 + /// 创建的下载开始事件。 + public static DownloadStartEventArgs Create(int serialId, string downloadPath, string downloadUri, long currentLength, object userData) + { + DownloadStartEventArgs downloadStartEventArgs = ReferencePool.Acquire(); + downloadStartEventArgs.SerialId = serialId; + downloadStartEventArgs.DownloadPath = downloadPath; + downloadStartEventArgs.DownloadUri = downloadUri; + downloadStartEventArgs.CurrentLength = currentLength; + downloadStartEventArgs.UserData = userData; + return downloadStartEventArgs; + } + + /// + /// 清理下载开始事件。 + /// + public override void Clear() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0L; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadStartEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadStartEventArgs.cs.meta new file mode 100644 index 0000000..f8bbe1f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadStartEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a2974e6322549924e9278b93d1e1fd13 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadSuccessEventArgs.cs new file mode 100644 index 0000000..57be62d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadSuccessEventArgs.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + /// + /// 下载成功事件。 + /// + public sealed class DownloadSuccessEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化下载成功事件的新实例。 + /// + public DownloadSuccessEventArgs() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0L; + UserData = null; + } + + /// + /// 获取下载任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取当前大小。 + /// + public long CurrentLength + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建下载成功事件。 + /// + /// 下载任务的序列编号。 + /// 下载后存放路径。 + /// 下载地址。 + /// 当前大小。 + /// 用户自定义数据。 + /// 创建的下载成功事件。 + public static DownloadSuccessEventArgs Create(int serialId, string downloadPath, string downloadUri, long currentLength, object userData) + { + DownloadSuccessEventArgs downloadSuccessEventArgs = ReferencePool.Acquire(); + downloadSuccessEventArgs.SerialId = serialId; + downloadSuccessEventArgs.DownloadPath = downloadPath; + downloadSuccessEventArgs.DownloadUri = downloadUri; + downloadSuccessEventArgs.CurrentLength = currentLength; + downloadSuccessEventArgs.UserData = userData; + return downloadSuccessEventArgs; + } + + /// + /// 清理下载成功事件。 + /// + public override void Clear() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0L; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadSuccessEventArgs.cs.meta new file mode 100644 index 0000000..0366245 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d225adc5f17c97a42b5da79324b975a8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadUpdateEventArgs.cs new file mode 100644 index 0000000..8741695 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadUpdateEventArgs.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Download +{ + /// + /// 下载更新事件。 + /// + public sealed class DownloadUpdateEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化下载更新事件的新实例。 + /// + public DownloadUpdateEventArgs() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0L; + UserData = null; + } + + /// + /// 获取下载任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取当前大小。 + /// + public long CurrentLength + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建下载更新事件。 + /// + /// 下载任务的序列编号。 + /// 下载后存放路径。 + /// 下载地址。 + /// 当前大小。 + /// 用户自定义数据。 + /// 创建的下载更新事件。 + public static DownloadUpdateEventArgs Create(int serialId, string downloadPath, string downloadUri, long currentLength, object userData) + { + DownloadUpdateEventArgs downloadUpdateEventArgs = ReferencePool.Acquire(); + downloadUpdateEventArgs.SerialId = serialId; + downloadUpdateEventArgs.DownloadPath = downloadPath; + downloadUpdateEventArgs.DownloadUri = downloadUri; + downloadUpdateEventArgs.CurrentLength = currentLength; + downloadUpdateEventArgs.UserData = userData; + return downloadUpdateEventArgs; + } + + /// + /// 清理下载更新事件。 + /// + public override void Clear() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0L; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadUpdateEventArgs.cs.meta new file mode 100644 index 0000000..bbb25de --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/DownloadUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7d7640e13d60d34449a048583aa00936 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/IDownloadAgentHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/IDownloadAgentHelper.cs new file mode 100644 index 0000000..14757e6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/IDownloadAgentHelper.cs @@ -0,0 +1,66 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.Download +{ + /// + /// 下载代理辅助器接口。 + /// + public interface IDownloadAgentHelper + { + /// + /// 下载代理辅助器更新数据流事件。 + /// + event EventHandler DownloadAgentHelperUpdateBytes; + + /// + /// 下载代理辅助器更新数据大小事件。 + /// + event EventHandler DownloadAgentHelperUpdateLength; + + /// + /// 下载代理辅助器完成事件。 + /// + event EventHandler DownloadAgentHelperComplete; + + /// + /// 下载代理辅助器错误事件。 + /// + event EventHandler DownloadAgentHelperError; + + /// + /// 通过下载代理辅助器下载指定地址的数据。 + /// + /// 下载地址。 + /// 用户自定义数据。 + void Download(string downloadUri, object userData); + + /// + /// 通过下载代理辅助器下载指定地址的数据。 + /// + /// 下载地址。 + /// 下载数据起始位置。 + /// 用户自定义数据。 + void Download(string downloadUri, long fromPosition, object userData); + + /// + /// 通过下载代理辅助器下载指定地址的数据。 + /// + /// 下载地址。 + /// 下载数据起始位置。 + /// 下载数据结束位置。 + /// 用户自定义数据。 + void Download(string downloadUri, long fromPosition, long toPosition, object userData); + + /// + /// 重置下载代理辅助器。 + /// + void Reset(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/IDownloadAgentHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/IDownloadAgentHelper.cs.meta new file mode 100644 index 0000000..ab9fda6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/IDownloadAgentHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f96087ef0c8ca5f49813ac4166698485 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/IDownloadManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/IDownloadManager.cs new file mode 100644 index 0000000..ffe352f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/IDownloadManager.cs @@ -0,0 +1,240 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.Download +{ + /// + /// 下载管理器接口。 + /// + public interface IDownloadManager + { + /// + /// 获取或设置下载是否被暂停。 + /// + bool Paused + { + get; + set; + } + + /// + /// 获取下载代理总数量。 + /// + int TotalAgentCount + { + get; + } + + /// + /// 获取可用下载代理数量。 + /// + int FreeAgentCount + { + get; + } + + /// + /// 获取工作中下载代理数量。 + /// + int WorkingAgentCount + { + get; + } + + /// + /// 获取等待下载任务数量。 + /// + int WaitingTaskCount + { + get; + } + + /// + /// 获取或设置将缓冲区写入磁盘的临界大小。 + /// + int FlushSize + { + get; + set; + } + + /// + /// 获取或设置下载超时时长,以秒为单位。 + /// + float Timeout + { + get; + set; + } + + /// + /// 获取当前下载速度。 + /// + float CurrentSpeed + { + get; + } + + /// + /// 下载开始事件。 + /// + event EventHandler DownloadStart; + + /// + /// 下载更新事件。 + /// + event EventHandler DownloadUpdate; + + /// + /// 下载成功事件。 + /// + event EventHandler DownloadSuccess; + + /// + /// 下载失败事件。 + /// + event EventHandler DownloadFailure; + + /// + /// 增加下载代理辅助器。 + /// + /// 要增加的下载代理辅助器。 + void AddDownloadAgentHelper(IDownloadAgentHelper downloadAgentHelper); + + /// + /// 根据下载任务的序列编号获取下载任务的信息。 + /// + /// 要获取信息的下载任务的序列编号。 + /// 下载任务的信息。 + TaskInfo GetDownloadInfo(int serialId); + + /// + /// 根据下载任务的标签获取下载任务的信息。 + /// + /// 要获取信息的下载任务的标签。 + /// 下载任务的信息。 + TaskInfo[] GetDownloadInfos(string tag); + + /// + /// 根据下载任务的标签获取下载任务的信息。 + /// + /// 要获取信息的下载任务的标签。 + /// 下载任务的信息。 + void GetDownloadInfos(string tag, List results); + + /// + /// 获取所有下载任务的信息。 + /// + /// 所有下载任务的信息。 + TaskInfo[] GetAllDownloadInfos(); + + /// + /// 获取所有下载任务的信息。 + /// + /// 所有下载任务的信息。 + void GetAllDownloadInfos(List results); + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 新增下载任务的序列编号。 + int AddDownload(string downloadPath, string downloadUri); + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 新增下载任务的序列编号。 + int AddDownload(string downloadPath, string downloadUri, string tag); + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的优先级。 + /// 新增下载任务的序列编号。 + int AddDownload(string downloadPath, string downloadUri, int priority); + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 用户自定义数据。 + /// 新增下载任务的序列编号。 + int AddDownload(string downloadPath, string downloadUri, object userData); + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 下载任务的优先级。 + /// 新增下载任务的序列编号。 + int AddDownload(string downloadPath, string downloadUri, string tag, int priority); + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 用户自定义数据。 + /// 新增下载任务的序列编号。 + int AddDownload(string downloadPath, string downloadUri, string tag, object userData); + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的优先级。 + /// 用户自定义数据。 + /// 新增下载任务的序列编号。 + int AddDownload(string downloadPath, string downloadUri, int priority, object userData); + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 下载任务的优先级。 + /// 用户自定义数据。 + /// 新增下载任务的序列编号。 + int AddDownload(string downloadPath, string downloadUri, string tag, int priority, object userData); + + /// + /// 根据下载任务的序列编号移除下载任务。 + /// + /// 要移除下载任务的序列编号。 + /// 是否移除下载任务成功。 + bool RemoveDownload(int serialId); + + /// + /// 根据下载任务的标签移除下载任务。 + /// + /// 要移除下载任务的标签。 + /// 移除下载任务的数量。 + int RemoveDownloads(string tag); + + /// + /// 移除所有下载任务。 + /// + /// 移除下载任务的数量。 + int RemoveAllDownloads(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/IDownloadManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/IDownloadManager.cs.meta new file mode 100644 index 0000000..b9a5b04 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Download/IDownloadManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc56bc96a4239f849b19f8aaf8b694ee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity.meta new file mode 100644 index 0000000..e9ddc57 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 180218d2dcfcc66418af572848317bfd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityGroup.cs new file mode 100644 index 0000000..68d340a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityGroup.cs @@ -0,0 +1,394 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.ObjectPool; +using System.Collections.Generic; + +namespace GameFramework.Entity +{ + internal sealed partial class EntityManager : GameFrameworkModule, IEntityManager + { + /// + /// 实体组。 + /// + private sealed class EntityGroup : IEntityGroup + { + private readonly string m_Name; + private readonly IEntityGroupHelper m_EntityGroupHelper; + private readonly IObjectPool m_InstancePool; + private readonly GameFrameworkLinkedList m_Entities; + private LinkedListNode m_CachedNode; + + /// + /// 初始化实体组的新实例。 + /// + /// 实体组名称。 + /// 实体实例对象池自动释放可释放对象的间隔秒数。 + /// 实体实例对象池容量。 + /// 实体实例对象池对象过期秒数。 + /// 实体实例对象池的优先级。 + /// 实体组辅助器。 + /// 对象池管理器。 + public EntityGroup(string name, float instanceAutoReleaseInterval, int instanceCapacity, float instanceExpireTime, int instancePriority, IEntityGroupHelper entityGroupHelper, IObjectPoolManager objectPoolManager) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Entity group name is invalid."); + } + + if (entityGroupHelper == null) + { + throw new GameFrameworkException("Entity group helper is invalid."); + } + + m_Name = name; + m_EntityGroupHelper = entityGroupHelper; + m_InstancePool = objectPoolManager.CreateSingleSpawnObjectPool(Utility.Text.Format("Entity Instance Pool ({0})", name), instanceCapacity, instanceExpireTime, instancePriority); + m_InstancePool.AutoReleaseInterval = instanceAutoReleaseInterval; + m_Entities = new GameFrameworkLinkedList(); + m_CachedNode = null; + } + + /// + /// 获取实体组名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取实体组中实体数量。 + /// + public int EntityCount + { + get + { + return m_Entities.Count; + } + } + + /// + /// 获取或设置实体组实例对象池自动释放可释放对象的间隔秒数。 + /// + public float InstanceAutoReleaseInterval + { + get + { + return m_InstancePool.AutoReleaseInterval; + } + set + { + m_InstancePool.AutoReleaseInterval = value; + } + } + + /// + /// 获取或设置实体组实例对象池的容量。 + /// + public int InstanceCapacity + { + get + { + return m_InstancePool.Capacity; + } + set + { + m_InstancePool.Capacity = value; + } + } + + /// + /// 获取或设置实体组实例对象池对象过期秒数。 + /// + public float InstanceExpireTime + { + get + { + return m_InstancePool.ExpireTime; + } + set + { + m_InstancePool.ExpireTime = value; + } + } + + /// + /// 获取或设置实体组实例对象池的优先级。 + /// + public int InstancePriority + { + get + { + return m_InstancePool.Priority; + } + set + { + m_InstancePool.Priority = value; + } + } + + /// + /// 获取实体组辅助器。 + /// + public IEntityGroupHelper Helper + { + get + { + return m_EntityGroupHelper; + } + } + + /// + /// 实体组轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void Update(float elapseSeconds, float realElapseSeconds) + { + LinkedListNode current = m_Entities.First; + while (current != null) + { + m_CachedNode = current.Next; + current.Value.OnUpdate(elapseSeconds, realElapseSeconds); + current = m_CachedNode; + m_CachedNode = null; + } + } + + /// + /// 实体组中是否存在实体。 + /// + /// 实体序列编号。 + /// 实体组中是否存在实体。 + public bool HasEntity(int entityId) + { + foreach (IEntity entity in m_Entities) + { + if (entity.Id == entityId) + { + return true; + } + } + + return false; + } + + /// + /// 实体组中是否存在实体。 + /// + /// 实体资源名称。 + /// 实体组中是否存在实体。 + public bool HasEntity(string entityAssetName) + { + if (string.IsNullOrEmpty(entityAssetName)) + { + throw new GameFrameworkException("Entity asset name is invalid."); + } + + foreach (IEntity entity in m_Entities) + { + if (entity.EntityAssetName == entityAssetName) + { + return true; + } + } + + return false; + } + + /// + /// 从实体组中获取实体。 + /// + /// 实体序列编号。 + /// 要获取的实体。 + public IEntity GetEntity(int entityId) + { + foreach (IEntity entity in m_Entities) + { + if (entity.Id == entityId) + { + return entity; + } + } + + return null; + } + + /// + /// 从实体组中获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + public IEntity GetEntity(string entityAssetName) + { + if (string.IsNullOrEmpty(entityAssetName)) + { + throw new GameFrameworkException("Entity asset name is invalid."); + } + + foreach (IEntity entity in m_Entities) + { + if (entity.EntityAssetName == entityAssetName) + { + return entity; + } + } + + return null; + } + + /// + /// 从实体组中获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + public IEntity[] GetEntities(string entityAssetName) + { + if (string.IsNullOrEmpty(entityAssetName)) + { + throw new GameFrameworkException("Entity asset name is invalid."); + } + + List results = new List(); + foreach (IEntity entity in m_Entities) + { + if (entity.EntityAssetName == entityAssetName) + { + results.Add(entity); + } + } + + return results.ToArray(); + } + + /// + /// 从实体组中获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + public void GetEntities(string entityAssetName, List results) + { + if (string.IsNullOrEmpty(entityAssetName)) + { + throw new GameFrameworkException("Entity asset name is invalid."); + } + + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (IEntity entity in m_Entities) + { + if (entity.EntityAssetName == entityAssetName) + { + results.Add(entity); + } + } + } + + /// + /// 从实体组中获取所有实体。 + /// + /// 实体组中的所有实体。 + public IEntity[] GetAllEntities() + { + List results = new List(); + foreach (IEntity entity in m_Entities) + { + results.Add(entity); + } + + return results.ToArray(); + } + + /// + /// 从实体组中获取所有实体。 + /// + /// 实体组中的所有实体。 + public void GetAllEntities(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (IEntity entity in m_Entities) + { + results.Add(entity); + } + } + + /// + /// 往实体组增加实体。 + /// + /// 要增加的实体。 + public void AddEntity(IEntity entity) + { + m_Entities.AddLast(entity); + } + + /// + /// 从实体组移除实体。 + /// + /// 要移除的实体。 + public void RemoveEntity(IEntity entity) + { + if (m_CachedNode != null && m_CachedNode.Value == entity) + { + m_CachedNode = m_CachedNode.Next; + } + + if (!m_Entities.Remove(entity)) + { + throw new GameFrameworkException(Utility.Text.Format("Entity group '{0}' not exists specified entity '[{1}]{2}'.", m_Name, entity.Id, entity.EntityAssetName)); + } + } + + public void RegisterEntityInstanceObject(EntityInstanceObject obj, bool spawned) + { + m_InstancePool.Register(obj, spawned); + } + + public EntityInstanceObject SpawnEntityInstanceObject(string name) + { + return m_InstancePool.Spawn(name); + } + + public void UnspawnEntity(IEntity entity) + { + m_InstancePool.Unspawn(entity.Handle); + } + + public void SetEntityInstanceLocked(object entityInstance, bool locked) + { + if (entityInstance == null) + { + throw new GameFrameworkException("Entity instance is invalid."); + } + + m_InstancePool.SetLocked(entityInstance, locked); + } + + public void SetEntityInstancePriority(object entityInstance, int priority) + { + if (entityInstance == null) + { + throw new GameFrameworkException("Entity instance is invalid."); + } + + m_InstancePool.SetPriority(entityInstance, priority); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityGroup.cs.meta new file mode 100644 index 0000000..a1e47ad --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 05a88a175c90f86408faa1ed513f632a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityInfo.cs new file mode 100644 index 0000000..f9b4c63 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityInfo.cs @@ -0,0 +1,136 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.Entity +{ + internal sealed partial class EntityManager : GameFrameworkModule, IEntityManager + { + /// + /// 实体信息。 + /// + private sealed class EntityInfo : IReference + { + private IEntity m_Entity; + private EntityStatus m_Status; + private IEntity m_ParentEntity; + private List m_ChildEntities; + + public EntityInfo() + { + m_Entity = null; + m_Status = EntityStatus.Unknown; + m_ParentEntity = null; + m_ChildEntities = new List(); + } + + public IEntity Entity + { + get + { + return m_Entity; + } + } + + public EntityStatus Status + { + get + { + return m_Status; + } + set + { + m_Status = value; + } + } + + public IEntity ParentEntity + { + get + { + return m_ParentEntity; + } + set + { + m_ParentEntity = value; + } + } + + public int ChildEntityCount + { + get + { + return m_ChildEntities.Count; + } + } + + public static EntityInfo Create(IEntity entity) + { + if (entity == null) + { + throw new GameFrameworkException("Entity is invalid."); + } + + EntityInfo entityInfo = ReferencePool.Acquire(); + entityInfo.m_Entity = entity; + entityInfo.m_Status = EntityStatus.WillInit; + return entityInfo; + } + + public void Clear() + { + m_Entity = null; + m_Status = EntityStatus.Unknown; + m_ParentEntity = null; + m_ChildEntities.Clear(); + } + + public IEntity GetChildEntity() + { + return m_ChildEntities.Count > 0 ? m_ChildEntities[0] : null; + } + + public IEntity[] GetChildEntities() + { + return m_ChildEntities.ToArray(); + } + + public void GetChildEntities(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (IEntity childEntity in m_ChildEntities) + { + results.Add(childEntity); + } + } + + public void AddChildEntity(IEntity childEntity) + { + if (m_ChildEntities.Contains(childEntity)) + { + throw new GameFrameworkException("Can not add child entity which is already exist."); + } + + m_ChildEntities.Add(childEntity); + } + + public void RemoveChildEntity(IEntity childEntity) + { + if (!m_ChildEntities.Remove(childEntity)) + { + throw new GameFrameworkException("Can not remove child entity which is not exist."); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityInfo.cs.meta new file mode 100644 index 0000000..683c5f0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4c9d5a756ddb574419edab3f3f9eb4e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityInstanceObject.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityInstanceObject.cs new file mode 100644 index 0000000..ec9af19 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityInstanceObject.cs @@ -0,0 +1,60 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.ObjectPool; + +namespace GameFramework.Entity +{ + internal sealed partial class EntityManager : GameFrameworkModule, IEntityManager + { + /// + /// 实体实例对象。 + /// + private sealed class EntityInstanceObject : ObjectBase + { + private object m_EntityAsset; + private IEntityHelper m_EntityHelper; + + public EntityInstanceObject() + { + m_EntityAsset = null; + m_EntityHelper = null; + } + + public static EntityInstanceObject Create(string name, object entityAsset, object entityInstance, IEntityHelper entityHelper) + { + if (entityAsset == null) + { + throw new GameFrameworkException("Entity asset is invalid."); + } + + if (entityHelper == null) + { + throw new GameFrameworkException("Entity helper is invalid."); + } + + EntityInstanceObject entityInstanceObject = ReferencePool.Acquire(); + entityInstanceObject.Initialize(name, entityInstance); + entityInstanceObject.m_EntityAsset = entityAsset; + entityInstanceObject.m_EntityHelper = entityHelper; + return entityInstanceObject; + } + + public override void Clear() + { + base.Clear(); + m_EntityAsset = null; + m_EntityHelper = null; + } + + protected internal override void Release(bool isShutdown) + { + m_EntityHelper.ReleaseEntity(m_EntityAsset, Target); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityInstanceObject.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityInstanceObject.cs.meta new file mode 100644 index 0000000..8bf221c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityInstanceObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 78dfd3faf2fe0d348ba7c22d745702be +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityStatus.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityStatus.cs new file mode 100644 index 0000000..3bfdc4c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityStatus.cs @@ -0,0 +1,28 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Entity +{ + internal sealed partial class EntityManager : GameFrameworkModule, IEntityManager + { + /// + /// 实体状态。 + /// + private enum EntityStatus : byte + { + Unknown = 0, + WillInit, + Inited, + WillShow, + Showed, + WillHide, + Hidden, + WillRecycle, + Recycled + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityStatus.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityStatus.cs.meta new file mode 100644 index 0000000..15dfacb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.EntityStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: adc7d533633489d439b2e8542edac1f5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.ShowEntityInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.ShowEntityInfo.cs new file mode 100644 index 0000000..c395063 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.ShowEntityInfo.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Entity +{ + internal sealed partial class EntityManager : GameFrameworkModule, IEntityManager + { + private sealed class ShowEntityInfo : IReference + { + private int m_SerialId; + private int m_EntityId; + private EntityGroup m_EntityGroup; + private object m_UserData; + + public ShowEntityInfo() + { + m_SerialId = 0; + m_EntityId = 0; + m_EntityGroup = null; + m_UserData = null; + } + + public int SerialId + { + get + { + return m_SerialId; + } + } + + public int EntityId + { + get + { + return m_EntityId; + } + } + + public EntityGroup EntityGroup + { + get + { + return m_EntityGroup; + } + } + + public object UserData + { + get + { + return m_UserData; + } + } + + public static ShowEntityInfo Create(int serialId, int entityId, EntityGroup entityGroup, object userData) + { + ShowEntityInfo showEntityInfo = ReferencePool.Acquire(); + showEntityInfo.m_SerialId = serialId; + showEntityInfo.m_EntityId = entityId; + showEntityInfo.m_EntityGroup = entityGroup; + showEntityInfo.m_UserData = userData; + return showEntityInfo; + } + + public void Clear() + { + m_SerialId = 0; + m_EntityId = 0; + m_EntityGroup = null; + m_UserData = null; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.ShowEntityInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.ShowEntityInfo.cs.meta new file mode 100644 index 0000000..5ea6bc5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.ShowEntityInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cc8fd464aae90174b94b8992940f604a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.cs new file mode 100644 index 0000000..33188e1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.cs @@ -0,0 +1,1327 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.ObjectPool; +using GameFramework.Resource; +using System; +using System.Collections.Generic; + +namespace GameFramework.Entity +{ + /// + /// 实体管理器。 + /// + internal sealed partial class EntityManager : GameFrameworkModule, IEntityManager + { + private readonly Dictionary m_EntityInfos; + private readonly Dictionary m_EntityGroups; + private readonly Dictionary m_EntitiesBeingLoaded; + private readonly HashSet m_EntitiesToReleaseOnLoad; + private readonly Queue m_RecycleQueue; + private readonly LoadAssetCallbacks m_LoadAssetCallbacks; + private IObjectPoolManager m_ObjectPoolManager; + private IResourceManager m_ResourceManager; + private IEntityHelper m_EntityHelper; + private int m_Serial; + private bool m_IsShutdown; + private EventHandler m_ShowEntitySuccessEventHandler; + private EventHandler m_ShowEntityFailureEventHandler; + private EventHandler m_ShowEntityUpdateEventHandler; + private EventHandler m_ShowEntityDependencyAssetEventHandler; + private EventHandler m_HideEntityCompleteEventHandler; + + /// + /// 初始化实体管理器的新实例。 + /// + public EntityManager() + { + m_EntityInfos = new Dictionary(); + m_EntityGroups = new Dictionary(StringComparer.Ordinal); + m_EntitiesBeingLoaded = new Dictionary(); + m_EntitiesToReleaseOnLoad = new HashSet(); + m_RecycleQueue = new Queue(); + m_LoadAssetCallbacks = new LoadAssetCallbacks(LoadAssetSuccessCallback, LoadAssetFailureCallback, LoadAssetUpdateCallback, LoadAssetDependencyAssetCallback); + m_ObjectPoolManager = null; + m_ResourceManager = null; + m_EntityHelper = null; + m_Serial = 0; + m_IsShutdown = false; + m_ShowEntitySuccessEventHandler = null; + m_ShowEntityFailureEventHandler = null; + m_ShowEntityUpdateEventHandler = null; + m_ShowEntityDependencyAssetEventHandler = null; + m_HideEntityCompleteEventHandler = null; + } + + /// + /// 获取实体数量。 + /// + public int EntityCount + { + get + { + return m_EntityInfos.Count; + } + } + + /// + /// 获取实体组数量。 + /// + public int EntityGroupCount + { + get + { + return m_EntityGroups.Count; + } + } + + /// + /// 显示实体成功事件。 + /// + public event EventHandler ShowEntitySuccess + { + add + { + m_ShowEntitySuccessEventHandler += value; + } + remove + { + m_ShowEntitySuccessEventHandler -= value; + } + } + + /// + /// 显示实体失败事件。 + /// + public event EventHandler ShowEntityFailure + { + add + { + m_ShowEntityFailureEventHandler += value; + } + remove + { + m_ShowEntityFailureEventHandler -= value; + } + } + + /// + /// 显示实体更新事件。 + /// + public event EventHandler ShowEntityUpdate + { + add + { + m_ShowEntityUpdateEventHandler += value; + } + remove + { + m_ShowEntityUpdateEventHandler -= value; + } + } + + /// + /// 显示实体时加载依赖资源事件。 + /// + public event EventHandler ShowEntityDependencyAsset + { + add + { + m_ShowEntityDependencyAssetEventHandler += value; + } + remove + { + m_ShowEntityDependencyAssetEventHandler -= value; + } + } + + /// + /// 隐藏实体完成事件。 + /// + public event EventHandler HideEntityComplete + { + add + { + m_HideEntityCompleteEventHandler += value; + } + remove + { + m_HideEntityCompleteEventHandler -= value; + } + } + + /// + /// 实体管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + while (m_RecycleQueue.Count > 0) + { + EntityInfo entityInfo = m_RecycleQueue.Dequeue(); + IEntity entity = entityInfo.Entity; + EntityGroup entityGroup = (EntityGroup)entity.EntityGroup; + if (entityGroup == null) + { + throw new GameFrameworkException("Entity group is invalid."); + } + + entityInfo.Status = EntityStatus.WillRecycle; + entity.OnRecycle(); + entityInfo.Status = EntityStatus.Recycled; + entityGroup.UnspawnEntity(entity); + ReferencePool.Release(entityInfo); + } + + foreach (KeyValuePair entityGroup in m_EntityGroups) + { + entityGroup.Value.Update(elapseSeconds, realElapseSeconds); + } + } + + /// + /// 关闭并清理实体管理器。 + /// + internal override void Shutdown() + { + m_IsShutdown = true; + HideAllLoadedEntities(); + m_EntityGroups.Clear(); + m_EntitiesBeingLoaded.Clear(); + m_EntitiesToReleaseOnLoad.Clear(); + m_RecycleQueue.Clear(); + } + + /// + /// 设置对象池管理器。 + /// + /// 对象池管理器。 + public void SetObjectPoolManager(IObjectPoolManager objectPoolManager) + { + if (objectPoolManager == null) + { + throw new GameFrameworkException("Object pool manager is invalid."); + } + + m_ObjectPoolManager = objectPoolManager; + } + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + public void SetResourceManager(IResourceManager resourceManager) + { + if (resourceManager == null) + { + throw new GameFrameworkException("Resource manager is invalid."); + } + + m_ResourceManager = resourceManager; + } + + /// + /// 设置实体辅助器。 + /// + /// 实体辅助器。 + public void SetEntityHelper(IEntityHelper entityHelper) + { + if (entityHelper == null) + { + throw new GameFrameworkException("Entity helper is invalid."); + } + + m_EntityHelper = entityHelper; + } + + /// + /// 是否存在实体组。 + /// + /// 实体组名称。 + /// 是否存在实体组。 + public bool HasEntityGroup(string entityGroupName) + { + if (string.IsNullOrEmpty(entityGroupName)) + { + throw new GameFrameworkException("Entity group name is invalid."); + } + + return m_EntityGroups.ContainsKey(entityGroupName); + } + + /// + /// 获取实体组。 + /// + /// 实体组名称。 + /// 要获取的实体组。 + public IEntityGroup GetEntityGroup(string entityGroupName) + { + if (string.IsNullOrEmpty(entityGroupName)) + { + throw new GameFrameworkException("Entity group name is invalid."); + } + + EntityGroup entityGroup = null; + if (m_EntityGroups.TryGetValue(entityGroupName, out entityGroup)) + { + return entityGroup; + } + + return null; + } + + /// + /// 获取所有实体组。 + /// + /// 所有实体组。 + public IEntityGroup[] GetAllEntityGroups() + { + int index = 0; + IEntityGroup[] results = new IEntityGroup[m_EntityGroups.Count]; + foreach (KeyValuePair entityGroup in m_EntityGroups) + { + results[index++] = entityGroup.Value; + } + + return results; + } + + /// + /// 获取所有实体组。 + /// + /// 所有实体组。 + public void GetAllEntityGroups(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair entityGroup in m_EntityGroups) + { + results.Add(entityGroup.Value); + } + } + + /// + /// 增加实体组。 + /// + /// 实体组名称。 + /// 实体实例对象池自动释放可释放对象的间隔秒数。 + /// 实体实例对象池容量。 + /// 实体实例对象池对象过期秒数。 + /// 实体实例对象池的优先级。 + /// 实体组辅助器。 + /// 是否增加实体组成功。 + public bool AddEntityGroup(string entityGroupName, float instanceAutoReleaseInterval, int instanceCapacity, float instanceExpireTime, int instancePriority, IEntityGroupHelper entityGroupHelper) + { + if (string.IsNullOrEmpty(entityGroupName)) + { + throw new GameFrameworkException("Entity group name is invalid."); + } + + if (entityGroupHelper == null) + { + throw new GameFrameworkException("Entity group helper is invalid."); + } + + if (m_ObjectPoolManager == null) + { + throw new GameFrameworkException("You must set object pool manager first."); + } + + if (HasEntityGroup(entityGroupName)) + { + return false; + } + + m_EntityGroups.Add(entityGroupName, new EntityGroup(entityGroupName, instanceAutoReleaseInterval, instanceCapacity, instanceExpireTime, instancePriority, entityGroupHelper, m_ObjectPoolManager)); + + return true; + } + + /// + /// 是否存在实体。 + /// + /// 实体编号。 + /// 是否存在实体。 + public bool HasEntity(int entityId) + { + return m_EntityInfos.ContainsKey(entityId); + } + + /// + /// 是否存在实体。 + /// + /// 实体资源名称。 + /// 是否存在实体。 + public bool HasEntity(string entityAssetName) + { + if (string.IsNullOrEmpty(entityAssetName)) + { + throw new GameFrameworkException("Entity asset name is invalid."); + } + + foreach (KeyValuePair entityInfo in m_EntityInfos) + { + if (entityInfo.Value.Entity.EntityAssetName == entityAssetName) + { + return true; + } + } + + return false; + } + + /// + /// 获取实体。 + /// + /// 实体编号。 + /// 要获取的实体。 + public IEntity GetEntity(int entityId) + { + EntityInfo entityInfo = GetEntityInfo(entityId); + if (entityInfo == null) + { + return null; + } + + return entityInfo.Entity; + } + + /// + /// 获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + public IEntity GetEntity(string entityAssetName) + { + if (string.IsNullOrEmpty(entityAssetName)) + { + throw new GameFrameworkException("Entity asset name is invalid."); + } + + foreach (KeyValuePair entityInfo in m_EntityInfos) + { + if (entityInfo.Value.Entity.EntityAssetName == entityAssetName) + { + return entityInfo.Value.Entity; + } + } + + return null; + } + + /// + /// 获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + public IEntity[] GetEntities(string entityAssetName) + { + if (string.IsNullOrEmpty(entityAssetName)) + { + throw new GameFrameworkException("Entity asset name is invalid."); + } + + List results = new List(); + foreach (KeyValuePair entityInfo in m_EntityInfos) + { + if (entityInfo.Value.Entity.EntityAssetName == entityAssetName) + { + results.Add(entityInfo.Value.Entity); + } + } + + return results.ToArray(); + } + + /// + /// 获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + public void GetEntities(string entityAssetName, List results) + { + if (string.IsNullOrEmpty(entityAssetName)) + { + throw new GameFrameworkException("Entity asset name is invalid."); + } + + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair entityInfo in m_EntityInfos) + { + if (entityInfo.Value.Entity.EntityAssetName == entityAssetName) + { + results.Add(entityInfo.Value.Entity); + } + } + } + + /// + /// 获取所有已加载的实体。 + /// + /// 所有已加载的实体。 + public IEntity[] GetAllLoadedEntities() + { + int index = 0; + IEntity[] results = new IEntity[m_EntityInfos.Count]; + foreach (KeyValuePair entityInfo in m_EntityInfos) + { + results[index++] = entityInfo.Value.Entity; + } + + return results; + } + + /// + /// 获取所有已加载的实体。 + /// + /// 所有已加载的实体。 + public void GetAllLoadedEntities(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair entityInfo in m_EntityInfos) + { + results.Add(entityInfo.Value.Entity); + } + } + + /// + /// 获取所有正在加载实体的编号。 + /// + /// 所有正在加载实体的编号。 + public int[] GetAllLoadingEntityIds() + { + int index = 0; + int[] results = new int[m_EntitiesBeingLoaded.Count]; + foreach (KeyValuePair entityBeingLoaded in m_EntitiesBeingLoaded) + { + results[index++] = entityBeingLoaded.Key; + } + + return results; + } + + /// + /// 获取所有正在加载实体的编号。 + /// + /// 所有正在加载实体的编号。 + public void GetAllLoadingEntityIds(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair entityBeingLoaded in m_EntitiesBeingLoaded) + { + results.Add(entityBeingLoaded.Key); + } + } + + /// + /// 是否正在加载实体。 + /// + /// 实体编号。 + /// 是否正在加载实体。 + public bool IsLoadingEntity(int entityId) + { + return m_EntitiesBeingLoaded.ContainsKey(entityId); + } + + /// + /// 是否是合法的实体。 + /// + /// 实体。 + /// 实体是否合法。 + public bool IsValidEntity(IEntity entity) + { + if (entity == null) + { + return false; + } + + return HasEntity(entity.Id); + } + + /// + /// 显示实体。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + public void ShowEntity(int entityId, string entityAssetName, string entityGroupName) + { + ShowEntity(entityId, entityAssetName, entityGroupName, Constant.DefaultPriority, null); + } + + /// + /// 显示实体。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + /// 加载实体资源的优先级。 + public void ShowEntity(int entityId, string entityAssetName, string entityGroupName, int priority) + { + ShowEntity(entityId, entityAssetName, entityGroupName, priority, null); + } + + /// + /// 显示实体。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + /// 用户自定义数据。 + public void ShowEntity(int entityId, string entityAssetName, string entityGroupName, object userData) + { + ShowEntity(entityId, entityAssetName, entityGroupName, Constant.DefaultPriority, userData); + } + + /// + /// 显示实体。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + /// 加载实体资源的优先级。 + /// 用户自定义数据。 + public void ShowEntity(int entityId, string entityAssetName, string entityGroupName, int priority, object userData) + { + if (m_ResourceManager == null) + { + throw new GameFrameworkException("You must set resource manager first."); + } + + if (m_EntityHelper == null) + { + throw new GameFrameworkException("You must set entity helper first."); + } + + if (string.IsNullOrEmpty(entityAssetName)) + { + throw new GameFrameworkException("Entity asset name is invalid."); + } + + if (string.IsNullOrEmpty(entityGroupName)) + { + throw new GameFrameworkException("Entity group name is invalid."); + } + + if (HasEntity(entityId)) + { + throw new GameFrameworkException(Utility.Text.Format("Entity id '{0}' is already exist.", entityId)); + } + + if (IsLoadingEntity(entityId)) + { + throw new GameFrameworkException(Utility.Text.Format("Entity '{0}' is already being loaded.", entityId)); + } + + EntityGroup entityGroup = (EntityGroup)GetEntityGroup(entityGroupName); + if (entityGroup == null) + { + throw new GameFrameworkException(Utility.Text.Format("Entity group '{0}' is not exist.", entityGroupName)); + } + + EntityInstanceObject entityInstanceObject = entityGroup.SpawnEntityInstanceObject(entityAssetName); + if (entityInstanceObject == null) + { + int serialId = ++m_Serial; + m_EntitiesBeingLoaded.Add(entityId, serialId); + m_ResourceManager.LoadAsset(entityAssetName, priority, m_LoadAssetCallbacks, ShowEntityInfo.Create(serialId, entityId, entityGroup, userData)); + return; + } + + InternalShowEntity(entityId, entityAssetName, entityGroup, entityInstanceObject.Target, false, 0f, userData); + } + + /// + /// 隐藏实体。 + /// + /// 实体编号。 + public void HideEntity(int entityId) + { + HideEntity(entityId, null); + } + + /// + /// 隐藏实体。 + /// + /// 实体编号。 + /// 用户自定义数据。 + public void HideEntity(int entityId, object userData) + { + if (IsLoadingEntity(entityId)) + { + m_EntitiesToReleaseOnLoad.Add(m_EntitiesBeingLoaded[entityId]); + m_EntitiesBeingLoaded.Remove(entityId); + return; + } + + EntityInfo entityInfo = GetEntityInfo(entityId); + if (entityInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find entity '{0}'.", entityId)); + } + + InternalHideEntity(entityInfo, userData); + } + + /// + /// 隐藏实体。 + /// + /// 实体。 + public void HideEntity(IEntity entity) + { + HideEntity(entity, null); + } + + /// + /// 隐藏实体。 + /// + /// 实体。 + /// 用户自定义数据。 + public void HideEntity(IEntity entity, object userData) + { + if (entity == null) + { + throw new GameFrameworkException("Entity is invalid."); + } + + HideEntity(entity.Id, userData); + } + + /// + /// 隐藏所有已加载的实体。 + /// + public void HideAllLoadedEntities() + { + HideAllLoadedEntities(null); + } + + /// + /// 隐藏所有已加载的实体。 + /// + /// 用户自定义数据。 + public void HideAllLoadedEntities(object userData) + { + while (m_EntityInfos.Count > 0) + { + foreach (KeyValuePair entityInfo in m_EntityInfos) + { + InternalHideEntity(entityInfo.Value, userData); + break; + } + } + } + + /// + /// 隐藏所有正在加载的实体。 + /// + public void HideAllLoadingEntities() + { + foreach (KeyValuePair entityBeingLoaded in m_EntitiesBeingLoaded) + { + m_EntitiesToReleaseOnLoad.Add(entityBeingLoaded.Value); + } + + m_EntitiesBeingLoaded.Clear(); + } + + /// + /// 获取父实体。 + /// + /// 要获取父实体的子实体的实体编号。 + /// 子实体的父实体。 + public IEntity GetParentEntity(int childEntityId) + { + EntityInfo childEntityInfo = GetEntityInfo(childEntityId); + if (childEntityInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find child entity '{0}'.", childEntityId)); + } + + return childEntityInfo.ParentEntity; + } + + /// + /// 获取父实体。 + /// + /// 要获取父实体的子实体。 + /// 子实体的父实体。 + public IEntity GetParentEntity(IEntity childEntity) + { + if (childEntity == null) + { + throw new GameFrameworkException("Child entity is invalid."); + } + + return GetParentEntity(childEntity.Id); + } + + /// + /// 获取子实体数量。 + /// + /// 要获取子实体数量的父实体的实体编号。 + /// 子实体数量。 + public int GetChildEntityCount(int parentEntityId) + { + EntityInfo parentEntityInfo = GetEntityInfo(parentEntityId); + if (parentEntityInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find parent entity '{0}'.", parentEntityId)); + } + + return parentEntityInfo.ChildEntityCount; + } + + /// + /// 获取子实体。 + /// + /// 要获取子实体的父实体的实体编号。 + /// 子实体。 + public IEntity GetChildEntity(int parentEntityId) + { + EntityInfo parentEntityInfo = GetEntityInfo(parentEntityId); + if (parentEntityInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find parent entity '{0}'.", parentEntityId)); + } + + return parentEntityInfo.GetChildEntity(); + } + + /// + /// 获取子实体。 + /// + /// 要获取子实体的父实体。 + /// 子实体。 + public IEntity GetChildEntity(IEntity parentEntity) + { + if (parentEntity == null) + { + throw new GameFrameworkException("Parent entity is invalid."); + } + + return GetChildEntity(parentEntity.Id); + } + + /// + /// 获取所有子实体。 + /// + /// 要获取所有子实体的父实体的实体编号。 + /// 所有子实体。 + public IEntity[] GetChildEntities(int parentEntityId) + { + EntityInfo parentEntityInfo = GetEntityInfo(parentEntityId); + if (parentEntityInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find parent entity '{0}'.", parentEntityId)); + } + + return parentEntityInfo.GetChildEntities(); + } + + /// + /// 获取所有子实体。 + /// + /// 要获取所有子实体的父实体的实体编号。 + /// 所有子实体。 + public void GetChildEntities(int parentEntityId, List results) + { + EntityInfo parentEntityInfo = GetEntityInfo(parentEntityId); + if (parentEntityInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find parent entity '{0}'.", parentEntityId)); + } + + parentEntityInfo.GetChildEntities(results); + } + + /// + /// 获取所有子实体。 + /// + /// 要获取所有子实体的父实体。 + /// 所有子实体。 + public IEntity[] GetChildEntities(IEntity parentEntity) + { + if (parentEntity == null) + { + throw new GameFrameworkException("Parent entity is invalid."); + } + + return GetChildEntities(parentEntity.Id); + } + + /// + /// 获取所有子实体。 + /// + /// 要获取所有子实体的父实体。 + /// 所有子实体。 + public void GetChildEntities(IEntity parentEntity, List results) + { + if (parentEntity == null) + { + throw new GameFrameworkException("Parent entity is invalid."); + } + + GetChildEntities(parentEntity.Id, results); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体的实体编号。 + public void AttachEntity(int childEntityId, int parentEntityId) + { + AttachEntity(childEntityId, parentEntityId, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体的实体编号。 + /// 用户自定义数据。 + public void AttachEntity(int childEntityId, int parentEntityId, object userData) + { + if (childEntityId == parentEntityId) + { + throw new GameFrameworkException(Utility.Text.Format("Can not attach entity when child entity id equals to parent entity id '{0}'.", parentEntityId)); + } + + EntityInfo childEntityInfo = GetEntityInfo(childEntityId); + if (childEntityInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find child entity '{0}'.", childEntityId)); + } + + if (childEntityInfo.Status >= EntityStatus.WillHide) + { + throw new GameFrameworkException(Utility.Text.Format("Can not attach entity when child entity status is '{0}'.", childEntityInfo.Status)); + } + + EntityInfo parentEntityInfo = GetEntityInfo(parentEntityId); + if (parentEntityInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find parent entity '{0}'.", parentEntityId)); + } + + if (parentEntityInfo.Status >= EntityStatus.WillHide) + { + throw new GameFrameworkException(Utility.Text.Format("Can not attach entity when parent entity status is '{0}'.", parentEntityInfo.Status)); + } + + IEntity childEntity = childEntityInfo.Entity; + IEntity parentEntity = parentEntityInfo.Entity; + DetachEntity(childEntity.Id, userData); + childEntityInfo.ParentEntity = parentEntity; + parentEntityInfo.AddChildEntity(childEntity); + parentEntity.OnAttached(childEntity, userData); + childEntity.OnAttachTo(parentEntity, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体。 + public void AttachEntity(int childEntityId, IEntity parentEntity) + { + AttachEntity(childEntityId, parentEntity, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体。 + /// 用户自定义数据。 + public void AttachEntity(int childEntityId, IEntity parentEntity, object userData) + { + if (parentEntity == null) + { + throw new GameFrameworkException("Parent entity is invalid."); + } + + AttachEntity(childEntityId, parentEntity.Id, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体的实体编号。 + public void AttachEntity(IEntity childEntity, int parentEntityId) + { + AttachEntity(childEntity, parentEntityId, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体的实体编号。 + /// 用户自定义数据。 + public void AttachEntity(IEntity childEntity, int parentEntityId, object userData) + { + if (childEntity == null) + { + throw new GameFrameworkException("Child entity is invalid."); + } + + AttachEntity(childEntity.Id, parentEntityId, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体。 + public void AttachEntity(IEntity childEntity, IEntity parentEntity) + { + AttachEntity(childEntity, parentEntity, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体。 + /// 用户自定义数据。 + public void AttachEntity(IEntity childEntity, IEntity parentEntity, object userData) + { + if (childEntity == null) + { + throw new GameFrameworkException("Child entity is invalid."); + } + + if (parentEntity == null) + { + throw new GameFrameworkException("Parent entity is invalid."); + } + + AttachEntity(childEntity.Id, parentEntity.Id, userData); + } + + /// + /// 解除子实体。 + /// + /// 要解除的子实体的实体编号。 + public void DetachEntity(int childEntityId) + { + DetachEntity(childEntityId, null); + } + + /// + /// 解除子实体。 + /// + /// 要解除的子实体的实体编号。 + /// 用户自定义数据。 + public void DetachEntity(int childEntityId, object userData) + { + EntityInfo childEntityInfo = GetEntityInfo(childEntityId); + if (childEntityInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find child entity '{0}'.", childEntityId)); + } + + IEntity parentEntity = childEntityInfo.ParentEntity; + if (parentEntity == null) + { + return; + } + + EntityInfo parentEntityInfo = GetEntityInfo(parentEntity.Id); + if (parentEntityInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find parent entity '{0}'.", parentEntity.Id)); + } + + IEntity childEntity = childEntityInfo.Entity; + childEntityInfo.ParentEntity = null; + parentEntityInfo.RemoveChildEntity(childEntity); + parentEntity.OnDetached(childEntity, userData); + childEntity.OnDetachFrom(parentEntity, userData); + } + + /// + /// 解除子实体。 + /// + /// 要解除的子实体。 + public void DetachEntity(IEntity childEntity) + { + DetachEntity(childEntity, null); + } + + /// + /// 解除子实体。 + /// + /// 要解除的子实体。 + /// 用户自定义数据。 + public void DetachEntity(IEntity childEntity, object userData) + { + if (childEntity == null) + { + throw new GameFrameworkException("Child entity is invalid."); + } + + DetachEntity(childEntity.Id, userData); + } + + /// + /// 解除所有子实体。 + /// + /// 被解除的父实体的实体编号。 + public void DetachChildEntities(int parentEntityId) + { + DetachChildEntities(parentEntityId, null); + } + + /// + /// 解除所有子实体。 + /// + /// 被解除的父实体的实体编号。 + /// 用户自定义数据。 + public void DetachChildEntities(int parentEntityId, object userData) + { + EntityInfo parentEntityInfo = GetEntityInfo(parentEntityId); + if (parentEntityInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find parent entity '{0}'.", parentEntityId)); + } + + while (parentEntityInfo.ChildEntityCount > 0) + { + IEntity childEntity = parentEntityInfo.GetChildEntity(); + DetachEntity(childEntity.Id, userData); + } + } + + /// + /// 解除所有子实体。 + /// + /// 被解除的父实体。 + public void DetachChildEntities(IEntity parentEntity) + { + DetachChildEntities(parentEntity, null); + } + + /// + /// 解除所有子实体。 + /// + /// 被解除的父实体。 + /// 用户自定义数据。 + public void DetachChildEntities(IEntity parentEntity, object userData) + { + if (parentEntity == null) + { + throw new GameFrameworkException("Parent entity is invalid."); + } + + DetachChildEntities(parentEntity.Id, userData); + } + + /// + /// 获取实体信息。 + /// + /// 实体编号。 + /// 实体信息。 + private EntityInfo GetEntityInfo(int entityId) + { + EntityInfo entityInfo = null; + if (m_EntityInfos.TryGetValue(entityId, out entityInfo)) + { + return entityInfo; + } + + return null; + } + + private void InternalShowEntity(int entityId, string entityAssetName, EntityGroup entityGroup, object entityInstance, bool isNewInstance, float duration, object userData) + { + try + { + IEntity entity = m_EntityHelper.CreateEntity(entityInstance, entityGroup, userData); + if (entity == null) + { + throw new GameFrameworkException("Can not create entity in entity helper."); + } + + EntityInfo entityInfo = EntityInfo.Create(entity); + m_EntityInfos.Add(entityId, entityInfo); + entityInfo.Status = EntityStatus.WillInit; + entity.OnInit(entityId, entityAssetName, entityGroup, isNewInstance, userData); + entityInfo.Status = EntityStatus.Inited; + entityGroup.AddEntity(entity); + entityInfo.Status = EntityStatus.WillShow; + entity.OnShow(userData); + entityInfo.Status = EntityStatus.Showed; + + if (m_ShowEntitySuccessEventHandler != null) + { + ShowEntitySuccessEventArgs showEntitySuccessEventArgs = ShowEntitySuccessEventArgs.Create(entity, duration, userData); + m_ShowEntitySuccessEventHandler(this, showEntitySuccessEventArgs); + ReferencePool.Release(showEntitySuccessEventArgs); + } + } + catch (Exception exception) + { + if (m_ShowEntityFailureEventHandler != null) + { + ShowEntityFailureEventArgs showEntityFailureEventArgs = ShowEntityFailureEventArgs.Create(entityId, entityAssetName, entityGroup.Name, exception.ToString(), userData); + m_ShowEntityFailureEventHandler(this, showEntityFailureEventArgs); + ReferencePool.Release(showEntityFailureEventArgs); + return; + } + + throw; + } + } + + private void InternalHideEntity(EntityInfo entityInfo, object userData) + { + while (entityInfo.ChildEntityCount > 0) + { + IEntity childEntity = entityInfo.GetChildEntity(); + HideEntity(childEntity.Id, userData); + } + + if (entityInfo.Status == EntityStatus.Hidden) + { + return; + } + + IEntity entity = entityInfo.Entity; + DetachEntity(entity.Id, userData); + entityInfo.Status = EntityStatus.WillHide; + entity.OnHide(m_IsShutdown, userData); + entityInfo.Status = EntityStatus.Hidden; + + EntityGroup entityGroup = (EntityGroup)entity.EntityGroup; + if (entityGroup == null) + { + throw new GameFrameworkException("Entity group is invalid."); + } + + entityGroup.RemoveEntity(entity); + if (!m_EntityInfos.Remove(entity.Id)) + { + throw new GameFrameworkException("Entity info is unmanaged."); + } + + if (m_HideEntityCompleteEventHandler != null) + { + HideEntityCompleteEventArgs hideEntityCompleteEventArgs = HideEntityCompleteEventArgs.Create(entity.Id, entity.EntityAssetName, entityGroup, userData); + m_HideEntityCompleteEventHandler(this, hideEntityCompleteEventArgs); + ReferencePool.Release(hideEntityCompleteEventArgs); + } + + m_RecycleQueue.Enqueue(entityInfo); + } + + private void LoadAssetSuccessCallback(string entityAssetName, object entityAsset, float duration, object userData) + { + ShowEntityInfo showEntityInfo = (ShowEntityInfo)userData; + if (showEntityInfo == null) + { + throw new GameFrameworkException("Show entity info is invalid."); + } + + if (m_EntitiesToReleaseOnLoad.Contains(showEntityInfo.SerialId)) + { + m_EntitiesToReleaseOnLoad.Remove(showEntityInfo.SerialId); + ReferencePool.Release(showEntityInfo); + m_EntityHelper.ReleaseEntity(entityAsset, null); + return; + } + + m_EntitiesBeingLoaded.Remove(showEntityInfo.EntityId); + EntityInstanceObject entityInstanceObject = EntityInstanceObject.Create(entityAssetName, entityAsset, m_EntityHelper.InstantiateEntity(entityAsset), m_EntityHelper); + showEntityInfo.EntityGroup.RegisterEntityInstanceObject(entityInstanceObject, true); + + InternalShowEntity(showEntityInfo.EntityId, entityAssetName, showEntityInfo.EntityGroup, entityInstanceObject.Target, true, duration, showEntityInfo.UserData); + ReferencePool.Release(showEntityInfo); + } + + private void LoadAssetFailureCallback(string entityAssetName, LoadResourceStatus status, string errorMessage, object userData) + { + ShowEntityInfo showEntityInfo = (ShowEntityInfo)userData; + if (showEntityInfo == null) + { + throw new GameFrameworkException("Show entity info is invalid."); + } + + if (m_EntitiesToReleaseOnLoad.Contains(showEntityInfo.SerialId)) + { + m_EntitiesToReleaseOnLoad.Remove(showEntityInfo.SerialId); + return; + } + + m_EntitiesBeingLoaded.Remove(showEntityInfo.EntityId); + string appendErrorMessage = Utility.Text.Format("Load entity failure, asset name '{0}', status '{1}', error message '{2}'.", entityAssetName, status, errorMessage); + if (m_ShowEntityFailureEventHandler != null) + { + ShowEntityFailureEventArgs showEntityFailureEventArgs = ShowEntityFailureEventArgs.Create(showEntityInfo.EntityId, entityAssetName, showEntityInfo.EntityGroup.Name, appendErrorMessage, showEntityInfo.UserData); + m_ShowEntityFailureEventHandler(this, showEntityFailureEventArgs); + ReferencePool.Release(showEntityFailureEventArgs); + return; + } + + throw new GameFrameworkException(appendErrorMessage); + } + + private void LoadAssetUpdateCallback(string entityAssetName, float progress, object userData) + { + ShowEntityInfo showEntityInfo = (ShowEntityInfo)userData; + if (showEntityInfo == null) + { + throw new GameFrameworkException("Show entity info is invalid."); + } + + if (m_ShowEntityUpdateEventHandler != null) + { + ShowEntityUpdateEventArgs showEntityUpdateEventArgs = ShowEntityUpdateEventArgs.Create(showEntityInfo.EntityId, entityAssetName, showEntityInfo.EntityGroup.Name, progress, showEntityInfo.UserData); + m_ShowEntityUpdateEventHandler(this, showEntityUpdateEventArgs); + ReferencePool.Release(showEntityUpdateEventArgs); + } + } + + private void LoadAssetDependencyAssetCallback(string entityAssetName, string dependencyAssetName, int loadedCount, int totalCount, object userData) + { + ShowEntityInfo showEntityInfo = (ShowEntityInfo)userData; + if (showEntityInfo == null) + { + throw new GameFrameworkException("Show entity info is invalid."); + } + + if (m_ShowEntityDependencyAssetEventHandler != null) + { + ShowEntityDependencyAssetEventArgs showEntityDependencyAssetEventArgs = ShowEntityDependencyAssetEventArgs.Create(showEntityInfo.EntityId, entityAssetName, showEntityInfo.EntityGroup.Name, dependencyAssetName, loadedCount, totalCount, showEntityInfo.UserData); + m_ShowEntityDependencyAssetEventHandler(this, showEntityDependencyAssetEventArgs); + ReferencePool.Release(showEntityDependencyAssetEventArgs); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.cs.meta new file mode 100644 index 0000000..8637a41 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/EntityManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eee578270537c0c40af3759c88085583 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/HideEntityCompleteEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/HideEntityCompleteEventArgs.cs new file mode 100644 index 0000000..04d421d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/HideEntityCompleteEventArgs.cs @@ -0,0 +1,91 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Entity +{ + /// + /// 隐藏实体完成事件。 + /// + public sealed class HideEntityCompleteEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化隐藏实体完成事件的新实例。 + /// + public HideEntityCompleteEventArgs() + { + EntityId = 0; + EntityAssetName = null; + EntityGroup = null; + UserData = null; + } + + /// + /// 获取实体编号。 + /// + public int EntityId + { + get; + private set; + } + + /// + /// 获取实体资源名称。 + /// + public string EntityAssetName + { + get; + private set; + } + + /// + /// 获取实体所属的实体组。 + /// + public IEntityGroup EntityGroup + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建隐藏实体完成事件。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体所属的实体组。 + /// 用户自定义数据。 + /// 创建的隐藏实体完成事件。 + public static HideEntityCompleteEventArgs Create(int entityId, string entityAssetName, IEntityGroup entityGroup, object userData) + { + HideEntityCompleteEventArgs hideEntityCompleteEventArgs = ReferencePool.Acquire(); + hideEntityCompleteEventArgs.EntityId = entityId; + hideEntityCompleteEventArgs.EntityAssetName = entityAssetName; + hideEntityCompleteEventArgs.EntityGroup = entityGroup; + hideEntityCompleteEventArgs.UserData = userData; + return hideEntityCompleteEventArgs; + } + + /// + /// 清理隐藏实体完成事件。 + /// + public override void Clear() + { + EntityId = 0; + EntityAssetName = null; + EntityGroup = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/HideEntityCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/HideEntityCompleteEventArgs.cs.meta new file mode 100644 index 0000000..449b0b4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/HideEntityCompleteEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b474b837c539cdf4c9316bf47ed22f06 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntity.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntity.cs new file mode 100644 index 0000000..d40e2cc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntity.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Entity +{ + /// + /// 实体接口。 + /// + public interface IEntity + { + /// + /// 获取实体编号。 + /// + int Id + { + get; + } + + /// + /// 获取实体资源名称。 + /// + string EntityAssetName + { + get; + } + + /// + /// 获取实体实例。 + /// + object Handle + { + get; + } + + /// + /// 获取实体所属的实体组。 + /// + IEntityGroup EntityGroup + { + get; + } + + /// + /// 实体初始化。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体所属的实体组。 + /// 是否是新实例。 + /// 用户自定义数据。 + void OnInit(int entityId, string entityAssetName, IEntityGroup entityGroup, bool isNewInstance, object userData); + + /// + /// 实体回收。 + /// + void OnRecycle(); + + /// + /// 实体显示。 + /// + /// 用户自定义数据。 + void OnShow(object userData); + + /// + /// 实体隐藏。 + /// + /// 是否是关闭实体管理器时触发。 + /// 用户自定义数据。 + void OnHide(bool isShutdown, object userData); + + /// + /// 实体附加子实体。 + /// + /// 附加的子实体。 + /// 用户自定义数据。 + void OnAttached(IEntity childEntity, object userData); + + /// + /// 实体解除子实体。 + /// + /// 解除的子实体。 + /// 用户自定义数据。 + void OnDetached(IEntity childEntity, object userData); + + /// + /// 实体附加子实体。 + /// + /// 被附加的父实体。 + /// 用户自定义数据。 + void OnAttachTo(IEntity parentEntity, object userData); + + /// + /// 实体解除子实体。 + /// + /// 被解除的父实体。 + /// 用户自定义数据。 + void OnDetachFrom(IEntity parentEntity, object userData); + + /// + /// 实体轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + void OnUpdate(float elapseSeconds, float realElapseSeconds); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntity.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntity.cs.meta new file mode 100644 index 0000000..ab48454 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3e9325b75955dd74e95ae66daf83152b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityGroup.cs new file mode 100644 index 0000000..0b14855 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityGroup.cs @@ -0,0 +1,145 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.Entity +{ + /// + /// 实体组接口。 + /// + public interface IEntityGroup + { + /// + /// 获取实体组名称。 + /// + string Name + { + get; + } + + /// + /// 获取实体组中实体数量。 + /// + int EntityCount + { + get; + } + + /// + /// 获取或设置实体组实例对象池自动释放可释放对象的间隔秒数。 + /// + float InstanceAutoReleaseInterval + { + get; + set; + } + + /// + /// 获取或设置实体组实例对象池的容量。 + /// + int InstanceCapacity + { + get; + set; + } + + /// + /// 获取或设置实体组实例对象池对象过期秒数。 + /// + float InstanceExpireTime + { + get; + set; + } + + /// + /// 获取或设置实体组实例对象池的优先级。 + /// + int InstancePriority + { + get; + set; + } + + /// + /// 获取实体组辅助器。 + /// + IEntityGroupHelper Helper + { + get; + } + + /// + /// 实体组中是否存在实体。 + /// + /// 实体序列编号。 + /// 实体组中是否存在实体。 + bool HasEntity(int entityId); + + /// + /// 实体组中是否存在实体。 + /// + /// 实体资源名称。 + /// 实体组中是否存在实体。 + bool HasEntity(string entityAssetName); + + /// + /// 从实体组中获取实体。 + /// + /// 实体序列编号。 + /// 要获取的实体。 + IEntity GetEntity(int entityId); + + /// + /// 从实体组中获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + IEntity GetEntity(string entityAssetName); + + /// + /// 从实体组中获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + IEntity[] GetEntities(string entityAssetName); + + /// + /// 从实体组中获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + void GetEntities(string entityAssetName, List results); + + /// + /// 从实体组中获取所有实体。 + /// + /// 实体组中的所有实体。 + IEntity[] GetAllEntities(); + + /// + /// 从实体组中获取所有实体。 + /// + /// 实体组中的所有实体。 + void GetAllEntities(List results); + + /// + /// 设置实体实例是否被加锁。 + /// + /// 实体实例。 + /// 实体实例是否被加锁。 + void SetEntityInstanceLocked(object entityInstance, bool locked); + + /// + /// 设置实体实例的优先级。 + /// + /// 实体实例。 + /// 实体实例优先级。 + void SetEntityInstancePriority(object entityInstance, int priority); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityGroup.cs.meta new file mode 100644 index 0000000..c71ff6f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f78f0cfcfbd44cf48902c7d9eb72932d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityGroupHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityGroupHelper.cs new file mode 100644 index 0000000..fe58e00 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityGroupHelper.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Entity +{ + /// + /// 实体组辅助器接口。 + /// + public interface IEntityGroupHelper + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityGroupHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityGroupHelper.cs.meta new file mode 100644 index 0000000..5346fe7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityGroupHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cadd2228fcd4e884c97821773e45413d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityHelper.cs new file mode 100644 index 0000000..4caeba4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityHelper.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Entity +{ + /// + /// 实体辅助器接口。 + /// + public interface IEntityHelper + { + /// + /// 实例化实体。 + /// + /// 要实例化的实体资源。 + /// 实例化后的实体。 + object InstantiateEntity(object entityAsset); + + /// + /// 创建实体。 + /// + /// 实体实例。 + /// 实体所属的实体组。 + /// 用户自定义数据。 + /// 实体。 + IEntity CreateEntity(object entityInstance, IEntityGroup entityGroup, object userData); + + /// + /// 释放实体。 + /// + /// 要释放的实体资源。 + /// 要释放的实体实例。 + void ReleaseEntity(object entityAsset, object entityInstance); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityHelper.cs.meta new file mode 100644 index 0000000..4337ae2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f2b89f697c0c2424f85ffaf83748f770 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityManager.cs new file mode 100644 index 0000000..f5b59f2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityManager.cs @@ -0,0 +1,450 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.ObjectPool; +using GameFramework.Resource; +using System; +using System.Collections.Generic; + +namespace GameFramework.Entity +{ + /// + /// 实体管理器接口。 + /// + public interface IEntityManager + { + /// + /// 获取实体数量。 + /// + int EntityCount + { + get; + } + + /// + /// 获取实体组数量。 + /// + int EntityGroupCount + { + get; + } + + /// + /// 显示实体成功事件。 + /// + event EventHandler ShowEntitySuccess; + + /// + /// 显示实体失败事件。 + /// + event EventHandler ShowEntityFailure; + + /// + /// 显示实体更新事件。 + /// + event EventHandler ShowEntityUpdate; + + /// + /// 显示实体时加载依赖资源事件。 + /// + event EventHandler ShowEntityDependencyAsset; + + /// + /// 隐藏实体完成事件。 + /// + event EventHandler HideEntityComplete; + + /// + /// 设置对象池管理器。 + /// + /// 对象池管理器。 + void SetObjectPoolManager(IObjectPoolManager objectPoolManager); + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + void SetResourceManager(IResourceManager resourceManager); + + /// + /// 设置实体辅助器。 + /// + /// 实体辅助器。 + void SetEntityHelper(IEntityHelper entityHelper); + + /// + /// 是否存在实体组。 + /// + /// 实体组名称。 + /// 是否存在实体组。 + bool HasEntityGroup(string entityGroupName); + + /// + /// 获取实体组。 + /// + /// 实体组名称。 + /// 要获取的实体组。 + IEntityGroup GetEntityGroup(string entityGroupName); + + /// + /// 获取所有实体组。 + /// + /// 所有实体组。 + IEntityGroup[] GetAllEntityGroups(); + + /// + /// 获取所有实体组。 + /// + /// 所有实体组。 + void GetAllEntityGroups(List results); + + /// + /// 增加实体组。 + /// + /// 实体组名称。 + /// 实体实例对象池自动释放可释放对象的间隔秒数。 + /// 实体实例对象池容量。 + /// 实体实例对象池对象过期秒数。 + /// 实体实例对象池的优先级。 + /// 实体组辅助器。 + /// 是否增加实体组成功。 + bool AddEntityGroup(string entityGroupName, float instanceAutoReleaseInterval, int instanceCapacity, float instanceExpireTime, int instancePriority, IEntityGroupHelper entityGroupHelper); + + /// + /// 是否存在实体。 + /// + /// 实体编号。 + /// 是否存在实体。 + bool HasEntity(int entityId); + + /// + /// 是否存在实体。 + /// + /// 实体资源名称。 + /// 是否存在实体。 + bool HasEntity(string entityAssetName); + + /// + /// 获取实体。 + /// + /// 实体编号。 + /// 要获取的实体。 + IEntity GetEntity(int entityId); + + /// + /// 获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + IEntity GetEntity(string entityAssetName); + + /// + /// 获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + IEntity[] GetEntities(string entityAssetName); + + /// + /// 获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + void GetEntities(string entityAssetName, List results); + + /// + /// 获取所有已加载的实体。 + /// + /// 所有已加载的实体。 + IEntity[] GetAllLoadedEntities(); + + /// + /// 获取所有已加载的实体。 + /// + /// 所有已加载的实体。 + void GetAllLoadedEntities(List results); + + /// + /// 获取所有正在加载实体的编号。 + /// + /// 所有正在加载实体的编号。 + int[] GetAllLoadingEntityIds(); + + /// + /// 获取所有正在加载实体的编号。 + /// + /// 所有正在加载实体的编号。 + void GetAllLoadingEntityIds(List results); + + /// + /// 是否正在加载实体。 + /// + /// 实体编号。 + /// 是否正在加载实体。 + bool IsLoadingEntity(int entityId); + + /// + /// 是否是合法的实体。 + /// + /// 实体。 + /// 实体是否合法。 + bool IsValidEntity(IEntity entity); + + /// + /// 显示实体。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + void ShowEntity(int entityId, string entityAssetName, string entityGroupName); + + /// + /// 显示实体。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + /// 加载实体资源的优先级。 + void ShowEntity(int entityId, string entityAssetName, string entityGroupName, int priority); + + /// + /// 显示实体。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + /// 用户自定义数据。 + void ShowEntity(int entityId, string entityAssetName, string entityGroupName, object userData); + + /// + /// 显示实体。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + /// 加载实体资源的优先级。 + /// 用户自定义数据。 + void ShowEntity(int entityId, string entityAssetName, string entityGroupName, int priority, object userData); + + /// + /// 隐藏实体。 + /// + /// 实体编号。 + void HideEntity(int entityId); + + /// + /// 隐藏实体。 + /// + /// 实体编号。 + /// 用户自定义数据。 + void HideEntity(int entityId, object userData); + + /// + /// 隐藏实体。 + /// + /// 实体。 + void HideEntity(IEntity entity); + + /// + /// 隐藏实体。 + /// + /// 实体。 + /// 用户自定义数据。 + void HideEntity(IEntity entity, object userData); + + /// + /// 隐藏所有已加载的实体。 + /// + void HideAllLoadedEntities(); + + /// + /// 隐藏所有已加载的实体。 + /// + /// 用户自定义数据。 + void HideAllLoadedEntities(object userData); + + /// + /// 隐藏所有正在加载的实体。 + /// + void HideAllLoadingEntities(); + + /// + /// 获取父实体。 + /// + /// 要获取父实体的子实体的实体编号。 + /// 子实体的父实体。 + IEntity GetParentEntity(int childEntityId); + + /// + /// 获取父实体。 + /// + /// 要获取父实体的子实体。 + /// 子实体的父实体。 + IEntity GetParentEntity(IEntity childEntity); + + /// + /// 获取子实体数量。 + /// + /// 要获取子实体数量的父实体的实体编号。 + /// 子实体数量。 + int GetChildEntityCount(int parentEntityId); + + /// + /// 获取子实体。 + /// + /// 要获取子实体的父实体的实体编号。 + /// 子实体。 + IEntity GetChildEntity(int parentEntityId); + + /// + /// 获取子实体。 + /// + /// 要获取子实体的父实体。 + /// 子实体。 + IEntity GetChildEntity(IEntity parentEntity); + + /// + /// 获取所有子实体。 + /// + /// 要获取所有子实体的父实体的实体编号。 + /// 所有子实体。 + IEntity[] GetChildEntities(int parentEntityId); + + /// + /// 获取所有子实体。 + /// + /// 要获取所有子实体的父实体的实体编号。 + /// 所有子实体。 + void GetChildEntities(int parentEntityId, List results); + + /// + /// 获取所有子实体。 + /// + /// 要获取所有子实体的父实体。 + /// 所有子实体。 + IEntity[] GetChildEntities(IEntity parentEntity); + + /// + /// 获取所有子实体。 + /// + /// 要获取所有子实体的父实体。 + /// 所有子实体。 + void GetChildEntities(IEntity parentEntity, List results); + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体的实体编号。 + void AttachEntity(int childEntityId, int parentEntityId); + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体的实体编号。 + /// 用户自定义数据。 + void AttachEntity(int childEntityId, int parentEntityId, object userData); + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体。 + void AttachEntity(int childEntityId, IEntity parentEntity); + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体。 + /// 用户自定义数据。 + void AttachEntity(int childEntityId, IEntity parentEntity, object userData); + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体的实体编号。 + void AttachEntity(IEntity childEntity, int parentEntityId); + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体的实体编号。 + /// 用户自定义数据。 + void AttachEntity(IEntity childEntity, int parentEntityId, object userData); + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体。 + void AttachEntity(IEntity childEntity, IEntity parentEntity); + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体。 + /// 用户自定义数据。 + void AttachEntity(IEntity childEntity, IEntity parentEntity, object userData); + + /// + /// 解除子实体。 + /// + /// 要解除的子实体的实体编号。 + void DetachEntity(int childEntityId); + + /// + /// 解除子实体。 + /// + /// 要解除的子实体的实体编号。 + /// 用户自定义数据。 + void DetachEntity(int childEntityId, object userData); + + /// + /// 解除子实体。 + /// + /// 要解除的子实体。 + void DetachEntity(IEntity childEntity); + + /// + /// 解除子实体。 + /// + /// 要解除的子实体。 + /// 用户自定义数据。 + void DetachEntity(IEntity childEntity, object userData); + + /// + /// 解除所有子实体。 + /// + /// 被解除的父实体的实体编号。 + void DetachChildEntities(int parentEntityId); + + /// + /// 解除所有子实体。 + /// + /// 被解除的父实体的实体编号。 + /// 用户自定义数据。 + void DetachChildEntities(int parentEntityId, object userData); + + /// + /// 解除所有子实体。 + /// + /// 被解除的父实体。 + void DetachChildEntities(IEntity parentEntity); + + /// + /// 解除所有子实体。 + /// + /// 被解除的父实体。 + /// 用户自定义数据。 + void DetachChildEntities(IEntity parentEntity, object userData); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityManager.cs.meta new file mode 100644 index 0000000..795f83c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/IEntityManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af86c0d3edb7a334f9bf80e25c54393e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityDependencyAssetEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityDependencyAssetEventArgs.cs new file mode 100644 index 0000000..41453f5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityDependencyAssetEventArgs.cs @@ -0,0 +1,130 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Entity +{ + /// + /// 显示实体时加载依赖资源事件。 + /// + public sealed class ShowEntityDependencyAssetEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化显示实体时加载依赖资源事件的新实例。 + /// + public ShowEntityDependencyAssetEventArgs() + { + EntityId = 0; + EntityAssetName = null; + EntityGroupName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + + /// + /// 获取实体编号。 + /// + public int EntityId + { + get; + private set; + } + + /// + /// 获取实体资源名称。 + /// + public string EntityAssetName + { + get; + private set; + } + + /// + /// 获取实体组名称。 + /// + public string EntityGroupName + { + get; + private set; + } + + /// + /// 获取被加载的依赖资源名称。 + /// + public string DependencyAssetName + { + get; + private set; + } + + /// + /// 获取当前已加载依赖资源数量。 + /// + public int LoadedCount + { + get; + private set; + } + + /// + /// 获取总共加载依赖资源数量。 + /// + public int TotalCount + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建显示实体时加载依赖资源事件。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + /// 被加载的依赖资源名称。 + /// 当前已加载依赖资源数量。 + /// 总共加载依赖资源数量。 + /// 用户自定义数据。 + /// 创建的显示实体时加载依赖资源事件。 + public static ShowEntityDependencyAssetEventArgs Create(int entityId, string entityAssetName, string entityGroupName, string dependencyAssetName, int loadedCount, int totalCount, object userData) + { + ShowEntityDependencyAssetEventArgs showEntityDependencyAssetEventArgs = ReferencePool.Acquire(); + showEntityDependencyAssetEventArgs.EntityId = entityId; + showEntityDependencyAssetEventArgs.EntityAssetName = entityAssetName; + showEntityDependencyAssetEventArgs.EntityGroupName = entityGroupName; + showEntityDependencyAssetEventArgs.DependencyAssetName = dependencyAssetName; + showEntityDependencyAssetEventArgs.LoadedCount = loadedCount; + showEntityDependencyAssetEventArgs.TotalCount = totalCount; + showEntityDependencyAssetEventArgs.UserData = userData; + return showEntityDependencyAssetEventArgs; + } + + /// + /// 清理显示实体时加载依赖资源事件。 + /// + public override void Clear() + { + EntityId = 0; + EntityAssetName = null; + EntityGroupName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityDependencyAssetEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityDependencyAssetEventArgs.cs.meta new file mode 100644 index 0000000..b66b5de --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityDependencyAssetEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c29f7f51222af0341a969a26afe74341 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityFailureEventArgs.cs new file mode 100644 index 0000000..4f63476 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityFailureEventArgs.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Entity +{ + /// + /// 显示实体失败事件。 + /// + public sealed class ShowEntityFailureEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化显示实体失败事件的新实例。 + /// + public ShowEntityFailureEventArgs() + { + EntityId = 0; + EntityAssetName = null; + EntityGroupName = null; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取实体编号。 + /// + public int EntityId + { + get; + private set; + } + + /// + /// 获取实体资源名称。 + /// + public string EntityAssetName + { + get; + private set; + } + + /// + /// 获取实体组名称。 + /// + public string EntityGroupName + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建显示实体失败事件。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + /// 错误信息。 + /// 用户自定义数据。 + /// 创建的显示实体失败事件。 + public static ShowEntityFailureEventArgs Create(int entityId, string entityAssetName, string entityGroupName, string errorMessage, object userData) + { + ShowEntityFailureEventArgs showEntityFailureEventArgs = ReferencePool.Acquire(); + showEntityFailureEventArgs.EntityId = entityId; + showEntityFailureEventArgs.EntityAssetName = entityAssetName; + showEntityFailureEventArgs.EntityGroupName = entityGroupName; + showEntityFailureEventArgs.ErrorMessage = errorMessage; + showEntityFailureEventArgs.UserData = userData; + return showEntityFailureEventArgs; + } + + /// + /// 清理显示实体失败事件。 + /// + public override void Clear() + { + EntityId = 0; + EntityAssetName = null; + EntityGroupName = null; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityFailureEventArgs.cs.meta new file mode 100644 index 0000000..4d0eb8e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6c68aefb100bc724ca3ff7106978d008 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntitySuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntitySuccessEventArgs.cs new file mode 100644 index 0000000..7928977 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntitySuccessEventArgs.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Entity +{ + /// + /// 显示实体成功事件。 + /// + public sealed class ShowEntitySuccessEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化显示实体成功事件的新实例。 + /// + public ShowEntitySuccessEventArgs() + { + Entity = null; + Duration = 0f; + UserData = null; + } + + /// + /// 获取显示成功的实体。 + /// + public IEntity Entity + { + get; + private set; + } + + /// + /// 获取加载持续时间。 + /// + public float Duration + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建显示实体成功事件。 + /// + /// 加载成功的实体。 + /// 加载持续时间。 + /// 用户自定义数据。 + /// 创建的显示实体成功事件。 + public static ShowEntitySuccessEventArgs Create(IEntity entity, float duration, object userData) + { + ShowEntitySuccessEventArgs showEntitySuccessEventArgs = ReferencePool.Acquire(); + showEntitySuccessEventArgs.Entity = entity; + showEntitySuccessEventArgs.Duration = duration; + showEntitySuccessEventArgs.UserData = userData; + return showEntitySuccessEventArgs; + } + + /// + /// 清理显示实体成功事件。 + /// + public override void Clear() + { + Entity = null; + Duration = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntitySuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntitySuccessEventArgs.cs.meta new file mode 100644 index 0000000..324c74e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntitySuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4637c464d89e11e42a2125e46d7b4fb3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityUpdateEventArgs.cs new file mode 100644 index 0000000..e24b9a0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityUpdateEventArgs.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Entity +{ + /// + /// 显示实体更新事件。 + /// + public sealed class ShowEntityUpdateEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化显示实体更新事件的新实例。 + /// + public ShowEntityUpdateEventArgs() + { + EntityId = 0; + EntityAssetName = null; + EntityGroupName = null; + Progress = 0f; + UserData = null; + } + + /// + /// 获取实体编号。 + /// + public int EntityId + { + get; + private set; + } + + /// + /// 获取实体资源名称。 + /// + public string EntityAssetName + { + get; + private set; + } + + /// + /// 获取实体组名称。 + /// + public string EntityGroupName + { + get; + private set; + } + + /// + /// 获取显示实体进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建显示实体更新事件。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + /// 显示实体进度。 + /// 用户自定义数据。 + /// 创建的显示实体更新事件。 + public static ShowEntityUpdateEventArgs Create(int entityId, string entityAssetName, string entityGroupName, float progress, object userData) + { + ShowEntityUpdateEventArgs showEntityUpdateEventArgs = ReferencePool.Acquire(); + showEntityUpdateEventArgs.EntityId = entityId; + showEntityUpdateEventArgs.EntityAssetName = entityAssetName; + showEntityUpdateEventArgs.EntityGroupName = entityGroupName; + showEntityUpdateEventArgs.Progress = progress; + showEntityUpdateEventArgs.UserData = userData; + return showEntityUpdateEventArgs; + } + + /// + /// 清理显示实体更新事件。 + /// + public override void Clear() + { + EntityId = 0; + EntityAssetName = null; + EntityGroupName = null; + Progress = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityUpdateEventArgs.cs.meta new file mode 100644 index 0000000..adf95e8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Entity/ShowEntityUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 11d44af5d8234634db75a886ac49bd38 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event.meta new file mode 100644 index 0000000..27485f0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fe4730f3ed4392c488fb14d1d8528085 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/EventManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/EventManager.cs new file mode 100644 index 0000000..fcf6451 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/EventManager.cs @@ -0,0 +1,149 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.Event +{ + /// + /// 事件管理器。 + /// + internal sealed class EventManager : GameFrameworkModule, IEventManager + { + private readonly EventPool m_EventPool; + + /// + /// 初始化事件管理器的新实例。 + /// + public EventManager() + { + m_EventPool = new EventPool(EventPoolMode.AllowNoHandler | EventPoolMode.AllowMultiHandler); + } + + /// + /// 获取事件处理函数的数量。 + /// + public int EventHandlerCount + { + get + { + return m_EventPool.EventHandlerCount; + } + } + + /// + /// 获取事件数量。 + /// + public int EventCount + { + get + { + return m_EventPool.EventCount; + } + } + + /// + /// 获取游戏框架模块优先级。 + /// + /// 优先级较高的模块会优先轮询,并且关闭操作会后进行。 + internal override int Priority + { + get + { + return 7; + } + } + + /// + /// 事件管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + m_EventPool.Update(elapseSeconds, realElapseSeconds); + } + + /// + /// 关闭并清理事件管理器。 + /// + internal override void Shutdown() + { + m_EventPool.Shutdown(); + } + + /// + /// 获取事件处理函数的数量。 + /// + /// 事件类型编号。 + /// 事件处理函数的数量。 + public int Count(int id) + { + return m_EventPool.Count(id); + } + + /// + /// 检查是否存在事件处理函数。 + /// + /// 事件类型编号。 + /// 要检查的事件处理函数。 + /// 是否存在事件处理函数。 + public bool Check(int id, EventHandler handler) + { + return m_EventPool.Check(id, handler); + } + + /// + /// 订阅事件处理函数。 + /// + /// 事件类型编号。 + /// 要订阅的事件处理函数。 + public void Subscribe(int id, EventHandler handler) + { + m_EventPool.Subscribe(id, handler); + } + + /// + /// 取消订阅事件处理函数。 + /// + /// 事件类型编号。 + /// 要取消订阅的事件处理函数。 + public void Unsubscribe(int id, EventHandler handler) + { + m_EventPool.Unsubscribe(id, handler); + } + + /// + /// 设置默认事件处理函数。 + /// + /// 要设置的默认事件处理函数。 + public void SetDefaultHandler(EventHandler handler) + { + m_EventPool.SetDefaultHandler(handler); + } + + /// + /// 抛出事件,这个操作是线程安全的,即使不在主线程中抛出,也可保证在主线程中回调事件处理函数,但事件会在抛出后的下一帧分发。 + /// + /// 事件源。 + /// 事件参数。 + public void Fire(object sender, GameEventArgs e) + { + m_EventPool.Fire(sender, e); + } + + /// + /// 抛出事件立即模式,这个操作不是线程安全的,事件会立刻分发。 + /// + /// 事件源。 + /// 事件参数。 + public void FireNow(object sender, GameEventArgs e) + { + m_EventPool.FireNow(sender, e); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/EventManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/EventManager.cs.meta new file mode 100644 index 0000000..5aefea9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/EventManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c3969249ba61301478e1f8c0d86944c2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/GameEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/GameEventArgs.cs new file mode 100644 index 0000000..6c04619 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/GameEventArgs.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Event +{ + /// + /// 游戏逻辑事件基类。 + /// + public abstract class GameEventArgs : BaseEventArgs + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/GameEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/GameEventArgs.cs.meta new file mode 100644 index 0000000..111a40d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/GameEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 276f510fe7a726442af464e396fba336 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/IEventManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/IEventManager.cs new file mode 100644 index 0000000..02d0f6a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/IEventManager.cs @@ -0,0 +1,82 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.Event +{ + /// + /// 事件管理器接口。 + /// + public interface IEventManager + { + /// + /// 获取事件处理函数的数量。 + /// + int EventHandlerCount + { + get; + } + + /// + /// 获取事件数量。 + /// + int EventCount + { + get; + } + + /// + /// 获取事件处理函数的数量。 + /// + /// 事件类型编号。 + /// 事件处理函数的数量。 + int Count(int id); + + /// + /// 检查是否存在事件处理函数。 + /// + /// 事件类型编号。 + /// 要检查的事件处理函数。 + /// 是否存在事件处理函数。 + bool Check(int id, EventHandler handler); + + /// + /// 订阅事件处理函数。 + /// + /// 事件类型编号。 + /// 要订阅的事件处理函数。 + void Subscribe(int id, EventHandler handler); + + /// + /// 取消订阅事件处理函数。 + /// + /// 事件类型编号。 + /// 要取消订阅的事件处理函数。 + void Unsubscribe(int id, EventHandler handler); + + /// + /// 设置默认事件处理函数。 + /// + /// 要设置的默认事件处理函数。 + void SetDefaultHandler(EventHandler handler); + + /// + /// 抛出事件,这个操作是线程安全的,即使不在主线程中抛出,也可保证在主线程中回调事件处理函数,但事件会在抛出后的下一帧分发。 + /// + /// 事件源。 + /// 事件参数。 + void Fire(object sender, GameEventArgs e); + + /// + /// 抛出事件立即模式,这个操作不是线程安全的,事件会立刻分发。 + /// + /// 事件源。 + /// 事件参数。 + void FireNow(object sender, GameEventArgs e); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/IEventManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/IEventManager.cs.meta new file mode 100644 index 0000000..7b2e98a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Event/IEventManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e67fdaacf6818b140b13b20e72e380dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem.meta new file mode 100644 index 0000000..87f6f54 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a82daa71a1304224eaeccf3065f59a7d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/CommonFileSystemStream.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/CommonFileSystemStream.cs new file mode 100644 index 0000000..4ca7d14 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/CommonFileSystemStream.cs @@ -0,0 +1,162 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.IO; + +namespace GameFramework.FileSystem +{ + /// + /// 通用文件系统流。 + /// + public sealed class CommonFileSystemStream : FileSystemStream, IDisposable + { + private readonly FileStream m_FileStream; + + /// + /// 初始化通用文件系统流的新实例。 + /// + /// 要加载的文件系统的完整路径。 + /// 要加载的文件系统的访问方式。 + /// 是否创建新的文件系统流。 + public CommonFileSystemStream(string fullPath, FileSystemAccess access, bool createNew) + { + if (string.IsNullOrEmpty(fullPath)) + { + throw new GameFrameworkException("Full path is invalid."); + } + + switch (access) + { + case FileSystemAccess.Read: + m_FileStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read); + break; + + case FileSystemAccess.Write: + m_FileStream = new FileStream(fullPath, createNew ? FileMode.Create : FileMode.Open, FileAccess.Write, FileShare.Read); + break; + + case FileSystemAccess.ReadWrite: + m_FileStream = new FileStream(fullPath, createNew ? FileMode.Create : FileMode.Open, FileAccess.ReadWrite, FileShare.Read); + break; + + default: + throw new GameFrameworkException("Access is invalid."); + } + } + + /// + /// 获取或设置文件系统流位置。 + /// + public override long Position + { + get + { + return m_FileStream.Position; + } + set + { + m_FileStream.Position = value; + } + } + + /// + /// 获取文件系统流长度。 + /// + public override long Length + { + get + { + return m_FileStream.Length; + } + } + + /// + /// 设置文件系统流长度。 + /// + /// 要设置的文件系统流的长度。 + public override void SetLength(long length) + { + m_FileStream.SetLength(length); + } + + /// + /// 定位文件系统流位置。 + /// + /// 要定位的文件系统流位置的偏移。 + /// 要定位的文件系统流位置的方式。 + public override void Seek(long offset, SeekOrigin origin) + { + m_FileStream.Seek(offset, origin); + } + + /// + /// 从文件系统流中读取一个字节。 + /// + /// 读取的字节,若已经到达文件结尾,则返回 -1。 + public override int ReadByte() + { + return m_FileStream.ReadByte(); + } + + /// + /// 从文件系统流中读取二进制流。 + /// + /// 存储读取文件内容的二进制流。 + /// 存储读取文件内容的二进制流的起始位置。 + /// 存储读取文件内容的二进制流的长度。 + /// 实际读取了多少字节。 + public override int Read(byte[] buffer, int startIndex, int length) + { + return m_FileStream.Read(buffer, startIndex, length); + } + + /// + /// 向文件系统流中写入一个字节。 + /// + /// 要写入的字节。 + public override void WriteByte(byte value) + { + m_FileStream.WriteByte(value); + } + + /// + /// 向文件系统流中写入二进制流。 + /// + /// 存储写入文件内容的二进制流。 + /// 存储写入文件内容的二进制流的起始位置。 + /// 存储写入文件内容的二进制流的长度。 + public override void Write(byte[] buffer, int startIndex, int length) + { + m_FileStream.Write(buffer, startIndex, length); + } + + /// + /// 将文件系统流立刻更新到存储介质中。 + /// + public override void Flush() + { + m_FileStream.Flush(); + } + + /// + /// 关闭文件系统流。 + /// + public override void Close() + { + m_FileStream.Close(); + } + + /// + /// 销毁文件系统流。 + /// + public void Dispose() + { + m_FileStream.Dispose(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/CommonFileSystemStream.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/CommonFileSystemStream.cs.meta new file mode 100644 index 0000000..cf89b6d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/CommonFileSystemStream.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c0009c925b8c6f646aa0604971a42813 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileInfo.cs new file mode 100644 index 0000000..8ad4895 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileInfo.cs @@ -0,0 +1,94 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.FileSystem +{ + /// + /// 文件信息。 + /// + [StructLayout(LayoutKind.Auto)] + public struct FileInfo + { + private readonly string m_Name; + private readonly long m_Offset; + private readonly int m_Length; + + /// + /// 初始化文件信息的新实例。 + /// + /// 文件名称。 + /// 文件偏移。 + /// 文件长度。 + public FileInfo(string name, long offset, int length) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + if (offset < 0L) + { + throw new GameFrameworkException("Offset is invalid."); + } + + if (length < 0) + { + throw new GameFrameworkException("Length is invalid."); + } + + m_Name = name; + m_Offset = offset; + m_Length = length; + } + + /// + /// 获取文件信息是否有效。 + /// + public bool IsValid + { + get + { + return !string.IsNullOrEmpty(m_Name) && m_Offset >= 0L && m_Length >= 0; + } + } + + /// + /// 获取文件名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取文件偏移。 + /// + public long Offset + { + get + { + return m_Offset; + } + } + + /// + /// 获取文件长度。 + /// + public int Length + { + get + { + return m_Length; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileInfo.cs.meta new file mode 100644 index 0000000..96fe25e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f925951dd3c2201418a72c3592fa64e4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.BlockData.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.BlockData.cs new file mode 100644 index 0000000..6f75d9d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.BlockData.cs @@ -0,0 +1,76 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.FileSystem +{ + internal sealed partial class FileSystem : IFileSystem + { + /// + /// 块数据。 + /// + [StructLayout(LayoutKind.Sequential)] + private struct BlockData + { + public static readonly BlockData Empty = new BlockData(0, 0); + + private readonly int m_StringIndex; + private readonly int m_ClusterIndex; + private readonly int m_Length; + + public BlockData(int clusterIndex, int length) + : this(-1, clusterIndex, length) + { + } + + public BlockData(int stringIndex, int clusterIndex, int length) + { + m_StringIndex = stringIndex; + m_ClusterIndex = clusterIndex; + m_Length = length; + } + + public bool Using + { + get + { + return m_StringIndex >= 0; + } + } + + public int StringIndex + { + get + { + return m_StringIndex; + } + } + + public int ClusterIndex + { + get + { + return m_ClusterIndex; + } + } + + public int Length + { + get + { + return m_Length; + } + } + + public BlockData Free() + { + return new BlockData(m_ClusterIndex, (int)GetUpBoundClusterOffset(m_Length)); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.BlockData.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.BlockData.cs.meta new file mode 100644 index 0000000..c3b4fa4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.BlockData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 673f7b724e40aa34882b02487b912702 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.HeaderData.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.HeaderData.cs new file mode 100644 index 0000000..9428cd6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.HeaderData.cs @@ -0,0 +1,105 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.FileSystem +{ + internal sealed partial class FileSystem : IFileSystem + { + /// + /// 头数据。 + /// + [StructLayout(LayoutKind.Sequential)] + private struct HeaderData + { + private const int HeaderLength = 3; + private const int FileSystemVersion = 0; + private const int EncryptBytesLength = 4; + private static readonly byte[] Header = new byte[HeaderLength] { (byte)'G', (byte)'F', (byte)'F' }; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = HeaderLength)] + private readonly byte[] m_Header; + + private readonly byte m_Version; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = EncryptBytesLength)] + private readonly byte[] m_EncryptBytes; + + private readonly int m_MaxFileCount; + private readonly int m_MaxBlockCount; + private readonly int m_BlockCount; + + public HeaderData(int maxFileCount, int maxBlockCount) + : this(FileSystemVersion, new byte[EncryptBytesLength], maxFileCount, maxBlockCount, 0) + { + Utility.Random.GetRandomBytes(m_EncryptBytes); + } + + public HeaderData(byte version, byte[] encryptBytes, int maxFileCount, int maxBlockCount, int blockCount) + { + m_Header = Header; + m_Version = version; + m_EncryptBytes = encryptBytes; + m_MaxFileCount = maxFileCount; + m_MaxBlockCount = maxBlockCount; + m_BlockCount = blockCount; + } + + public bool IsValid + { + get + { + return m_Header.Length == HeaderLength && m_Header[0] == Header[0] && m_Header[1] == Header[1] && m_Header[2] == Header[2] && m_Version == FileSystemVersion && m_EncryptBytes.Length == EncryptBytesLength + && m_MaxFileCount > 0 && m_MaxBlockCount > 0 && m_MaxFileCount <= m_MaxBlockCount && m_BlockCount > 0 && m_BlockCount <= m_MaxBlockCount; + } + } + + public byte Version + { + get + { + return m_Version; + } + } + + public int MaxFileCount + { + get + { + return m_MaxFileCount; + } + } + + public int MaxBlockCount + { + get + { + return m_MaxBlockCount; + } + } + + public int BlockCount + { + get + { + return m_BlockCount; + } + } + + public byte[] GetEncryptBytes() + { + return m_EncryptBytes; + } + + public HeaderData SetBlockCount(int blockCount) + { + return new HeaderData(m_Version, m_EncryptBytes, m_MaxFileCount, m_MaxBlockCount, blockCount); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.HeaderData.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.HeaderData.cs.meta new file mode 100644 index 0000000..7041853 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.HeaderData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 65f96dfcbe4107442afb1b46ac24a1bf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.StringData.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.StringData.cs new file mode 100644 index 0000000..bc4b46b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.StringData.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Runtime.InteropServices; + +namespace GameFramework.FileSystem +{ + internal sealed partial class FileSystem : IFileSystem + { + /// + /// 字符串数据。 + /// + [StructLayout(LayoutKind.Sequential)] + private struct StringData + { + private static readonly byte[] s_CachedBytes = new byte[byte.MaxValue + 1]; + + private readonly byte m_Length; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = byte.MaxValue)] + private readonly byte[] m_Bytes; + + public StringData(byte length, byte[] bytes) + { + m_Length = length; + m_Bytes = bytes; + } + + public string GetString(byte[] encryptBytes) + { + if (m_Length <= 0) + { + return null; + } + + Array.Copy(m_Bytes, 0, s_CachedBytes, 0, m_Length); + Utility.Encryption.GetSelfXorBytes(s_CachedBytes, 0, m_Length, encryptBytes); + return Utility.Converter.GetString(s_CachedBytes, 0, m_Length); + } + + public StringData SetString(string value, byte[] encryptBytes) + { + if (string.IsNullOrEmpty(value)) + { + return Clear(); + } + + int length = Utility.Converter.GetBytes(value, s_CachedBytes); + if (length > byte.MaxValue) + { + throw new GameFrameworkException(Utility.Text.Format("String '{0}' is too long.", value)); + } + + Utility.Encryption.GetSelfXorBytes(s_CachedBytes, encryptBytes); + Array.Copy(s_CachedBytes, 0, m_Bytes, 0, length); + return new StringData((byte)length, m_Bytes); + } + + public StringData Clear() + { + return new StringData(0, m_Bytes); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.StringData.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.StringData.cs.meta new file mode 100644 index 0000000..81361f3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.StringData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0b63c47b17be2754380fb9201e7cb5e0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.cs new file mode 100644 index 0000000..f1af280 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.cs @@ -0,0 +1,1381 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; + +namespace GameFramework.FileSystem +{ + /// + /// 文件系统。 + /// + internal sealed partial class FileSystem : IFileSystem + { + private const int ClusterSize = 1024 * 4; + private const int CachedBytesLength = 0x1000; + + private static readonly string[] EmptyStringArray = new string[] { }; + private static readonly byte[] s_CachedBytes = new byte[CachedBytesLength]; + + private static readonly int HeaderDataSize = Marshal.SizeOf(typeof(HeaderData)); + private static readonly int BlockDataSize = Marshal.SizeOf(typeof(BlockData)); + private static readonly int StringDataSize = Marshal.SizeOf(typeof(StringData)); + + private readonly string m_FullPath; + private readonly FileSystemAccess m_Access; + private readonly FileSystemStream m_Stream; + private readonly Dictionary m_FileDatas; + private readonly List m_BlockDatas; + private readonly GameFrameworkMultiDictionary m_FreeBlockIndexes; + private readonly SortedDictionary m_StringDatas; + private readonly Queue m_FreeStringIndexes; + private readonly Queue m_FreeStringDatas; + + private HeaderData m_HeaderData; + private int m_BlockDataOffset; + private int m_StringDataOffset; + private int m_FileDataOffset; + + /// + /// 初始化文件系统的新实例。 + /// + /// 文件系统完整路径。 + /// 文件系统访问方式。 + /// 文件系统流。 + private FileSystem(string fullPath, FileSystemAccess access, FileSystemStream stream) + { + if (string.IsNullOrEmpty(fullPath)) + { + throw new GameFrameworkException("Full path is invalid."); + } + + if (access == FileSystemAccess.Unspecified) + { + throw new GameFrameworkException("Access is invalid."); + } + + if (stream == null) + { + throw new GameFrameworkException("Stream is invalid."); + } + + m_FullPath = fullPath; + m_Access = access; + m_Stream = stream; + m_FileDatas = new Dictionary(StringComparer.Ordinal); + m_BlockDatas = new List(); + m_FreeBlockIndexes = new GameFrameworkMultiDictionary(); + m_StringDatas = new SortedDictionary(); + m_FreeStringIndexes = new Queue(); + m_FreeStringDatas = new Queue(); + + m_HeaderData = default(HeaderData); + m_BlockDataOffset = 0; + m_StringDataOffset = 0; + m_FileDataOffset = 0; + + Utility.Marshal.EnsureCachedHGlobalSize(CachedBytesLength); + } + + /// + /// 获取文件系统完整路径。 + /// + public string FullPath + { + get + { + return m_FullPath; + } + } + + /// + /// 获取文件系统访问方式。 + /// + public FileSystemAccess Access + { + get + { + return m_Access; + } + } + + /// + /// 获取文件数量。 + /// + public int FileCount + { + get + { + return m_FileDatas.Count; + } + } + + /// + /// 获取最大文件数量。 + /// + public int MaxFileCount + { + get + { + return m_HeaderData.MaxFileCount; + } + } + + /// + /// 创建文件系统。 + /// + /// 要创建的文件系统的完整路径。 + /// 要创建的文件系统的访问方式。 + /// 要创建的文件系统的文件系统流。 + /// 要创建的文件系统的最大文件数量。 + /// 要创建的文件系统的最大块数据数量。 + /// 创建的文件系统。 + public static FileSystem Create(string fullPath, FileSystemAccess access, FileSystemStream stream, int maxFileCount, int maxBlockCount) + { + if (maxFileCount <= 0) + { + throw new GameFrameworkException("Max file count is invalid."); + } + + if (maxBlockCount <= 0) + { + throw new GameFrameworkException("Max block count is invalid."); + } + + if (maxFileCount > maxBlockCount) + { + throw new GameFrameworkException("Max file count can not larger than max block count."); + } + + FileSystem fileSystem = new FileSystem(fullPath, access, stream); + fileSystem.m_HeaderData = new HeaderData(maxFileCount, maxBlockCount); + CalcOffsets(fileSystem); + Utility.Marshal.StructureToBytes(fileSystem.m_HeaderData, HeaderDataSize, s_CachedBytes); + + try + { + stream.Write(s_CachedBytes, 0, HeaderDataSize); + stream.SetLength(fileSystem.m_FileDataOffset); + return fileSystem; + } + catch + { + fileSystem.Shutdown(); + return null; + } + } + + /// + /// 加载文件系统。 + /// + /// 要加载的文件系统的完整路径。 + /// 要加载的文件系统的访问方式。 + /// 要加载的文件系统的文件系统流。 + /// 加载的文件系统。 + public static FileSystem Load(string fullPath, FileSystemAccess access, FileSystemStream stream) + { + FileSystem fileSystem = new FileSystem(fullPath, access, stream); + + stream.Read(s_CachedBytes, 0, HeaderDataSize); + fileSystem.m_HeaderData = Utility.Marshal.BytesToStructure(HeaderDataSize, s_CachedBytes); + if (!fileSystem.m_HeaderData.IsValid) + { + return null; + } + + CalcOffsets(fileSystem); + + if (fileSystem.m_BlockDatas.Capacity < fileSystem.m_HeaderData.BlockCount) + { + fileSystem.m_BlockDatas.Capacity = fileSystem.m_HeaderData.BlockCount; + } + + for (int i = 0; i < fileSystem.m_HeaderData.BlockCount; i++) + { + stream.Read(s_CachedBytes, 0, BlockDataSize); + BlockData blockData = Utility.Marshal.BytesToStructure(BlockDataSize, s_CachedBytes); + fileSystem.m_BlockDatas.Add(blockData); + } + + for (int i = 0; i < fileSystem.m_BlockDatas.Count; i++) + { + BlockData blockData = fileSystem.m_BlockDatas[i]; + if (blockData.Using) + { + StringData stringData = fileSystem.ReadStringData(blockData.StringIndex); + fileSystem.m_StringDatas.Add(blockData.StringIndex, stringData); + fileSystem.m_FileDatas.Add(stringData.GetString(fileSystem.m_HeaderData.GetEncryptBytes()), i); + } + else + { + fileSystem.m_FreeBlockIndexes.Add(blockData.Length, i); + } + } + + int index = 0; + foreach (KeyValuePair i in fileSystem.m_StringDatas) + { + while (index < i.Key) + { + fileSystem.m_FreeStringIndexes.Enqueue(index++); + } + + index++; + } + + return fileSystem; + } + + /// + /// 关闭并清理文件系统。 + /// + public void Shutdown() + { + m_Stream.Close(); + + m_FileDatas.Clear(); + m_BlockDatas.Clear(); + m_FreeBlockIndexes.Clear(); + m_StringDatas.Clear(); + m_FreeStringIndexes.Clear(); + m_FreeStringDatas.Clear(); + + m_BlockDataOffset = 0; + m_StringDataOffset = 0; + m_FileDataOffset = 0; + } + + /// + /// 获取文件信息。 + /// + /// 要获取文件信息的文件名称。 + /// 获取的文件信息。 + public FileInfo GetFileInfo(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + int blockIndex = 0; + if (!m_FileDatas.TryGetValue(name, out blockIndex)) + { + return default(FileInfo); + } + + BlockData blockData = m_BlockDatas[blockIndex]; + return new FileInfo(name, GetClusterOffset(blockData.ClusterIndex), blockData.Length); + } + + /// + /// 获取所有文件信息。 + /// + /// 获取的所有文件信息。 + public FileInfo[] GetAllFileInfos() + { + int index = 0; + FileInfo[] results = new FileInfo[m_FileDatas.Count]; + foreach (KeyValuePair fileData in m_FileDatas) + { + BlockData blockData = m_BlockDatas[fileData.Value]; + results[index++] = new FileInfo(fileData.Key, GetClusterOffset(blockData.ClusterIndex), blockData.Length); + } + + return results; + } + + /// + /// 获取所有文件信息。 + /// + /// 获取的所有文件信息。 + public void GetAllFileInfos(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair fileData in m_FileDatas) + { + BlockData blockData = m_BlockDatas[fileData.Value]; + results.Add(new FileInfo(fileData.Key, GetClusterOffset(blockData.ClusterIndex), blockData.Length)); + } + } + + /// + /// 检查是否存在指定文件。 + /// + /// 要检查的文件名称。 + /// 是否存在指定文件。 + public bool HasFile(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + return m_FileDatas.ContainsKey(name); + } + + /// + /// 读取指定文件。 + /// + /// 要读取的文件名称。 + /// 存储读取文件内容的二进制流。 + public byte[] ReadFile(string name) + { + if (m_Access != FileSystemAccess.Read && m_Access != FileSystemAccess.ReadWrite) + { + throw new GameFrameworkException("File system is not readable."); + } + + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + FileInfo fileInfo = GetFileInfo(name); + if (!fileInfo.IsValid) + { + return null; + } + + int length = fileInfo.Length; + byte[] buffer = new byte[length]; + if (length > 0) + { + m_Stream.Position = fileInfo.Offset; + m_Stream.Read(buffer, 0, length); + } + + return buffer; + } + + /// + /// 读取指定文件。 + /// + /// 要读取的文件名称。 + /// 存储读取文件内容的二进制流。 + /// 实际读取了多少字节。 + public int ReadFile(string name, byte[] buffer) + { + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return ReadFile(name, buffer, 0, buffer.Length); + } + + /// + /// 读取指定文件。 + /// + /// 要读取的文件名称。 + /// 存储读取文件内容的二进制流。 + /// 存储读取文件内容的二进制流的起始位置。 + /// 实际读取了多少字节。 + public int ReadFile(string name, byte[] buffer, int startIndex) + { + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return ReadFile(name, buffer, startIndex, buffer.Length - startIndex); + } + + /// + /// 读取指定文件。 + /// + /// 要读取的文件名称。 + /// 存储读取文件内容的二进制流。 + /// 存储读取文件内容的二进制流的起始位置。 + /// 存储读取文件内容的二进制流的长度。 + /// 实际读取了多少字节。 + public int ReadFile(string name, byte[] buffer, int startIndex, int length) + { + if (m_Access != FileSystemAccess.Read && m_Access != FileSystemAccess.ReadWrite) + { + throw new GameFrameworkException("File system is not readable."); + } + + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + if (startIndex < 0 || length < 0 || startIndex + length > buffer.Length) + { + throw new GameFrameworkException("Start index or length is invalid."); + } + + FileInfo fileInfo = GetFileInfo(name); + if (!fileInfo.IsValid) + { + return 0; + } + + m_Stream.Position = fileInfo.Offset; + if (length > fileInfo.Length) + { + length = fileInfo.Length; + } + + if (length > 0) + { + return m_Stream.Read(buffer, startIndex, length); + } + + return 0; + } + + /// + /// 读取指定文件。 + /// + /// 要读取的文件名称。 + /// 存储读取文件内容的二进制流。 + /// 实际读取了多少字节。 + public int ReadFile(string name, Stream stream) + { + if (m_Access != FileSystemAccess.Read && m_Access != FileSystemAccess.ReadWrite) + { + throw new GameFrameworkException("File system is not readable."); + } + + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + if (stream == null) + { + throw new GameFrameworkException("Stream is invalid."); + } + + if (!stream.CanWrite) + { + throw new GameFrameworkException("Stream is not writable."); + } + + FileInfo fileInfo = GetFileInfo(name); + if (!fileInfo.IsValid) + { + return 0; + } + + int length = fileInfo.Length; + if (length > 0) + { + m_Stream.Position = fileInfo.Offset; + return m_Stream.Read(stream, length); + } + + return 0; + } + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 要读取片段的长度。 + /// 存储读取文件片段内容的二进制流。 + public byte[] ReadFileSegment(string name, int length) + { + return ReadFileSegment(name, 0, length); + } + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 要读取片段的偏移。 + /// 要读取片段的长度。 + /// 存储读取文件片段内容的二进制流。 + public byte[] ReadFileSegment(string name, int offset, int length) + { + if (m_Access != FileSystemAccess.Read && m_Access != FileSystemAccess.ReadWrite) + { + throw new GameFrameworkException("File system is not readable."); + } + + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + if (offset < 0) + { + throw new GameFrameworkException("Index is invalid."); + } + + if (length < 0) + { + throw new GameFrameworkException("Length is invalid."); + } + + FileInfo fileInfo = GetFileInfo(name); + if (!fileInfo.IsValid) + { + return null; + } + + if (offset > fileInfo.Length) + { + offset = fileInfo.Length; + } + + int leftLength = fileInfo.Length - offset; + if (length > leftLength) + { + length = leftLength; + } + + byte[] buffer = new byte[length]; + if (length > 0) + { + m_Stream.Position = fileInfo.Offset + offset; + m_Stream.Read(buffer, 0, length); + } + + return buffer; + } + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 存储读取文件片段内容的二进制流。 + /// 实际读取了多少字节。 + public int ReadFileSegment(string name, byte[] buffer) + { + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return ReadFileSegment(name, 0, buffer, 0, buffer.Length); + } + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 存储读取文件片段内容的二进制流。 + /// 要读取片段的长度。 + /// 实际读取了多少字节。 + public int ReadFileSegment(string name, byte[] buffer, int length) + { + return ReadFileSegment(name, 0, buffer, 0, length); + } + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 存储读取文件片段内容的二进制流。 + /// 存储读取文件片段内容的二进制流的起始位置。 + /// 要读取片段的长度。 + /// 实际读取了多少字节。 + public int ReadFileSegment(string name, byte[] buffer, int startIndex, int length) + { + return ReadFileSegment(name, 0, buffer, startIndex, length); + } + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 要读取片段的偏移。 + /// 存储读取文件片段内容的二进制流。 + /// 实际读取了多少字节。 + public int ReadFileSegment(string name, int offset, byte[] buffer) + { + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return ReadFileSegment(name, offset, buffer, 0, buffer.Length); + } + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 要读取片段的偏移。 + /// 存储读取文件片段内容的二进制流。 + /// 要读取片段的长度。 + /// 实际读取了多少字节。 + public int ReadFileSegment(string name, int offset, byte[] buffer, int length) + { + return ReadFileSegment(name, offset, buffer, 0, length); + } + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 要读取片段的偏移。 + /// 存储读取文件片段内容的二进制流。 + /// 存储读取文件片段内容的二进制流的起始位置。 + /// 要读取片段的长度。 + /// 实际读取了多少字节。 + public int ReadFileSegment(string name, int offset, byte[] buffer, int startIndex, int length) + { + if (m_Access != FileSystemAccess.Read && m_Access != FileSystemAccess.ReadWrite) + { + throw new GameFrameworkException("File system is not readable."); + } + + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + if (offset < 0) + { + throw new GameFrameworkException("Index is invalid."); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + if (startIndex < 0 || length < 0 || startIndex + length > buffer.Length) + { + throw new GameFrameworkException("Start index or length is invalid."); + } + + FileInfo fileInfo = GetFileInfo(name); + if (!fileInfo.IsValid) + { + return 0; + } + + if (offset > fileInfo.Length) + { + offset = fileInfo.Length; + } + + int leftLength = fileInfo.Length - offset; + if (length > leftLength) + { + length = leftLength; + } + + if (length > 0) + { + m_Stream.Position = fileInfo.Offset + offset; + return m_Stream.Read(buffer, startIndex, length); + } + + return 0; + } + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 存储读取文件片段内容的二进制流。 + /// 要读取片段的长度。 + /// 实际读取了多少字节。 + public int ReadFileSegment(string name, Stream stream, int length) + { + return ReadFileSegment(name, 0, stream, length); + } + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 要读取片段的偏移。 + /// 存储读取文件片段内容的二进制流。 + /// 要读取片段的长度。 + /// 实际读取了多少字节。 + public int ReadFileSegment(string name, int offset, Stream stream, int length) + { + if (m_Access != FileSystemAccess.Read && m_Access != FileSystemAccess.ReadWrite) + { + throw new GameFrameworkException("File system is not readable."); + } + + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + if (offset < 0) + { + throw new GameFrameworkException("Index is invalid."); + } + + if (stream == null) + { + throw new GameFrameworkException("Stream is invalid."); + } + + if (!stream.CanWrite) + { + throw new GameFrameworkException("Stream is not writable."); + } + + if (length < 0) + { + throw new GameFrameworkException("Length is invalid."); + } + + FileInfo fileInfo = GetFileInfo(name); + if (!fileInfo.IsValid) + { + return 0; + } + + if (offset > fileInfo.Length) + { + offset = fileInfo.Length; + } + + int leftLength = fileInfo.Length - offset; + if (length > leftLength) + { + length = leftLength; + } + + if (length > 0) + { + m_Stream.Position = fileInfo.Offset + offset; + return m_Stream.Read(stream, length); + } + + return 0; + } + + /// + /// 写入指定文件。 + /// + /// 要写入的文件名称。 + /// 存储写入文件内容的二进制流。 + /// 是否写入指定文件成功。 + public bool WriteFile(string name, byte[] buffer) + { + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return WriteFile(name, buffer, 0, buffer.Length); + } + + /// + /// 写入指定文件。 + /// + /// 要写入的文件名称。 + /// 存储写入文件内容的二进制流。 + /// 存储写入文件内容的二进制流的起始位置。 + /// 是否写入指定文件成功。 + public bool WriteFile(string name, byte[] buffer, int startIndex) + { + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return WriteFile(name, buffer, startIndex, buffer.Length - startIndex); + } + + /// + /// 写入指定文件。 + /// + /// 要写入的文件名称。 + /// 存储写入文件内容的二进制流。 + /// 存储写入文件内容的二进制流的起始位置。 + /// 存储写入文件内容的二进制流的长度。 + /// 是否写入指定文件成功。 + public bool WriteFile(string name, byte[] buffer, int startIndex, int length) + { + if (m_Access != FileSystemAccess.Write && m_Access != FileSystemAccess.ReadWrite) + { + throw new GameFrameworkException("File system is not writable."); + } + + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + if (name.Length > byte.MaxValue) + { + throw new GameFrameworkException(Utility.Text.Format("Name '{0}' is too long.", name)); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + if (startIndex < 0 || length < 0 || startIndex + length > buffer.Length) + { + throw new GameFrameworkException("Start index or length is invalid."); + } + + bool hasFile = false; + int oldBlockIndex = -1; + if (m_FileDatas.TryGetValue(name, out oldBlockIndex)) + { + hasFile = true; + } + + if (!hasFile && m_FileDatas.Count >= m_HeaderData.MaxFileCount) + { + return false; + } + + int blockIndex = AllocBlock(length); + if (blockIndex < 0) + { + return false; + } + + if (length > 0) + { + m_Stream.Position = GetClusterOffset(m_BlockDatas[blockIndex].ClusterIndex); + m_Stream.Write(buffer, startIndex, length); + } + + ProcessWriteFile(name, hasFile, oldBlockIndex, blockIndex, length); + m_Stream.Flush(); + return true; + } + + /// + /// 写入指定文件。 + /// + /// 要写入的文件名称。 + /// 存储写入文件内容的二进制流。 + /// 是否写入指定文件成功。 + public bool WriteFile(string name, Stream stream) + { + if (m_Access != FileSystemAccess.Write && m_Access != FileSystemAccess.ReadWrite) + { + throw new GameFrameworkException("File system is not writable."); + } + + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + if (name.Length > byte.MaxValue) + { + throw new GameFrameworkException(Utility.Text.Format("Name '{0}' is too long.", name)); + } + + if (stream == null) + { + throw new GameFrameworkException("Stream is invalid."); + } + + if (!stream.CanRead) + { + throw new GameFrameworkException("Stream is not readable."); + } + + bool hasFile = false; + int oldBlockIndex = -1; + if (m_FileDatas.TryGetValue(name, out oldBlockIndex)) + { + hasFile = true; + } + + if (!hasFile && m_FileDatas.Count >= m_HeaderData.MaxFileCount) + { + return false; + } + + int length = (int)(stream.Length - stream.Position); + int blockIndex = AllocBlock(length); + if (blockIndex < 0) + { + return false; + } + + if (length > 0) + { + m_Stream.Position = GetClusterOffset(m_BlockDatas[blockIndex].ClusterIndex); + m_Stream.Write(stream, length); + } + + ProcessWriteFile(name, hasFile, oldBlockIndex, blockIndex, length); + m_Stream.Flush(); + return true; + } + + /// + /// 写入指定文件。 + /// + /// 要写入的文件名称。 + /// 存储写入文件内容的文件路径。 + /// 是否写入指定文件成功。 + public bool WriteFile(string name, string filePath) + { + if (string.IsNullOrEmpty(filePath)) + { + throw new GameFrameworkException("File path is invalid"); + } + + if (!File.Exists(filePath)) + { + return false; + } + + using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + return WriteFile(name, fileStream); + } + } + + /// + /// 将指定文件另存为物理文件。 + /// + /// 要另存为的文件名称。 + /// 存储写入文件内容的文件路径。 + /// 是否将指定文件另存为物理文件成功。 + public bool SaveAsFile(string name, string filePath) + { + if (m_Access != FileSystemAccess.Read && m_Access != FileSystemAccess.ReadWrite) + { + throw new GameFrameworkException("File system is not readable."); + } + + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + if (string.IsNullOrEmpty(filePath)) + { + throw new GameFrameworkException("File path is invalid"); + } + + FileInfo fileInfo = GetFileInfo(name); + if (!fileInfo.IsValid) + { + return false; + } + + if (File.Exists(filePath)) + { + File.Delete(filePath); + } + + string directory = Path.GetDirectoryName(filePath); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None)) + { + int length = fileInfo.Length; + if (length > 0) + { + m_Stream.Position = fileInfo.Offset; + return m_Stream.Read(fileStream, length) == length; + } + + return true; + } + } + + /// + /// 重命名指定文件。 + /// + /// 要重命名的文件名称。 + /// 重命名后的文件名称。 + /// 是否重命名指定文件成功。 + public bool RenameFile(string oldName, string newName) + { + if (m_Access != FileSystemAccess.Write && m_Access != FileSystemAccess.ReadWrite) + { + throw new GameFrameworkException("File system is not writable."); + } + + if (string.IsNullOrEmpty(oldName)) + { + throw new GameFrameworkException("Old name is invalid."); + } + + if (string.IsNullOrEmpty(newName)) + { + throw new GameFrameworkException("New name is invalid."); + } + + if (newName.Length > byte.MaxValue) + { + throw new GameFrameworkException(Utility.Text.Format("New name '{0}' is too long.", newName)); + } + + if (oldName == newName) + { + return true; + } + + if (m_FileDatas.ContainsKey(newName)) + { + return false; + } + + int blockIndex = 0; + if (!m_FileDatas.TryGetValue(oldName, out blockIndex)) + { + return false; + } + + int stringIndex = m_BlockDatas[blockIndex].StringIndex; + StringData stringData = m_StringDatas[stringIndex].SetString(newName, m_HeaderData.GetEncryptBytes()); + m_StringDatas[stringIndex] = stringData; + WriteStringData(stringIndex, stringData); + m_FileDatas.Add(newName, blockIndex); + m_FileDatas.Remove(oldName); + m_Stream.Flush(); + return true; + } + + /// + /// 删除指定文件。 + /// + /// 要删除的文件名称。 + /// 是否删除指定文件成功。 + public bool DeleteFile(string name) + { + if (m_Access != FileSystemAccess.Write && m_Access != FileSystemAccess.ReadWrite) + { + throw new GameFrameworkException("File system is not writable."); + } + + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + int blockIndex = 0; + if (!m_FileDatas.TryGetValue(name, out blockIndex)) + { + return false; + } + + m_FileDatas.Remove(name); + + BlockData blockData = m_BlockDatas[blockIndex]; + int stringIndex = blockData.StringIndex; + StringData stringData = m_StringDatas[stringIndex].Clear(); + m_FreeStringIndexes.Enqueue(stringIndex); + m_FreeStringDatas.Enqueue(stringData); + m_StringDatas.Remove(stringIndex); + WriteStringData(stringIndex, stringData); + + blockData = blockData.Free(); + m_BlockDatas[blockIndex] = blockData; + if (!TryCombineFreeBlocks(blockIndex)) + { + m_FreeBlockIndexes.Add(blockData.Length, blockIndex); + WriteBlockData(blockIndex); + } + + m_Stream.Flush(); + return true; + } + + private void ProcessWriteFile(string name, bool hasFile, int oldBlockIndex, int blockIndex, int length) + { + BlockData blockData = m_BlockDatas[blockIndex]; + if (hasFile) + { + BlockData oldBlockData = m_BlockDatas[oldBlockIndex]; + blockData = new BlockData(oldBlockData.StringIndex, blockData.ClusterIndex, length); + m_BlockDatas[blockIndex] = blockData; + WriteBlockData(blockIndex); + + oldBlockData = oldBlockData.Free(); + m_BlockDatas[oldBlockIndex] = oldBlockData; + if (!TryCombineFreeBlocks(oldBlockIndex)) + { + m_FreeBlockIndexes.Add(oldBlockData.Length, oldBlockIndex); + WriteBlockData(oldBlockIndex); + } + } + else + { + int stringIndex = AllocString(name); + blockData = new BlockData(stringIndex, blockData.ClusterIndex, length); + m_BlockDatas[blockIndex] = blockData; + WriteBlockData(blockIndex); + } + + if (hasFile) + { + m_FileDatas[name] = blockIndex; + } + else + { + m_FileDatas.Add(name, blockIndex); + } + } + + private bool TryCombineFreeBlocks(int freeBlockIndex) + { + BlockData freeBlockData = m_BlockDatas[freeBlockIndex]; + if (freeBlockData.Length <= 0) + { + return false; + } + + int previousFreeBlockIndex = -1; + int nextFreeBlockIndex = -1; + int nextBlockDataClusterIndex = freeBlockData.ClusterIndex + GetUpBoundClusterCount(freeBlockData.Length); + foreach (KeyValuePair> blockIndexes in m_FreeBlockIndexes) + { + if (blockIndexes.Key <= 0) + { + continue; + } + + int blockDataClusterCount = GetUpBoundClusterCount(blockIndexes.Key); + foreach (int blockIndex in blockIndexes.Value) + { + BlockData blockData = m_BlockDatas[blockIndex]; + if (blockData.ClusterIndex + blockDataClusterCount == freeBlockData.ClusterIndex) + { + previousFreeBlockIndex = blockIndex; + } + else if (blockData.ClusterIndex == nextBlockDataClusterIndex) + { + nextFreeBlockIndex = blockIndex; + } + } + } + + if (previousFreeBlockIndex < 0 && nextFreeBlockIndex < 0) + { + return false; + } + + m_FreeBlockIndexes.Remove(freeBlockData.Length, freeBlockIndex); + if (previousFreeBlockIndex >= 0) + { + BlockData previousFreeBlockData = m_BlockDatas[previousFreeBlockIndex]; + m_FreeBlockIndexes.Remove(previousFreeBlockData.Length, previousFreeBlockIndex); + freeBlockData = new BlockData(previousFreeBlockData.ClusterIndex, previousFreeBlockData.Length + freeBlockData.Length); + m_BlockDatas[previousFreeBlockIndex] = BlockData.Empty; + m_FreeBlockIndexes.Add(0, previousFreeBlockIndex); + WriteBlockData(previousFreeBlockIndex); + } + + if (nextFreeBlockIndex >= 0) + { + BlockData nextFreeBlockData = m_BlockDatas[nextFreeBlockIndex]; + m_FreeBlockIndexes.Remove(nextFreeBlockData.Length, nextFreeBlockIndex); + freeBlockData = new BlockData(freeBlockData.ClusterIndex, freeBlockData.Length + nextFreeBlockData.Length); + m_BlockDatas[nextFreeBlockIndex] = BlockData.Empty; + m_FreeBlockIndexes.Add(0, nextFreeBlockIndex); + WriteBlockData(nextFreeBlockIndex); + } + + m_BlockDatas[freeBlockIndex] = freeBlockData; + m_FreeBlockIndexes.Add(freeBlockData.Length, freeBlockIndex); + WriteBlockData(freeBlockIndex); + return true; + } + + private int GetEmptyBlockIndex() + { + GameFrameworkLinkedListRange lengthRange = default(GameFrameworkLinkedListRange); + if (m_FreeBlockIndexes.TryGetValue(0, out lengthRange)) + { + int blockIndex = lengthRange.First.Value; + m_FreeBlockIndexes.Remove(0, blockIndex); + return blockIndex; + } + + if (m_BlockDatas.Count < m_HeaderData.MaxBlockCount) + { + int blockIndex = m_BlockDatas.Count; + m_BlockDatas.Add(BlockData.Empty); + WriteHeaderData(); + return blockIndex; + } + + return -1; + } + + private int AllocBlock(int length) + { + if (length <= 0) + { + return GetEmptyBlockIndex(); + } + + length = (int)GetUpBoundClusterOffset(length); + + int lengthFound = -1; + GameFrameworkLinkedListRange lengthRange = default(GameFrameworkLinkedListRange); + foreach (KeyValuePair> i in m_FreeBlockIndexes) + { + if (i.Key < length) + { + continue; + } + + if (lengthFound >= 0 && lengthFound < i.Key) + { + continue; + } + + lengthFound = i.Key; + lengthRange = i.Value; + } + + if (lengthFound >= 0) + { + if (lengthFound > length && m_BlockDatas.Count >= m_HeaderData.MaxBlockCount) + { + return -1; + } + + int blockIndex = lengthRange.First.Value; + m_FreeBlockIndexes.Remove(lengthFound, blockIndex); + if (lengthFound > length) + { + BlockData blockData = m_BlockDatas[blockIndex]; + m_BlockDatas[blockIndex] = new BlockData(blockData.ClusterIndex, length); + WriteBlockData(blockIndex); + + int deltaLength = lengthFound - length; + int anotherBlockIndex = GetEmptyBlockIndex(); + m_BlockDatas[anotherBlockIndex] = new BlockData(blockData.ClusterIndex + GetUpBoundClusterCount(length), deltaLength); + m_FreeBlockIndexes.Add(deltaLength, anotherBlockIndex); + WriteBlockData(anotherBlockIndex); + } + + return blockIndex; + } + else + { + int blockIndex = GetEmptyBlockIndex(); + if (blockIndex < 0) + { + return -1; + } + + long fileLength = m_Stream.Length; + try + { + m_Stream.SetLength(fileLength + length); + } + catch + { + return -1; + } + + m_BlockDatas[blockIndex] = new BlockData(GetUpBoundClusterCount(fileLength), length); + WriteBlockData(blockIndex); + return blockIndex; + } + } + + private int AllocString(string value) + { + int stringIndex = -1; + StringData stringData = default(StringData); + + if (m_FreeStringIndexes.Count > 0) + { + stringIndex = m_FreeStringIndexes.Dequeue(); + } + else + { + stringIndex = m_StringDatas.Count; + } + + if (m_FreeStringDatas.Count > 0) + { + stringData = m_FreeStringDatas.Dequeue(); + } + else + { + byte[] bytes = new byte[byte.MaxValue]; + Utility.Random.GetRandomBytes(bytes); + stringData = new StringData(0, bytes); + } + + stringData = stringData.SetString(value, m_HeaderData.GetEncryptBytes()); + m_StringDatas.Add(stringIndex, stringData); + WriteStringData(stringIndex, stringData); + return stringIndex; + } + + private void WriteHeaderData() + { + m_HeaderData = m_HeaderData.SetBlockCount(m_BlockDatas.Count); + Utility.Marshal.StructureToBytes(m_HeaderData, HeaderDataSize, s_CachedBytes); + m_Stream.Position = 0L; + m_Stream.Write(s_CachedBytes, 0, HeaderDataSize); + } + + private void WriteBlockData(int blockIndex) + { + Utility.Marshal.StructureToBytes(m_BlockDatas[blockIndex], BlockDataSize, s_CachedBytes); + m_Stream.Position = m_BlockDataOffset + BlockDataSize * blockIndex; + m_Stream.Write(s_CachedBytes, 0, BlockDataSize); + } + + private StringData ReadStringData(int stringIndex) + { + m_Stream.Position = m_StringDataOffset + StringDataSize * stringIndex; + m_Stream.Read(s_CachedBytes, 0, StringDataSize); + return Utility.Marshal.BytesToStructure(StringDataSize, s_CachedBytes); + } + + private void WriteStringData(int stringIndex, StringData stringData) + { + Utility.Marshal.StructureToBytes(stringData, StringDataSize, s_CachedBytes); + m_Stream.Position = m_StringDataOffset + StringDataSize * stringIndex; + m_Stream.Write(s_CachedBytes, 0, StringDataSize); + } + + private static void CalcOffsets(FileSystem fileSystem) + { + fileSystem.m_BlockDataOffset = HeaderDataSize; + fileSystem.m_StringDataOffset = fileSystem.m_BlockDataOffset + BlockDataSize * fileSystem.m_HeaderData.MaxBlockCount; + fileSystem.m_FileDataOffset = (int)GetUpBoundClusterOffset(fileSystem.m_StringDataOffset + StringDataSize * fileSystem.m_HeaderData.MaxFileCount); + } + + private static long GetUpBoundClusterOffset(long offset) + { + return (offset - 1L + ClusterSize) / ClusterSize * ClusterSize; + } + + private static int GetUpBoundClusterCount(long length) + { + return (int)((length - 1L + ClusterSize) / ClusterSize); + } + + private static long GetClusterOffset(int clusterIndex) + { + return (long)ClusterSize * clusterIndex; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.cs.meta new file mode 100644 index 0000000..69e2395 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: adee24668eb76c648a130884359b6db7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemAccess.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemAccess.cs new file mode 100644 index 0000000..b0bc1be --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemAccess.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.FileSystem +{ + /// + /// 文件系统访问方式。 + /// + [Flags] + public enum FileSystemAccess : byte + { + /// + /// 未指定。 + /// + Unspecified = 0, + + /// + /// 只可读。 + /// + Read = 1, + + /// + /// 只可写。 + /// + Write = 2, + + /// + /// 可读写。 + /// + ReadWrite = 3 + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemAccess.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemAccess.cs.meta new file mode 100644 index 0000000..02b56f8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemAccess.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fe041668e95005446a79c11fa344a1a6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemManager.cs new file mode 100644 index 0000000..81a751d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemManager.cs @@ -0,0 +1,283 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.IO; + +namespace GameFramework.FileSystem +{ + /// + /// 文件系统管理器。 + /// + internal sealed class FileSystemManager : GameFrameworkModule, IFileSystemManager + { + private readonly Dictionary m_FileSystems; + + private IFileSystemHelper m_FileSystemHelper; + + /// + /// 初始化文件系统管理器的新实例。 + /// + public FileSystemManager() + { + m_FileSystems = new Dictionary(StringComparer.Ordinal); + m_FileSystemHelper = null; + } + + /// + /// 获取游戏框架模块优先级。 + /// + /// 优先级较高的模块会优先轮询,并且关闭操作会后进行。 + internal override int Priority + { + get + { + return 4; + } + } + + /// + /// 获取文件系统数量。 + /// + public int Count + { + get + { + return m_FileSystems.Count; + } + } + + /// + /// 文件系统管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 关闭并清理文件系统管理器。 + /// + internal override void Shutdown() + { + while (m_FileSystems.Count > 0) + { + foreach (KeyValuePair fileSystem in m_FileSystems) + { + DestroyFileSystem(fileSystem.Value, false); + break; + } + } + } + + /// + /// 设置文件系统辅助器。 + /// + /// 文件系统辅助器。 + public void SetFileSystemHelper(IFileSystemHelper fileSystemHelper) + { + if (fileSystemHelper == null) + { + throw new GameFrameworkException("File system helper is invalid."); + } + + m_FileSystemHelper = fileSystemHelper; + } + + /// + /// 检查是否存在文件系统。 + /// + /// 要检查的文件系统的完整路径。 + /// 是否存在文件系统。 + public bool HasFileSystem(string fullPath) + { + if (string.IsNullOrEmpty(fullPath)) + { + throw new GameFrameworkException("Full path is invalid."); + } + + return m_FileSystems.ContainsKey(Utility.Path.GetRegularPath(fullPath)); + } + + /// + /// 获取文件系统。 + /// + /// 要获取的文件系统的完整路径。 + /// 获取的文件系统。 + public IFileSystem GetFileSystem(string fullPath) + { + if (string.IsNullOrEmpty(fullPath)) + { + throw new GameFrameworkException("Full path is invalid."); + } + + FileSystem fileSystem = null; + if (m_FileSystems.TryGetValue(Utility.Path.GetRegularPath(fullPath), out fileSystem)) + { + return fileSystem; + } + + return null; + } + + /// + /// 创建文件系统。 + /// + /// 要创建的文件系统的完整路径。 + /// 要创建的文件系统的访问方式。 + /// 要创建的文件系统的最大文件数量。 + /// 要创建的文件系统的最大块数据数量。 + /// 创建的文件系统。 + public IFileSystem CreateFileSystem(string fullPath, FileSystemAccess access, int maxFileCount, int maxBlockCount) + { + if (m_FileSystemHelper == null) + { + throw new GameFrameworkException("File system helper is invalid."); + } + + if (string.IsNullOrEmpty(fullPath)) + { + throw new GameFrameworkException("Full path is invalid."); + } + + if (access == FileSystemAccess.Unspecified) + { + throw new GameFrameworkException("Access is invalid."); + } + + if (access == FileSystemAccess.Read) + { + throw new GameFrameworkException("Access read is invalid."); + } + + fullPath = Utility.Path.GetRegularPath(fullPath); + if (m_FileSystems.ContainsKey(fullPath)) + { + throw new GameFrameworkException(Utility.Text.Format("File system '{0}' is already exist.", fullPath)); + } + + FileSystemStream fileSystemStream = m_FileSystemHelper.CreateFileSystemStream(fullPath, access, true); + if (fileSystemStream == null) + { + throw new GameFrameworkException(Utility.Text.Format("Create file system stream for '{0}' failure.", fullPath)); + } + + FileSystem fileSystem = FileSystem.Create(fullPath, access, fileSystemStream, maxFileCount, maxBlockCount); + if (fileSystem == null) + { + throw new GameFrameworkException(Utility.Text.Format("Create file system '{0}' failure.", fullPath)); + } + + m_FileSystems.Add(fullPath, fileSystem); + return fileSystem; + } + + /// + /// 加载文件系统。 + /// + /// 要加载的文件系统的完整路径。 + /// 要加载的文件系统的访问方式。 + /// 加载的文件系统。 + public IFileSystem LoadFileSystem(string fullPath, FileSystemAccess access) + { + if (m_FileSystemHelper == null) + { + throw new GameFrameworkException("File system helper is invalid."); + } + + if (string.IsNullOrEmpty(fullPath)) + { + throw new GameFrameworkException("Full path is invalid."); + } + + if (access == FileSystemAccess.Unspecified) + { + throw new GameFrameworkException("Access is invalid."); + } + + fullPath = Utility.Path.GetRegularPath(fullPath); + if (m_FileSystems.ContainsKey(fullPath)) + { + throw new GameFrameworkException(Utility.Text.Format("File system '{0}' is already exist.", fullPath)); + } + + FileSystemStream fileSystemStream = m_FileSystemHelper.CreateFileSystemStream(fullPath, access, false); + if (fileSystemStream == null) + { + throw new GameFrameworkException(Utility.Text.Format("Create file system stream for '{0}' failure.", fullPath)); + } + + FileSystem fileSystem = FileSystem.Load(fullPath, access, fileSystemStream); + if (fileSystem == null) + { + fileSystemStream.Close(); + throw new GameFrameworkException(Utility.Text.Format("Load file system '{0}' failure.", fullPath)); + } + + m_FileSystems.Add(fullPath, fileSystem); + return fileSystem; + } + + /// + /// 销毁文件系统。 + /// + /// 要销毁的文件系统。 + /// 是否删除文件系统对应的物理文件。 + public void DestroyFileSystem(IFileSystem fileSystem, bool deletePhysicalFile) + { + if (fileSystem == null) + { + throw new GameFrameworkException("File system is invalid."); + } + + string fullPath = fileSystem.FullPath; + ((FileSystem)fileSystem).Shutdown(); + m_FileSystems.Remove(fullPath); + + if (deletePhysicalFile && File.Exists(fullPath)) + { + File.Delete(fullPath); + } + } + + /// + /// 获取所有文件系统集合。 + /// + /// 获取的所有文件系统集合。 + public IFileSystem[] GetAllFileSystems() + { + int index = 0; + IFileSystem[] results = new IFileSystem[m_FileSystems.Count]; + foreach (KeyValuePair fileSystem in m_FileSystems) + { + results[index++] = fileSystem.Value; + } + + return results; + } + + /// + /// 获取所有文件系统集合。 + /// + /// 获取的所有文件系统集合。 + public void GetAllFileSystems(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair fileSystem in m_FileSystems) + { + results.Add(fileSystem.Value); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemManager.cs.meta new file mode 100644 index 0000000..6d788b9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 847cf72ef4e839c44963a669560ae00d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemStream.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemStream.cs new file mode 100644 index 0000000..f0a1846 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemStream.cs @@ -0,0 +1,135 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.IO; + +namespace GameFramework.FileSystem +{ + /// + /// 文件系统流。 + /// + public abstract class FileSystemStream + { + /// + /// 缓存二进制流的长度。 + /// + protected const int CachedBytesLength = 0x1000; + + /// + /// 缓存二进制流。 + /// + protected static readonly byte[] s_CachedBytes = new byte[CachedBytesLength]; + + /// + /// 获取或设置文件系统流位置。 + /// + public abstract long Position + { + get; + set; + } + + /// + /// 获取文件系统流长度。 + /// + public abstract long Length + { + get; + } + + /// + /// 设置文件系统流长度。 + /// + /// 要设置的文件系统流的长度。 + public abstract void SetLength(long length); + + /// + /// 定位文件系统流位置。 + /// + /// 要定位的文件系统流位置的偏移。 + /// 要定位的文件系统流位置的方式。 + public abstract void Seek(long offset, SeekOrigin origin); + + /// + /// 从文件系统流中读取一个字节。 + /// + /// 读取的字节,若已经到达文件结尾,则返回 -1。 + public abstract int ReadByte(); + + /// + /// 从文件系统流中读取二进制流。 + /// + /// 存储读取文件内容的二进制流。 + /// 存储读取文件内容的二进制流的起始位置。 + /// 存储读取文件内容的二进制流的长度。 + /// 实际读取了多少字节。 + public abstract int Read(byte[] buffer, int startIndex, int length); + + /// + /// 从文件系统流中读取二进制流。 + /// + /// 存储读取文件内容的二进制流。 + /// 存储读取文件内容的二进制流的长度。 + /// 实际读取了多少字节。 + public int Read(Stream stream, int length) + { + int bytesRead = 0; + int bytesLeft = length; + while ((bytesRead = Read(s_CachedBytes, 0, bytesLeft < CachedBytesLength ? bytesLeft : CachedBytesLength)) > 0) + { + bytesLeft -= bytesRead; + stream.Write(s_CachedBytes, 0, bytesRead); + } + + Array.Clear(s_CachedBytes, 0, CachedBytesLength); + return length - bytesLeft; + } + + /// + /// 向文件系统流中写入一个字节。 + /// + /// 要写入的字节。 + public abstract void WriteByte(byte value); + + /// + /// 向文件系统流中写入二进制流。 + /// + /// 存储写入文件内容的二进制流。 + /// 存储写入文件内容的二进制流的起始位置。 + /// 存储写入文件内容的二进制流的长度。 + public abstract void Write(byte[] buffer, int startIndex, int length); + + /// + /// 向文件系统流中写入二进制流。 + /// + /// 存储写入文件内容的二进制流。 + /// 存储写入文件内容的二进制流的长度。 + public void Write(Stream stream, int length) + { + int bytesRead = 0; + int bytesLeft = length; + while ((bytesRead = stream.Read(s_CachedBytes, 0, bytesLeft < CachedBytesLength ? bytesLeft : CachedBytesLength)) > 0) + { + bytesLeft -= bytesRead; + Write(s_CachedBytes, 0, bytesRead); + } + + Array.Clear(s_CachedBytes, 0, CachedBytesLength); + } + + /// + /// 将文件系统流立刻更新到存储介质中。 + /// + public abstract void Flush(); + + /// + /// 关闭文件系统流。 + /// + public abstract void Close(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemStream.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemStream.cs.meta new file mode 100644 index 0000000..44436f1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/FileSystemStream.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 29982ed701ce57b409a664688940a07b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystem.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystem.cs new file mode 100644 index 0000000..1b7944e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystem.cs @@ -0,0 +1,277 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; +using System.IO; + +namespace GameFramework.FileSystem +{ + /// + /// 文件系统接口。 + /// + public interface IFileSystem + { + /// + /// 获取文件系统完整路径。 + /// + string FullPath + { + get; + } + + /// + /// 获取文件系统访问方式。 + /// + FileSystemAccess Access + { + get; + } + + /// + /// 获取文件数量。 + /// + int FileCount + { + get; + } + + /// + /// 获取最大文件数量。 + /// + int MaxFileCount + { + get; + } + + /// + /// 获取文件信息。 + /// + /// 要获取文件信息的文件名称。 + /// 获取的文件信息。 + FileInfo GetFileInfo(string name); + + /// + /// 获取所有文件信息。 + /// + /// 获取的所有文件信息。 + FileInfo[] GetAllFileInfos(); + + /// + /// 获取所有文件信息。 + /// + /// 获取的所有文件信息。 + void GetAllFileInfos(List results); + + /// + /// 检查是否存在指定文件。 + /// + /// 要检查的文件名称。 + /// 是否存在指定文件。 + bool HasFile(string name); + + /// + /// 读取指定文件。 + /// + /// 要读取的文件名称。 + /// 存储读取文件内容的二进制流。 + byte[] ReadFile(string name); + + /// + /// 读取指定文件。 + /// + /// 要读取的文件名称。 + /// 存储读取文件内容的二进制流。 + /// 实际读取了多少字节。 + int ReadFile(string name, byte[] buffer); + + /// + /// 读取指定文件。 + /// + /// 要读取的文件名称。 + /// 存储读取文件内容的二进制流。 + /// 存储读取文件内容的二进制流的起始位置。 + /// 实际读取了多少字节。 + int ReadFile(string name, byte[] buffer, int startIndex); + + /// + /// 读取指定文件。 + /// + /// 要读取的文件名称。 + /// 存储读取文件内容的二进制流。 + /// 存储读取文件内容的二进制流的起始位置。 + /// 存储读取文件内容的二进制流的长度。 + /// 实际读取了多少字节。 + int ReadFile(string name, byte[] buffer, int startIndex, int length); + + /// + /// 读取指定文件。 + /// + /// 要读取的文件名称。 + /// 存储读取文件内容的二进制流。 + /// 实际读取了多少字节。 + int ReadFile(string name, Stream stream); + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 要读取片段的长度。 + /// 存储读取文件片段内容的二进制流。 + byte[] ReadFileSegment(string name, int length); + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 要读取片段的偏移。 + /// 要读取片段的长度。 + /// 存储读取文件片段内容的二进制流。 + byte[] ReadFileSegment(string name, int offset, int length); + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 存储读取文件片段内容的二进制流。 + /// 实际读取了多少字节。 + int ReadFileSegment(string name, byte[] buffer); + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 存储读取文件片段内容的二进制流。 + /// 要读取片段的长度。 + /// 实际读取了多少字节。 + int ReadFileSegment(string name, byte[] buffer, int length); + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 存储读取文件片段内容的二进制流。 + /// 存储读取文件片段内容的二进制流的起始位置。 + /// 要读取片段的长度。 + /// 实际读取了多少字节。 + int ReadFileSegment(string name, byte[] buffer, int startIndex, int length); + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 要读取片段的偏移。 + /// 存储读取文件片段内容的二进制流。 + /// 实际读取了多少字节。 + int ReadFileSegment(string name, int offset, byte[] buffer); + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 要读取片段的偏移。 + /// 存储读取文件片段内容的二进制流。 + /// 要读取片段的长度。 + /// 实际读取了多少字节。 + int ReadFileSegment(string name, int offset, byte[] buffer, int length); + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 要读取片段的偏移。 + /// 存储读取文件片段内容的二进制流。 + /// 存储读取文件片段内容的二进制流的起始位置。 + /// 要读取片段的长度。 + /// 实际读取了多少字节。 + int ReadFileSegment(string name, int offset, byte[] buffer, int startIndex, int length); + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 存储读取文件片段内容的二进制流。 + /// 要读取片段的长度。 + /// 实际读取了多少字节。 + int ReadFileSegment(string name, Stream stream, int length); + + /// + /// 读取指定文件的指定片段。 + /// + /// 要读取片段的文件名称。 + /// 要读取片段的偏移。 + /// 存储读取文件片段内容的二进制流。 + /// 要读取片段的长度。 + /// 实际读取了多少字节。 + int ReadFileSegment(string name, int offset, Stream stream, int length); + + /// + /// 写入指定文件。 + /// + /// 要写入的文件名称。 + /// 存储写入文件内容的二进制流。 + /// 是否写入指定文件成功。 + bool WriteFile(string name, byte[] buffer); + + /// + /// 写入指定文件。 + /// + /// 要写入的文件名称。 + /// 存储写入文件内容的二进制流。 + /// 存储写入文件内容的二进制流的起始位置。 + /// 是否写入指定文件成功。 + bool WriteFile(string name, byte[] buffer, int startIndex); + + /// + /// 写入指定文件。 + /// + /// 要写入的文件名称。 + /// 存储写入文件内容的二进制流。 + /// 存储写入文件内容的二进制流的起始位置。 + /// 存储写入文件内容的二进制流的长度。 + /// 是否写入指定文件成功。 + bool WriteFile(string name, byte[] buffer, int startIndex, int length); + + /// + /// 写入指定文件。 + /// + /// 要写入的文件名称。 + /// 存储写入文件内容的二进制流。 + /// 是否写入指定文件成功。 + bool WriteFile(string name, Stream stream); + + /// + /// 写入指定文件。 + /// + /// 要写入的文件名称。 + /// 存储写入文件内容的文件路径。 + /// 是否写入指定文件成功。 + bool WriteFile(string name, string filePath); + + /// + /// 将指定文件另存为物理文件。 + /// + /// 要另存为的文件名称。 + /// 存储写入文件内容的文件路径。 + /// 是否将指定文件另存为物理文件成功。 + bool SaveAsFile(string name, string filePath); + + /// + /// 重命名指定文件。 + /// + /// 要重命名的文件名称。 + /// 重命名后的文件名称。 + /// 是否重命名指定文件成功。 + bool RenameFile(string oldName, string newName); + + /// + /// 删除指定文件。 + /// + /// 要删除的文件名称。 + /// 是否删除指定文件成功。 + bool DeleteFile(string name); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystem.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystem.cs.meta new file mode 100644 index 0000000..82793ef --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8579bcaa59f35d141b05835ce0590b81 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystemHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystemHelper.cs new file mode 100644 index 0000000..546ee80 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystemHelper.cs @@ -0,0 +1,24 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.FileSystem +{ + /// + /// 文件系统辅助器接口。 + /// + public interface IFileSystemHelper + { + /// + /// 创建文件系统流。 + /// + /// 要加载的文件系统的完整路径。 + /// 要加载的文件系统的访问方式。 + /// 是否创建新的文件系统流。 + /// 创建的文件系统流。 + FileSystemStream CreateFileSystemStream(string fullPath, FileSystemAccess access, bool createNew); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystemHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystemHelper.cs.meta new file mode 100644 index 0000000..2a60df2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystemHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2590f8fdb586a4c4688082efdcb6182c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystemManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystemManager.cs new file mode 100644 index 0000000..866cbe0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystemManager.cs @@ -0,0 +1,82 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.FileSystem +{ + /// + /// 文件系统管理器。 + /// + public interface IFileSystemManager + { + /// + /// 获取文件系统数量。 + /// + int Count + { + get; + } + + /// + /// 设置文件系统辅助器。 + /// + /// 文件系统辅助器。 + void SetFileSystemHelper(IFileSystemHelper fileSystemHelper); + + /// + /// 检查是否存在文件系统。 + /// + /// 要检查的文件系统的完整路径。 + /// 是否存在文件系统。 + bool HasFileSystem(string fullPath); + + /// + /// 获取文件系统。 + /// + /// 要获取的文件系统的完整路径。 + /// 获取的文件系统。 + IFileSystem GetFileSystem(string fullPath); + + /// + /// 创建文件系统。 + /// + /// 要创建的文件系统的完整路径。 + /// 要创建的文件系统的访问方式。 + /// 要创建的文件系统的最大文件数量。 + /// 要创建的文件系统的最大块数据数量。 + /// 创建的文件系统。 + IFileSystem CreateFileSystem(string fullPath, FileSystemAccess access, int maxFileCount, int maxBlockCount); + + /// + /// 加载文件系统。 + /// + /// 要加载的文件系统的完整路径。 + /// 要加载的文件系统的访问方式。 + /// 加载的文件系统。 + IFileSystem LoadFileSystem(string fullPath, FileSystemAccess access); + + /// + /// 销毁文件系统。 + /// + /// 要销毁的文件系统。 + /// 是否删除文件系统对应的物理文件。 + void DestroyFileSystem(IFileSystem fileSystem, bool deletePhysicalFile); + + /// + /// 获取所有文件系统集合。 + /// + /// 获取的所有文件系统集合。 + IFileSystem[] GetAllFileSystems(); + + /// + /// 获取所有文件系统集合。 + /// + /// 获取的所有文件系统集合。 + void GetAllFileSystems(List results); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystemManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystemManager.cs.meta new file mode 100644 index 0000000..a58b819 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/FileSystem/IFileSystemManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 10ae1b26debca324b94218750fd78cf7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm.meta new file mode 100644 index 0000000..0ccacb6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0267b272dd3ee21439390ebec948002c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/Fsm.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/Fsm.cs new file mode 100644 index 0000000..a218e10 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/Fsm.cs @@ -0,0 +1,588 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.Fsm +{ + /// + /// 有限状态机。 + /// + /// 有限状态机持有者类型。 + internal sealed class Fsm : FsmBase, IReference, IFsm where T : class + { + private T m_Owner; + private readonly Dictionary> m_States; + private Dictionary m_Datas; + private FsmState m_CurrentState; + private float m_CurrentStateTime; + private bool m_IsDestroyed; + + /// + /// 初始化有限状态机的新实例。 + /// + public Fsm() + { + m_Owner = null; + m_States = new Dictionary>(); + m_Datas = null; + m_CurrentState = null; + m_CurrentStateTime = 0f; + m_IsDestroyed = true; + } + + /// + /// 获取有限状态机持有者。 + /// + public T Owner + { + get + { + return m_Owner; + } + } + + /// + /// 获取有限状态机持有者类型。 + /// + public override Type OwnerType + { + get + { + return typeof(T); + } + } + + /// + /// 获取有限状态机中状态的数量。 + /// + public override int FsmStateCount + { + get + { + return m_States.Count; + } + } + + /// + /// 获取有限状态机是否正在运行。 + /// + public override bool IsRunning + { + get + { + return m_CurrentState != null; + } + } + + /// + /// 获取有限状态机是否被销毁。 + /// + public override bool IsDestroyed + { + get + { + return m_IsDestroyed; + } + } + + /// + /// 获取当前有限状态机状态。 + /// + public FsmState CurrentState + { + get + { + return m_CurrentState; + } + } + + /// + /// 获取当前有限状态机状态名称。 + /// + public override string CurrentStateName + { + get + { + return m_CurrentState != null ? m_CurrentState.GetType().FullName : null; + } + } + + /// + /// 获取当前有限状态机状态持续时间。 + /// + public override float CurrentStateTime + { + get + { + return m_CurrentStateTime; + } + } + + /// + /// 创建有限状态机。 + /// + /// 有限状态机名称。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 创建的有限状态机。 + public static Fsm Create(string name, T owner, params FsmState[] states) + { + if (owner == null) + { + throw new GameFrameworkException("FSM owner is invalid."); + } + + if (states == null || states.Length < 1) + { + throw new GameFrameworkException("FSM states is invalid."); + } + + Fsm fsm = ReferencePool.Acquire>(); + fsm.Name = name; + fsm.m_Owner = owner; + fsm.m_IsDestroyed = false; + foreach (FsmState state in states) + { + if (state == null) + { + throw new GameFrameworkException("FSM states is invalid."); + } + + Type stateType = state.GetType(); + if (fsm.m_States.ContainsKey(stateType)) + { + throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' state '{1}' is already exist.", new TypeNamePair(typeof(T), name), stateType.FullName)); + } + + fsm.m_States.Add(stateType, state); + state.OnInit(fsm); + } + + return fsm; + } + + /// + /// 创建有限状态机。 + /// + /// 有限状态机名称。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 创建的有限状态机。 + public static Fsm Create(string name, T owner, List> states) + { + if (owner == null) + { + throw new GameFrameworkException("FSM owner is invalid."); + } + + if (states == null || states.Count < 1) + { + throw new GameFrameworkException("FSM states is invalid."); + } + + Fsm fsm = ReferencePool.Acquire>(); + fsm.Name = name; + fsm.m_Owner = owner; + fsm.m_IsDestroyed = false; + foreach (FsmState state in states) + { + if (state == null) + { + throw new GameFrameworkException("FSM states is invalid."); + } + + Type stateType = state.GetType(); + if (fsm.m_States.ContainsKey(stateType)) + { + throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' state '{1}' is already exist.", new TypeNamePair(typeof(T), name), stateType.FullName)); + } + + fsm.m_States.Add(stateType, state); + state.OnInit(fsm); + } + + return fsm; + } + + /// + /// 清理有限状态机。 + /// + public void Clear() + { + if (m_CurrentState != null) + { + m_CurrentState.OnLeave(this, true); + } + + foreach (KeyValuePair> state in m_States) + { + state.Value.OnDestroy(this); + } + + Name = null; + m_Owner = null; + m_States.Clear(); + + if (m_Datas != null) + { + foreach (KeyValuePair data in m_Datas) + { + if (data.Value == null) + { + continue; + } + + ReferencePool.Release(data.Value); + } + + m_Datas.Clear(); + } + + m_CurrentState = null; + m_CurrentStateTime = 0f; + m_IsDestroyed = true; + } + + /// + /// 开始有限状态机。 + /// + /// 要开始的有限状态机状态类型。 + public void Start() where TState : FsmState + { + if (IsRunning) + { + throw new GameFrameworkException("FSM is running, can not start again."); + } + + FsmState state = GetState(); + if (state == null) + { + throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' can not start state '{1}' which is not exist.", new TypeNamePair(typeof(T), Name), typeof(TState).FullName)); + } + + m_CurrentStateTime = 0f; + m_CurrentState = state; + m_CurrentState.OnEnter(this); + } + + /// + /// 开始有限状态机。 + /// + /// 要开始的有限状态机状态类型。 + public void Start(Type stateType) + { + if (IsRunning) + { + throw new GameFrameworkException("FSM is running, can not start again."); + } + + if (stateType == null) + { + throw new GameFrameworkException("State type is invalid."); + } + + if (!typeof(FsmState).IsAssignableFrom(stateType)) + { + throw new GameFrameworkException(Utility.Text.Format("State type '{0}' is invalid.", stateType.FullName)); + } + + FsmState state = GetState(stateType); + if (state == null) + { + throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' can not start state '{1}' which is not exist.", new TypeNamePair(typeof(T), Name), stateType.FullName)); + } + + m_CurrentStateTime = 0f; + m_CurrentState = state; + m_CurrentState.OnEnter(this); + } + + /// + /// 是否存在有限状态机状态。 + /// + /// 要检查的有限状态机状态类型。 + /// 是否存在有限状态机状态。 + public bool HasState() where TState : FsmState + { + return m_States.ContainsKey(typeof(TState)); + } + + /// + /// 是否存在有限状态机状态。 + /// + /// 要检查的有限状态机状态类型。 + /// 是否存在有限状态机状态。 + public bool HasState(Type stateType) + { + if (stateType == null) + { + throw new GameFrameworkException("State type is invalid."); + } + + if (!typeof(FsmState).IsAssignableFrom(stateType)) + { + throw new GameFrameworkException(Utility.Text.Format("State type '{0}' is invalid.", stateType.FullName)); + } + + return m_States.ContainsKey(stateType); + } + + /// + /// 获取有限状态机状态。 + /// + /// 要获取的有限状态机状态类型。 + /// 要获取的有限状态机状态。 + public TState GetState() where TState : FsmState + { + FsmState state = null; + if (m_States.TryGetValue(typeof(TState), out state)) + { + return (TState)state; + } + + return null; + } + + /// + /// 获取有限状态机状态。 + /// + /// 要获取的有限状态机状态类型。 + /// 要获取的有限状态机状态。 + public FsmState GetState(Type stateType) + { + if (stateType == null) + { + throw new GameFrameworkException("State type is invalid."); + } + + if (!typeof(FsmState).IsAssignableFrom(stateType)) + { + throw new GameFrameworkException(Utility.Text.Format("State type '{0}' is invalid.", stateType.FullName)); + } + + FsmState state = null; + if (m_States.TryGetValue(stateType, out state)) + { + return state; + } + + return null; + } + + /// + /// 获取有限状态机的所有状态。 + /// + /// 有限状态机的所有状态。 + public FsmState[] GetAllStates() + { + int index = 0; + FsmState[] results = new FsmState[m_States.Count]; + foreach (KeyValuePair> state in m_States) + { + results[index++] = state.Value; + } + + return results; + } + + /// + /// 获取有限状态机的所有状态。 + /// + /// 有限状态机的所有状态。 + public void GetAllStates(List> results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair> state in m_States) + { + results.Add(state.Value); + } + } + + /// + /// 是否存在有限状态机数据。 + /// + /// 有限状态机数据名称。 + /// 有限状态机数据是否存在。 + public bool HasData(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Data name is invalid."); + } + + if (m_Datas == null) + { + return false; + } + + return m_Datas.ContainsKey(name); + } + + /// + /// 获取有限状态机数据。 + /// + /// 要获取的有限状态机数据的类型。 + /// 有限状态机数据名称。 + /// 要获取的有限状态机数据。 + public TData GetData(string name) where TData : Variable + { + return (TData)GetData(name); + } + + /// + /// 获取有限状态机数据。 + /// + /// 有限状态机数据名称。 + /// 要获取的有限状态机数据。 + public Variable GetData(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Data name is invalid."); + } + + if (m_Datas == null) + { + return null; + } + + Variable data = null; + if (m_Datas.TryGetValue(name, out data)) + { + return data; + } + + return null; + } + + /// + /// 设置有限状态机数据。 + /// + /// 要设置的有限状态机数据的类型。 + /// 有限状态机数据名称。 + /// 要设置的有限状态机数据。 + public void SetData(string name, TData data) where TData : Variable + { + SetData(name, (Variable)data); + } + + /// + /// 设置有限状态机数据。 + /// + /// 有限状态机数据名称。 + /// 要设置的有限状态机数据。 + public void SetData(string name, Variable data) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Data name is invalid."); + } + + if (m_Datas == null) + { + m_Datas = new Dictionary(StringComparer.Ordinal); + } + + Variable oldData = GetData(name); + if (oldData != null) + { + ReferencePool.Release(oldData); + } + + m_Datas[name] = data; + } + + /// + /// 移除有限状态机数据。 + /// + /// 有限状态机数据名称。 + /// 是否移除有限状态机数据成功。 + public bool RemoveData(string name) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Data name is invalid."); + } + + if (m_Datas == null) + { + return false; + } + + Variable oldData = GetData(name); + if (oldData != null) + { + ReferencePool.Release(oldData); + } + + return m_Datas.Remove(name); + } + + /// + /// 有限状态机轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + if (m_CurrentState == null) + { + return; + } + + m_CurrentStateTime += elapseSeconds; + m_CurrentState.OnUpdate(this, elapseSeconds, realElapseSeconds); + } + + /// + /// 关闭并清理有限状态机。 + /// + internal override void Shutdown() + { + ReferencePool.Release(this); + } + + /// + /// 切换当前有限状态机状态。 + /// + /// 要切换到的有限状态机状态类型。 + internal void ChangeState() where TState : FsmState + { + ChangeState(typeof(TState)); + } + + /// + /// 切换当前有限状态机状态。 + /// + /// 要切换到的有限状态机状态类型。 + internal void ChangeState(Type stateType) + { + if (m_CurrentState == null) + { + throw new GameFrameworkException("Current state is invalid."); + } + + FsmState state = GetState(stateType); + if (state == null) + { + throw new GameFrameworkException(Utility.Text.Format("FSM '{0}' can not change state to '{1}' which is not exist.", new TypeNamePair(typeof(T), Name), stateType.FullName)); + } + + m_CurrentState.OnLeave(this, false); + m_CurrentStateTime = 0f; + m_CurrentState = state; + m_CurrentState.OnEnter(this); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/Fsm.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/Fsm.cs.meta new file mode 100644 index 0000000..b54c354 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/Fsm.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6c571690223c4464b9850060eea6c82b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmBase.cs new file mode 100644 index 0000000..9c74ab4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmBase.cs @@ -0,0 +1,113 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.Fsm +{ + /// + /// 有限状态机基类。 + /// + public abstract class FsmBase + { + private string m_Name; + + /// + /// 初始化有限状态机基类的新实例。 + /// + public FsmBase() + { + m_Name = string.Empty; + } + + /// + /// 获取有限状态机名称。 + /// + public string Name + { + get + { + return m_Name; + } + protected set + { + m_Name = value ?? string.Empty; + } + } + + /// + /// 获取有限状态机完整名称。 + /// + public string FullName + { + get + { + return new TypeNamePair(OwnerType, m_Name).ToString(); + } + } + + /// + /// 获取有限状态机持有者类型。 + /// + public abstract Type OwnerType + { + get; + } + + /// + /// 获取有限状态机中状态的数量。 + /// + public abstract int FsmStateCount + { + get; + } + + /// + /// 获取有限状态机是否正在运行。 + /// + public abstract bool IsRunning + { + get; + } + + /// + /// 获取有限状态机是否被销毁。 + /// + public abstract bool IsDestroyed + { + get; + } + + /// + /// 获取当前有限状态机状态名称。 + /// + public abstract string CurrentStateName + { + get; + } + + /// + /// 获取当前有限状态机状态持续时间。 + /// + public abstract float CurrentStateTime + { + get; + } + + /// + /// 有限状态机轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 当前已流逝时间,以秒为单位。 + internal abstract void Update(float elapseSeconds, float realElapseSeconds); + + /// + /// 关闭并清理有限状态机。 + /// + internal abstract void Shutdown(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmBase.cs.meta new file mode 100644 index 0000000..f9b5e91 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 41eea376bfd1a4f4d84cfb270e451fab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmManager.cs new file mode 100644 index 0000000..1e916d6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmManager.cs @@ -0,0 +1,411 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.Fsm +{ + /// + /// 有限状态机管理器。 + /// + internal sealed class FsmManager : GameFrameworkModule, IFsmManager + { + private readonly Dictionary m_Fsms; + private readonly List m_TempFsms; + + /// + /// 初始化有限状态机管理器的新实例。 + /// + public FsmManager() + { + m_Fsms = new Dictionary(); + m_TempFsms = new List(); + } + + /// + /// 获取游戏框架模块优先级。 + /// + /// 优先级较高的模块会优先轮询,并且关闭操作会后进行。 + internal override int Priority + { + get + { + return 1; + } + } + + /// + /// 获取有限状态机数量。 + /// + public int Count + { + get + { + return m_Fsms.Count; + } + } + + /// + /// 有限状态机管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + m_TempFsms.Clear(); + if (m_Fsms.Count <= 0) + { + return; + } + + foreach (KeyValuePair fsm in m_Fsms) + { + m_TempFsms.Add(fsm.Value); + } + + foreach (FsmBase fsm in m_TempFsms) + { + if (fsm.IsDestroyed) + { + continue; + } + + fsm.Update(elapseSeconds, realElapseSeconds); + } + } + + /// + /// 关闭并清理有限状态机管理器。 + /// + internal override void Shutdown() + { + foreach (KeyValuePair fsm in m_Fsms) + { + fsm.Value.Shutdown(); + } + + m_Fsms.Clear(); + m_TempFsms.Clear(); + } + + /// + /// 检查是否存在有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 是否存在有限状态机。 + public bool HasFsm() where T : class + { + return InternalHasFsm(new TypeNamePair(typeof(T))); + } + + /// + /// 检查是否存在有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 是否存在有限状态机。 + public bool HasFsm(Type ownerType) + { + if (ownerType == null) + { + throw new GameFrameworkException("Owner type is invalid."); + } + + return InternalHasFsm(new TypeNamePair(ownerType)); + } + + /// + /// 检查是否存在有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 是否存在有限状态机。 + public bool HasFsm(string name) where T : class + { + return InternalHasFsm(new TypeNamePair(typeof(T), name)); + } + + /// + /// 检查是否存在有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 是否存在有限状态机。 + public bool HasFsm(Type ownerType, string name) + { + if (ownerType == null) + { + throw new GameFrameworkException("Owner type is invalid."); + } + + return InternalHasFsm(new TypeNamePair(ownerType, name)); + } + + /// + /// 获取有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要获取的有限状态机。 + public IFsm GetFsm() where T : class + { + return (IFsm)InternalGetFsm(new TypeNamePair(typeof(T))); + } + + /// + /// 获取有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要获取的有限状态机。 + public FsmBase GetFsm(Type ownerType) + { + if (ownerType == null) + { + throw new GameFrameworkException("Owner type is invalid."); + } + + return InternalGetFsm(new TypeNamePair(ownerType)); + } + + /// + /// 获取有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 要获取的有限状态机。 + public IFsm GetFsm(string name) where T : class + { + return (IFsm)InternalGetFsm(new TypeNamePair(typeof(T), name)); + } + + /// + /// 获取有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 要获取的有限状态机。 + public FsmBase GetFsm(Type ownerType, string name) + { + if (ownerType == null) + { + throw new GameFrameworkException("Owner type is invalid."); + } + + return InternalGetFsm(new TypeNamePair(ownerType, name)); + } + + /// + /// 获取所有有限状态机。 + /// + /// 所有有限状态机。 + public FsmBase[] GetAllFsms() + { + int index = 0; + FsmBase[] results = new FsmBase[m_Fsms.Count]; + foreach (KeyValuePair fsm in m_Fsms) + { + results[index++] = fsm.Value; + } + + return results; + } + + /// + /// 获取所有有限状态机。 + /// + /// 所有有限状态机。 + public void GetAllFsms(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair fsm in m_Fsms) + { + results.Add(fsm.Value); + } + } + + /// + /// 创建有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 要创建的有限状态机。 + public IFsm CreateFsm(T owner, params FsmState[] states) where T : class + { + return CreateFsm(string.Empty, owner, states); + } + + /// + /// 创建有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 要创建的有限状态机。 + public IFsm CreateFsm(string name, T owner, params FsmState[] states) where T : class + { + TypeNamePair typeNamePair = new TypeNamePair(typeof(T), name); + if (HasFsm(name)) + { + throw new GameFrameworkException(Utility.Text.Format("Already exist FSM '{0}'.", typeNamePair)); + } + + Fsm fsm = Fsm.Create(name, owner, states); + m_Fsms.Add(typeNamePair, fsm); + return fsm; + } + + /// + /// 创建有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 要创建的有限状态机。 + public IFsm CreateFsm(T owner, List> states) where T : class + { + return CreateFsm(string.Empty, owner, states); + } + + /// + /// 创建有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 要创建的有限状态机。 + public IFsm CreateFsm(string name, T owner, List> states) where T : class + { + TypeNamePair typeNamePair = new TypeNamePair(typeof(T), name); + if (HasFsm(name)) + { + throw new GameFrameworkException(Utility.Text.Format("Already exist FSM '{0}'.", typeNamePair)); + } + + Fsm fsm = Fsm.Create(name, owner, states); + m_Fsms.Add(typeNamePair, fsm); + return fsm; + } + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 是否销毁有限状态机成功。 + public bool DestroyFsm() where T : class + { + return InternalDestroyFsm(new TypeNamePair(typeof(T))); + } + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 是否销毁有限状态机成功。 + public bool DestroyFsm(Type ownerType) + { + if (ownerType == null) + { + throw new GameFrameworkException("Owner type is invalid."); + } + + return InternalDestroyFsm(new TypeNamePair(ownerType)); + } + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要销毁的有限状态机名称。 + /// 是否销毁有限状态机成功。 + public bool DestroyFsm(string name) where T : class + { + return InternalDestroyFsm(new TypeNamePair(typeof(T), name)); + } + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要销毁的有限状态机名称。 + /// 是否销毁有限状态机成功。 + public bool DestroyFsm(Type ownerType, string name) + { + if (ownerType == null) + { + throw new GameFrameworkException("Owner type is invalid."); + } + + return InternalDestroyFsm(new TypeNamePair(ownerType, name)); + } + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要销毁的有限状态机。 + /// 是否销毁有限状态机成功。 + public bool DestroyFsm(IFsm fsm) where T : class + { + if (fsm == null) + { + throw new GameFrameworkException("FSM is invalid."); + } + + return InternalDestroyFsm(new TypeNamePair(typeof(T), fsm.Name)); + } + + /// + /// 销毁有限状态机。 + /// + /// 要销毁的有限状态机。 + /// 是否销毁有限状态机成功。 + public bool DestroyFsm(FsmBase fsm) + { + if (fsm == null) + { + throw new GameFrameworkException("FSM is invalid."); + } + + return InternalDestroyFsm(new TypeNamePair(fsm.OwnerType, fsm.Name)); + } + + private bool InternalHasFsm(TypeNamePair typeNamePair) + { + return m_Fsms.ContainsKey(typeNamePair); + } + + private FsmBase InternalGetFsm(TypeNamePair typeNamePair) + { + FsmBase fsm = null; + if (m_Fsms.TryGetValue(typeNamePair, out fsm)) + { + return fsm; + } + + return null; + } + + private bool InternalDestroyFsm(TypeNamePair typeNamePair) + { + FsmBase fsm = null; + if (m_Fsms.TryGetValue(typeNamePair, out fsm)) + { + fsm.Shutdown(); + return m_Fsms.Remove(typeNamePair); + } + + return false; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmManager.cs.meta new file mode 100644 index 0000000..6586071 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8d195a2b83a404c409bb0bc49af63d88 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmState.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmState.cs new file mode 100644 index 0000000..212b003 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmState.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.Fsm +{ + /// + /// 有限状态机状态基类。 + /// + /// 有限状态机持有者类型。 + public abstract class FsmState where T : class + { + /// + /// 初始化有限状态机状态基类的新实例。 + /// + public FsmState() + { + } + + /// + /// 有限状态机状态初始化时调用。 + /// + /// 有限状态机引用。 + protected internal virtual void OnInit(IFsm fsm) + { + } + + /// + /// 有限状态机状态进入时调用。 + /// + /// 有限状态机引用。 + protected internal virtual void OnEnter(IFsm fsm) + { + } + + /// + /// 有限状态机状态轮询时调用。 + /// + /// 有限状态机引用。 + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + protected internal virtual void OnUpdate(IFsm fsm, float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 有限状态机状态离开时调用。 + /// + /// 有限状态机引用。 + /// 是否是关闭有限状态机时触发。 + protected internal virtual void OnLeave(IFsm fsm, bool isShutdown) + { + } + + /// + /// 有限状态机状态销毁时调用。 + /// + /// 有限状态机引用。 + protected internal virtual void OnDestroy(IFsm fsm) + { + } + + /// + /// 切换当前有限状态机状态。 + /// + /// 要切换到的有限状态机状态类型。 + /// 有限状态机引用。 + protected void ChangeState(IFsm fsm) where TState : FsmState + { + Fsm fsmImplement = (Fsm)fsm; + if (fsmImplement == null) + { + throw new GameFrameworkException("FSM is invalid."); + } + + fsmImplement.ChangeState(); + } + + /// + /// 切换当前有限状态机状态。 + /// + /// 有限状态机引用。 + /// 要切换到的有限状态机状态类型。 + protected void ChangeState(IFsm fsm, Type stateType) + { + Fsm fsmImplement = (Fsm)fsm; + if (fsmImplement == null) + { + throw new GameFrameworkException("FSM is invalid."); + } + + if (stateType == null) + { + throw new GameFrameworkException("State type is invalid."); + } + + if (!typeof(FsmState).IsAssignableFrom(stateType)) + { + throw new GameFrameworkException(Utility.Text.Format("State type '{0}' is invalid.", stateType.FullName)); + } + + fsmImplement.ChangeState(stateType); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmState.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmState.cs.meta new file mode 100644 index 0000000..c38b534 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/FsmState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6f1d5955fd4cda84f8c06a860817387a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/IFsm.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/IFsm.cs new file mode 100644 index 0000000..f97563b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/IFsm.cs @@ -0,0 +1,179 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.Fsm +{ + /// + /// 有限状态机接口。 + /// + /// 有限状态机持有者类型。 + public interface IFsm where T : class + { + /// + /// 获取有限状态机名称。 + /// + string Name + { + get; + } + + /// + /// 获取有限状态机完整名称。 + /// + string FullName + { + get; + } + + /// + /// 获取有限状态机持有者。 + /// + T Owner + { + get; + } + + /// + /// 获取有限状态机中状态的数量。 + /// + int FsmStateCount + { + get; + } + + /// + /// 获取有限状态机是否正在运行。 + /// + bool IsRunning + { + get; + } + + /// + /// 获取有限状态机是否被销毁。 + /// + bool IsDestroyed + { + get; + } + + /// + /// 获取当前有限状态机状态。 + /// + FsmState CurrentState + { + get; + } + + /// + /// 获取当前有限状态机状态持续时间。 + /// + float CurrentStateTime + { + get; + } + + /// + /// 开始有限状态机。 + /// + /// 要开始的有限状态机状态类型。 + void Start() where TState : FsmState; + + /// + /// 开始有限状态机。 + /// + /// 要开始的有限状态机状态类型。 + void Start(Type stateType); + + /// + /// 是否存在有限状态机状态。 + /// + /// 要检查的有限状态机状态类型。 + /// 是否存在有限状态机状态。 + bool HasState() where TState : FsmState; + + /// + /// 是否存在有限状态机状态。 + /// + /// 要检查的有限状态机状态类型。 + /// 是否存在有限状态机状态。 + bool HasState(Type stateType); + + /// + /// 获取有限状态机状态。 + /// + /// 要获取的有限状态机状态类型。 + /// 要获取的有限状态机状态。 + TState GetState() where TState : FsmState; + + /// + /// 获取有限状态机状态。 + /// + /// 要获取的有限状态机状态类型。 + /// 要获取的有限状态机状态。 + FsmState GetState(Type stateType); + + /// + /// 获取有限状态机的所有状态。 + /// + /// 有限状态机的所有状态。 + FsmState[] GetAllStates(); + + /// + /// 获取有限状态机的所有状态。 + /// + /// 有限状态机的所有状态。 + void GetAllStates(List> results); + + /// + /// 是否存在有限状态机数据。 + /// + /// 有限状态机数据名称。 + /// 有限状态机数据是否存在。 + bool HasData(string name); + + /// + /// 获取有限状态机数据。 + /// + /// 要获取的有限状态机数据的类型。 + /// 有限状态机数据名称。 + /// 要获取的有限状态机数据。 + TData GetData(string name) where TData : Variable; + + /// + /// 获取有限状态机数据。 + /// + /// 有限状态机数据名称。 + /// 要获取的有限状态机数据。 + Variable GetData(string name); + + /// + /// 设置有限状态机数据。 + /// + /// 要设置的有限状态机数据的类型。 + /// 有限状态机数据名称。 + /// 要设置的有限状态机数据。 + void SetData(string name, TData data) where TData : Variable; + + /// + /// 设置有限状态机数据。 + /// + /// 有限状态机数据名称。 + /// 要设置的有限状态机数据。 + void SetData(string name, Variable data); + + /// + /// 移除有限状态机数据。 + /// + /// 有限状态机数据名称。 + /// 是否移除有限状态机数据成功。 + bool RemoveData(string name); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/IFsm.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/IFsm.cs.meta new file mode 100644 index 0000000..f0e7571 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/IFsm.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 68a04ab91d4f6a04288a73e004c86b6e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/IFsmManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/IFsmManager.cs new file mode 100644 index 0000000..0f0854b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/IFsmManager.cs @@ -0,0 +1,181 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.Fsm +{ + /// + /// 有限状态机管理器。 + /// + public interface IFsmManager + { + /// + /// 获取有限状态机数量。 + /// + int Count + { + get; + } + + /// + /// 检查是否存在有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 是否存在有限状态机。 + bool HasFsm() where T : class; + + /// + /// 检查是否存在有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 是否存在有限状态机。 + bool HasFsm(Type ownerType); + + /// + /// 检查是否存在有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 是否存在有限状态机。 + bool HasFsm(string name) where T : class; + + /// + /// 检查是否存在有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 是否存在有限状态机。 + bool HasFsm(Type ownerType, string name); + + /// + /// 获取有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要获取的有限状态机。 + IFsm GetFsm() where T : class; + + /// + /// 获取有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要获取的有限状态机。 + FsmBase GetFsm(Type ownerType); + + /// + /// 获取有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 要获取的有限状态机。 + IFsm GetFsm(string name) where T : class; + + /// + /// 获取有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 要获取的有限状态机。 + FsmBase GetFsm(Type ownerType, string name); + + /// + /// 获取所有有限状态机。 + /// + /// 所有有限状态机。 + FsmBase[] GetAllFsms(); + + /// + /// 获取所有有限状态机。 + /// + /// 所有有限状态机。 + void GetAllFsms(List results); + + /// + /// 创建有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 要创建的有限状态机。 + IFsm CreateFsm(T owner, params FsmState[] states) where T : class; + + /// + /// 创建有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 要创建的有限状态机。 + IFsm CreateFsm(string name, T owner, params FsmState[] states) where T : class; + + /// + /// 创建有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 要创建的有限状态机。 + IFsm CreateFsm(T owner, List> states) where T : class; + + /// + /// 创建有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 要创建的有限状态机。 + IFsm CreateFsm(string name, T owner, List> states) where T : class; + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 是否销毁有限状态机成功。 + bool DestroyFsm() where T : class; + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 是否销毁有限状态机成功。 + bool DestroyFsm(Type ownerType); + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要销毁的有限状态机名称。 + /// 是否销毁有限状态机成功。 + bool DestroyFsm(string name) where T : class; + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要销毁的有限状态机名称。 + /// 是否销毁有限状态机成功。 + bool DestroyFsm(Type ownerType, string name); + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要销毁的有限状态机。 + /// 是否销毁有限状态机成功。 + bool DestroyFsm(IFsm fsm) where T : class; + + /// + /// 销毁有限状态机。 + /// + /// 要销毁的有限状态机。 + /// 是否销毁有限状态机成功。 + bool DestroyFsm(FsmBase fsm); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/IFsmManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/IFsmManager.cs.meta new file mode 100644 index 0000000..8cee9ae --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Fsm/IFsmManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 17fa8008d81863a4b935d453a45ddc43 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/GameFramework.asmdef b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/GameFramework.asmdef new file mode 100644 index 0000000..dbe8ffa --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/GameFramework.asmdef @@ -0,0 +1,14 @@ +{ + "name": "GameFramework", + "rootNamespace": "", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/GameFramework.asmdef.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/GameFramework.asmdef.meta new file mode 100644 index 0000000..2408661 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/GameFramework.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: bc1756600545274478db6a24483faf43 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries.meta new file mode 100644 index 0000000..ac0c9e5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1a46d69a0c58378428a0f12b118e5571 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries/ICSharpCode.SharpZipLib.dll b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries/ICSharpCode.SharpZipLib.dll new file mode 100644 index 0000000..fe643eb Binary files /dev/null and b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries/ICSharpCode.SharpZipLib.dll differ diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries/ICSharpCode.SharpZipLib.dll.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries/ICSharpCode.SharpZipLib.dll.meta new file mode 100644 index 0000000..4f6079f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries/ICSharpCode.SharpZipLib.dll.meta @@ -0,0 +1,33 @@ +fileFormatVersion: 2 +guid: bc9c7e2be608ffb4f900d02be002262e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries/link.xml b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries/link.xml new file mode 100644 index 0000000..c13e405 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries/link.xml @@ -0,0 +1,41 @@ + + + + + + + diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries/link.xml.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries/link.xml.meta new file mode 100644 index 0000000..7dee6d6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Libraries/link.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 843cc923151568443b86e022f705a263 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization.meta new file mode 100644 index 0000000..5c40bd0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d1fd84244cb36db4d99ee03b6d61b246 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/ILocalizationHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/ILocalizationHelper.cs new file mode 100644 index 0000000..7caaf09 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/ILocalizationHelper.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Localization +{ + /// + /// 本地化辅助器接口。 + /// + public interface ILocalizationHelper + { + /// + /// 获取系统语言。 + /// + Language SystemLanguage + { + get; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/ILocalizationHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/ILocalizationHelper.cs.meta new file mode 100644 index 0000000..c93b133 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/ILocalizationHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9a6a8606f5a51d243acbf47da824398c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/ILocalizationManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/ILocalizationManager.cs new file mode 100644 index 0000000..abaec56 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/ILocalizationManager.cs @@ -0,0 +1,504 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; + +namespace GameFramework.Localization +{ + /// + /// 本地化管理器接口。 + /// + public interface ILocalizationManager : IDataProvider + { + /// + /// 获取或设置本地化语言。 + /// + Language Language + { + get; + set; + } + + /// + /// 获取系统语言。 + /// + Language SystemLanguage + { + get; + } + + /// + /// 获取字典数量。 + /// + int DictionaryCount + { + get; + } + + /// + /// 获取缓冲二进制流的大小。 + /// + int CachedBytesSize + { + get; + } + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + void SetResourceManager(IResourceManager resourceManager); + + /// + /// 设置本地化数据提供者辅助器。 + /// + /// 本地化数据提供者辅助器。 + void SetDataProviderHelper(IDataProviderHelper dataProviderHelper); + + /// + /// 设置本地化辅助器。 + /// + /// 本地化辅助器。 + void SetLocalizationHelper(ILocalizationHelper localizationHelper); + + /// + /// 确保二进制流缓存分配足够大小的内存并缓存。 + /// + /// 要确保二进制流缓存分配内存的大小。 + void EnsureCachedBytesSize(int ensureSize); + + /// + /// 释放缓存的二进制流。 + /// + void FreeCachedBytes(); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典主键。 + /// 要获取的字典内容字符串。 + string GetString(string key); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数的类型。 + /// 字典主键。 + /// 字典参数。 + /// 要获取的字典内容字符串。 + string GetString(string key, T arg); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典参数 13 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 字典参数 13。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典参数 13 的类型。 + /// 字典参数 14 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 字典参数 13。 + /// 字典参数 14。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典参数 13 的类型。 + /// 字典参数 14 的类型。 + /// 字典参数 15 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 字典参数 13。 + /// 字典参数 14。 + /// 字典参数 15。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典参数 13 的类型。 + /// 字典参数 14 的类型。 + /// 字典参数 15 的类型。 + /// 字典参数 16 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 字典参数 13。 + /// 字典参数 14。 + /// 字典参数 15。 + /// 字典参数 16。 + /// 要获取的字典内容字符串。 + string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); + + /// + /// 是否存在字典。 + /// + /// 字典主键。 + /// 是否存在字典。 + bool HasRawString(string key); + + /// + /// 根据字典主键获取字典值。 + /// + /// 字典主键。 + /// 字典值。 + string GetRawString(string key); + + /// + /// 增加字典。 + /// + /// 字典主键。 + /// 字典内容。 + /// 是否增加字典成功。 + bool AddRawString(string key, string value); + + /// + /// 移除字典。 + /// + /// 字典主键。 + /// 是否移除字典成功。 + bool RemoveRawString(string key); + + /// + /// 清空所有字典。 + /// + void RemoveAllRawStrings(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/ILocalizationManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/ILocalizationManager.cs.meta new file mode 100644 index 0000000..1d91bf6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/ILocalizationManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4c9054927f75d144a805e7f7c948a425 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/Language.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/Language.cs new file mode 100644 index 0000000..ae4f929 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/Language.cs @@ -0,0 +1,270 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Localization +{ + /// + /// 本地化语言。 + /// + public enum Language : byte + { + /// + /// 未指定。 + /// + Unspecified = 0, + + /// + /// 南非荷兰语。 + /// + Afrikaans, + + /// + /// 阿尔巴尼亚语。 + /// + Albanian, + + /// + /// 阿拉伯语。 + /// + Arabic, + + /// + /// 巴斯克语。 + /// + Basque, + + /// + /// 白俄罗斯语。 + /// + Belarusian, + + /// + /// 保加利亚语。 + /// + Bulgarian, + + /// + /// 加泰罗尼亚语。 + /// + Catalan, + + /// + /// 简体中文。 + /// + ChineseSimplified, + + /// + /// 繁体中文。 + /// + ChineseTraditional, + + /// + /// 克罗地亚语。 + /// + Croatian, + + /// + /// 捷克语。 + /// + Czech, + + /// + /// 丹麦语。 + /// + Danish, + + /// + /// 荷兰语。 + /// + Dutch, + + /// + /// 英语。 + /// + English, + + /// + /// 爱沙尼亚语。 + /// + Estonian, + + /// + /// 法罗语。 + /// + Faroese, + + /// + /// 芬兰语。 + /// + Finnish, + + /// + /// 法语。 + /// + French, + + /// + /// 格鲁吉亚语。 + /// + Georgian, + + /// + /// 德语。 + /// + German, + + /// + /// 希腊语。 + /// + Greek, + + /// + /// 希伯来语。 + /// + Hebrew, + + /// + /// 匈牙利语。 + /// + Hungarian, + + /// + /// 冰岛语。 + /// + Icelandic, + + /// + /// 印尼语。 + /// + Indonesian, + + /// + /// 意大利语。 + /// + Italian, + + /// + /// 日语。 + /// + Japanese, + + /// + /// 韩语。 + /// + Korean, + + /// + /// 拉脱维亚语。 + /// + Latvian, + + /// + /// 立陶宛语。 + /// + Lithuanian, + + /// + /// 马其顿语。 + /// + Macedonian, + + /// + /// 马拉雅拉姆语。 + /// + Malayalam, + + /// + /// 挪威语。 + /// + Norwegian, + + /// + /// 波斯语。 + /// + Persian, + + /// + /// 波兰语。 + /// + Polish, + + /// + /// 巴西葡萄牙语。 + /// + PortugueseBrazil, + + /// + /// 葡萄牙语。 + /// + PortuguesePortugal, + + /// + /// 罗马尼亚语。 + /// + Romanian, + + /// + /// 俄语。 + /// + Russian, + + /// + /// 塞尔维亚克罗地亚语。 + /// + SerboCroatian, + + /// + /// 塞尔维亚西里尔语。 + /// + SerbianCyrillic, + + /// + /// 塞尔维亚拉丁语。 + /// + SerbianLatin, + + /// + /// 斯洛伐克语。 + /// + Slovak, + + /// + /// 斯洛文尼亚语。 + /// + Slovenian, + + /// + /// 西班牙语。 + /// + Spanish, + + /// + /// 瑞典语。 + /// + Swedish, + + /// + /// 泰语。 + /// + Thai, + + /// + /// 土耳其语。 + /// + Turkish, + + /// + /// 乌克兰语。 + /// + Ukrainian, + + /// + /// 越南语。 + /// + Vietnamese + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/Language.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/Language.cs.meta new file mode 100644 index 0000000..887ab22 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/Language.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0809c6adf37e2aa498051908ca0f3fc9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/LocalizationManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/LocalizationManager.cs new file mode 100644 index 0000000..7c045d6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/LocalizationManager.cs @@ -0,0 +1,1065 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System; +using System.Collections.Generic; + +namespace GameFramework.Localization +{ + /// + /// 本地化管理器。 + /// + internal sealed partial class LocalizationManager : GameFrameworkModule, ILocalizationManager + { + private readonly Dictionary m_Dictionary; + private readonly DataProvider m_DataProvider; + private ILocalizationHelper m_LocalizationHelper; + private Language m_Language; + + /// + /// 初始化本地化管理器的新实例。 + /// + public LocalizationManager() + { + m_Dictionary = new Dictionary(StringComparer.Ordinal); + m_DataProvider = new DataProvider(this); + m_LocalizationHelper = null; + m_Language = Language.Unspecified; + } + + /// + /// 获取或设置本地化语言。 + /// + public Language Language + { + get + { + return m_Language; + } + set + { + if (value == Language.Unspecified) + { + throw new GameFrameworkException("Language is invalid."); + } + + m_Language = value; + } + } + + /// + /// 获取系统语言。 + /// + public Language SystemLanguage + { + get + { + if (m_LocalizationHelper == null) + { + throw new GameFrameworkException("You must set localization helper first."); + } + + return m_LocalizationHelper.SystemLanguage; + } + } + + /// + /// 获取字典数量。 + /// + public int DictionaryCount + { + get + { + return m_Dictionary.Count; + } + } + + /// + /// 获取缓冲二进制流的大小。 + /// + public int CachedBytesSize + { + get + { + return DataProvider.CachedBytesSize; + } + } + + /// + /// 读取字典成功事件。 + /// + public event EventHandler ReadDataSuccess + { + add + { + m_DataProvider.ReadDataSuccess += value; + } + remove + { + m_DataProvider.ReadDataSuccess -= value; + } + } + + /// + /// 读取字典失败事件。 + /// + public event EventHandler ReadDataFailure + { + add + { + m_DataProvider.ReadDataFailure += value; + } + remove + { + m_DataProvider.ReadDataFailure -= value; + } + } + + /// + /// 读取字典更新事件。 + /// + public event EventHandler ReadDataUpdate + { + add + { + m_DataProvider.ReadDataUpdate += value; + } + remove + { + m_DataProvider.ReadDataUpdate -= value; + } + } + + /// + /// 读取字典时加载依赖资源事件。 + /// + public event EventHandler ReadDataDependencyAsset + { + add + { + m_DataProvider.ReadDataDependencyAsset += value; + } + remove + { + m_DataProvider.ReadDataDependencyAsset -= value; + } + } + + /// + /// 本地化管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 关闭并清理本地化管理器。 + /// + internal override void Shutdown() + { + } + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + public void SetResourceManager(IResourceManager resourceManager) + { + m_DataProvider.SetResourceManager(resourceManager); + } + + /// + /// 设置本地化数据提供者辅助器。 + /// + /// 本地化数据提供者辅助器。 + public void SetDataProviderHelper(IDataProviderHelper dataProviderHelper) + { + m_DataProvider.SetDataProviderHelper(dataProviderHelper); + } + + /// + /// 设置本地化辅助器。 + /// + /// 本地化辅助器。 + public void SetLocalizationHelper(ILocalizationHelper localizationHelper) + { + if (localizationHelper == null) + { + throw new GameFrameworkException("Localization helper is invalid."); + } + + m_LocalizationHelper = localizationHelper; + } + + /// + /// 确保二进制流缓存分配足够大小的内存并缓存。 + /// + /// 要确保二进制流缓存分配内存的大小。 + public void EnsureCachedBytesSize(int ensureSize) + { + DataProvider.EnsureCachedBytesSize(ensureSize); + } + + /// + /// 释放缓存的二进制流。 + /// + public void FreeCachedBytes() + { + DataProvider.FreeCachedBytes(); + } + + /// + /// 读取字典。 + /// + /// 字典资源名称。 + public void ReadData(string dictionaryAssetName) + { + m_DataProvider.ReadData(dictionaryAssetName); + } + + /// + /// 读取字典。 + /// + /// 字典资源名称。 + /// 加载字典资源的优先级。 + public void ReadData(string dictionaryAssetName, int priority) + { + m_DataProvider.ReadData(dictionaryAssetName, priority); + } + + /// + /// 读取字典。 + /// + /// 字典资源名称。 + /// 用户自定义数据。 + public void ReadData(string dictionaryAssetName, object userData) + { + m_DataProvider.ReadData(dictionaryAssetName, userData); + } + + /// + /// 读取字典。 + /// + /// 字典资源名称。 + /// 加载字典资源的优先级。 + /// 用户自定义数据。 + public void ReadData(string dictionaryAssetName, int priority, object userData) + { + m_DataProvider.ReadData(dictionaryAssetName, priority, userData); + } + + /// + /// 解析字典。 + /// + /// 要解析的字典字符串。 + /// 是否解析字典成功。 + public bool ParseData(string dictionaryString) + { + return m_DataProvider.ParseData(dictionaryString); + } + + /// + /// 解析字典。 + /// + /// 要解析的字典字符串。 + /// 用户自定义数据。 + /// 是否解析字典成功。 + public bool ParseData(string dictionaryString, object userData) + { + return m_DataProvider.ParseData(dictionaryString, userData); + } + + /// + /// 解析字典。 + /// + /// 要解析的字典二进制流。 + /// 是否解析字典成功。 + public bool ParseData(byte[] dictionaryBytes) + { + return m_DataProvider.ParseData(dictionaryBytes); + } + + /// + /// 解析字典。 + /// + /// 要解析的字典二进制流。 + /// 用户自定义数据。 + /// 是否解析字典成功。 + public bool ParseData(byte[] dictionaryBytes, object userData) + { + return m_DataProvider.ParseData(dictionaryBytes, userData); + } + + /// + /// 解析字典。 + /// + /// 要解析的字典二进制流。 + /// 字典二进制流的起始位置。 + /// 字典二进制流的长度。 + /// 是否解析字典成功。 + public bool ParseData(byte[] dictionaryBytes, int startIndex, int length) + { + return m_DataProvider.ParseData(dictionaryBytes, startIndex, length); + } + + /// + /// 解析字典。 + /// + /// 要解析的字典二进制流。 + /// 字典二进制流的起始位置。 + /// 字典二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析字典成功。 + public bool ParseData(byte[] dictionaryBytes, int startIndex, int length, object userData) + { + return m_DataProvider.ParseData(dictionaryBytes, startIndex, length, userData); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典主键。 + /// 要获取的字典内容字符串。 + public string GetString(string key) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + return value; + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数的类型。 + /// 字典主键。 + /// 字典参数。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T arg) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3}", key, value, arg, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3},{4}", key, value, arg1, arg2, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3},{4},{5}", key, value, arg1, arg2, arg3, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6}", key, value, arg1, arg2, arg3, arg4, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4, arg5); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7}", key, value, arg1, arg2, arg3, arg4, arg5, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4, arg5, arg6); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8}", key, value, arg1, arg2, arg3, arg4, arg5, arg6, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}", key, value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}", key, value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11}", key, value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12}", key, value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13}", key, value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14}", key, value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典参数 13 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 字典参数 13。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); + } + catch (Exception exception) + { + return Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15}", key, value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典参数 13 的类型。 + /// 字典参数 14 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 字典参数 13。 + /// 字典参数 14。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); + } + catch (Exception exception) + { + string args = Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13}", arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); + return Utility.Text.Format("{0},{1},{2},{3}", key, value, args, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典参数 13 的类型。 + /// 字典参数 14 的类型。 + /// 字典参数 15 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 字典参数 13。 + /// 字典参数 14。 + /// 字典参数 15。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); + } + catch (Exception exception) + { + string args = Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14}", arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); + return Utility.Text.Format("{0},{1},{2},{3}", key, value, args, exception); + } + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典参数 13 的类型。 + /// 字典参数 14 的类型。 + /// 字典参数 15 的类型。 + /// 字典参数 16 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 字典参数 13。 + /// 字典参数 14。 + /// 字典参数 15。 + /// 字典参数 16。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + string value = GetRawString(key); + if (value == null) + { + return Utility.Text.Format("{0}", key); + } + + try + { + return Utility.Text.Format(value, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); + } + catch (Exception exception) + { + string args = Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15}", arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); + return Utility.Text.Format("{0},{1},{2},{3}", key, value, args, exception); + } + } + + /// + /// 是否存在字典。 + /// + /// 字典主键。 + /// 是否存在字典。 + public bool HasRawString(string key) + { + if (string.IsNullOrEmpty(key)) + { + throw new GameFrameworkException("Key is invalid."); + } + + return m_Dictionary.ContainsKey(key); + } + + /// + /// 根据字典主键获取字典值。 + /// + /// 字典主键。 + /// 字典值。 + public string GetRawString(string key) + { + if (string.IsNullOrEmpty(key)) + { + throw new GameFrameworkException("Key is invalid."); + } + + string value = null; + if (m_Dictionary.TryGetValue(key, out value)) + { + return value; + } + + return null; + } + + /// + /// 增加字典。 + /// + /// 字典主键。 + /// 字典内容。 + /// 是否增加字典成功。 + public bool AddRawString(string key, string value) + { + if (string.IsNullOrEmpty(key)) + { + throw new GameFrameworkException("Key is invalid."); + } + + if (m_Dictionary.ContainsKey(key)) + { + return false; + } + + m_Dictionary.Add(key, value ?? string.Empty); + return true; + } + + /// + /// 移除字典。 + /// + /// 字典主键。 + /// 是否移除字典成功。 + public bool RemoveRawString(string key) + { + if (string.IsNullOrEmpty(key)) + { + throw new GameFrameworkException("Key is invalid."); + } + + return m_Dictionary.Remove(key); + } + + /// + /// 清空所有字典。 + /// + public void RemoveAllRawStrings() + { + m_Dictionary.Clear(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/LocalizationManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/LocalizationManager.cs.meta new file mode 100644 index 0000000..f8c9dd0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Localization/LocalizationManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fc0554d5f84bc5e4caaa5af77561973b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network.meta new file mode 100644 index 0000000..194969a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 10db358e21ecb0341bc7907a2add9524 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/AddressFamily.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/AddressFamily.cs new file mode 100644 index 0000000..a8e79a5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/AddressFamily.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Network +{ + /// + /// 网络地址类型。 + /// + public enum AddressFamily : byte + { + /// + /// 未知。 + /// + Unknown = 0, + + /// + /// IP 版本 4。 + /// + IPv4, + + /// + /// IP 版本 6。 + /// + IPv6 + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/AddressFamily.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/AddressFamily.cs.meta new file mode 100644 index 0000000..fcb6b51 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/AddressFamily.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2f0086471a7a51248ae7581b2d2ee098 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkChannel.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkChannel.cs new file mode 100644 index 0000000..251614d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkChannel.cs @@ -0,0 +1,164 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Net; +using System.Net.Sockets; + +namespace GameFramework.Network +{ + /// + /// 网络频道接口。 + /// + public interface INetworkChannel + { + /// + /// 获取网络频道名称。 + /// + string Name + { + get; + } + + /// + /// 获取网络频道所使用的 Socket。 + /// + Socket Socket + { + get; + } + + /// + /// 获取是否已连接。 + /// + bool Connected + { + get; + } + + /// + /// 获取网络服务类型。 + /// + ServiceType ServiceType + { + get; + } + + /// + /// 获取网络地址类型。 + /// + AddressFamily AddressFamily + { + get; + } + + /// + /// 获取要发送的消息包数量。 + /// + int SendPacketCount + { + get; + } + + /// + /// 获取累计发送的消息包数量。 + /// + int SentPacketCount + { + get; + } + + /// + /// 获取已接收未处理的消息包数量。 + /// + int ReceivePacketCount + { + get; + } + + /// + /// 获取累计已接收的消息包数量。 + /// + int ReceivedPacketCount + { + get; + } + + /// + /// 获取或设置当收到消息包时是否重置心跳流逝时间。 + /// + bool ResetHeartBeatElapseSecondsWhenReceivePacket + { + get; + set; + } + + /// + /// 获取丢失心跳的次数。 + /// + int MissHeartBeatCount + { + get; + } + + /// + /// 获取或设置心跳间隔时长,以秒为单位。 + /// + float HeartBeatInterval + { + get; + set; + } + + /// + /// 获取心跳等待时长,以秒为单位。 + /// + float HeartBeatElapseSeconds + { + get; + } + + /// + /// 注册网络消息包处理函数。 + /// + /// 要注册的网络消息包处理函数。 + void RegisterHandler(IPacketHandler handler); + + /// + /// 设置默认事件处理函数。 + /// + /// 要设置的默认事件处理函数。 + void SetDefaultHandler(EventHandler handler); + + /// + /// 连接到远程主机。 + /// + /// 远程主机的 IP 地址。 + /// 远程主机的端口号。 + void Connect(IPAddress ipAddress, int port); + + /// + /// 连接到远程主机。 + /// + /// 远程主机的 IP 地址。 + /// 远程主机的端口号。 + /// 用户自定义数据。 + void Connect(IPAddress ipAddress, int port, object userData); + + /// + /// 关闭网络频道。 + /// + void Close(); + + /// + /// 向远程主机发送消息包。 + /// + /// 消息包类型。 + /// 要发送的消息包。 + void Send(T packet) where T : Packet; + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkChannel.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkChannel.cs.meta new file mode 100644 index 0000000..db23eb9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkChannel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d615c82b424a0f841ba42857ce1ff896 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkChannelHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkChannelHelper.cs new file mode 100644 index 0000000..241f0de --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkChannelHelper.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.IO; + +namespace GameFramework.Network +{ + /// + /// 网络频道辅助器接口。 + /// + public interface INetworkChannelHelper + { + /// + /// 获取消息包头长度。 + /// + int PacketHeaderLength + { + get; + } + + /// + /// 初始化网络频道辅助器。 + /// + /// 网络频道。 + void Initialize(INetworkChannel networkChannel); + + /// + /// 关闭并清理网络频道辅助器。 + /// + void Shutdown(); + + /// + /// 准备进行连接。 + /// + void PrepareForConnecting(); + + /// + /// 发送心跳消息包。 + /// + /// 是否发送心跳消息包成功。 + bool SendHeartBeat(); + + /// + /// 序列化消息包。 + /// + /// 消息包类型。 + /// 要序列化的消息包。 + /// 要序列化的目标流。 + /// 是否序列化成功。 + bool Serialize(T packet, Stream destination) where T : Packet; + + /// + /// 反序列化消息包头。 + /// + /// 要反序列化的来源流。 + /// 用户自定义错误数据。 + /// 反序列化后的消息包头。 + IPacketHeader DeserializePacketHeader(Stream source, out object customErrorData); + + /// + /// 反序列化消息包。 + /// + /// 消息包头。 + /// 要反序列化的来源流。 + /// 用户自定义错误数据。 + /// 反序列化后的消息包。 + Packet DeserializePacket(IPacketHeader packetHeader, Stream source, out object customErrorData); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkChannelHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkChannelHelper.cs.meta new file mode 100644 index 0000000..f1f2108 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkChannelHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 97bf22cdf6563e94fb204efda40e85a2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkManager.cs new file mode 100644 index 0000000..96ce74c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkManager.cs @@ -0,0 +1,93 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.Network +{ + /// + /// 网络管理器接口。 + /// + public interface INetworkManager + { + /// + /// 获取网络频道数量。 + /// + int NetworkChannelCount + { + get; + } + + /// + /// 网络连接成功事件。 + /// + event EventHandler NetworkConnected; + + /// + /// 网络连接关闭事件。 + /// + event EventHandler NetworkClosed; + + /// + /// 网络心跳包丢失事件。 + /// + event EventHandler NetworkMissHeartBeat; + + /// + /// 网络错误事件。 + /// + event EventHandler NetworkError; + + /// + /// 用户自定义网络错误事件。 + /// + event EventHandler NetworkCustomError; + + /// + /// 检查是否存在网络频道。 + /// + /// 网络频道名称。 + /// 是否存在网络频道。 + bool HasNetworkChannel(string name); + + /// + /// 获取网络频道。 + /// + /// 网络频道名称。 + /// 要获取的网络频道。 + INetworkChannel GetNetworkChannel(string name); + + /// + /// 获取所有网络频道。 + /// + /// 所有网络频道。 + INetworkChannel[] GetAllNetworkChannels(); + + /// + /// 获取所有网络频道。 + /// + /// 所有网络频道。 + void GetAllNetworkChannels(List results); + + /// + /// 创建网络频道。 + /// + /// 网络频道名称。 + /// 网络服务类型。 + /// 网络频道辅助器。 + /// 要创建的网络频道。 + INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType, INetworkChannelHelper networkChannelHelper); + + /// + /// 销毁网络频道。 + /// + /// 网络频道名称。 + /// 是否销毁网络频道成功。 + bool DestroyNetworkChannel(string name); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkManager.cs.meta new file mode 100644 index 0000000..7594f03 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/INetworkManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b4f5ca33aebf0644b9d5cacbb6d322ff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/IPacketHandler.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/IPacketHandler.cs new file mode 100644 index 0000000..e157ee8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/IPacketHandler.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Network +{ + /// + /// 网络消息包处理器接口。 + /// + public interface IPacketHandler + { + /// + /// 获取网络消息包协议编号。 + /// + int Id + { + get; + } + + /// + /// 网络消息包处理函数。 + /// + /// 网络消息包源。 + /// 网络消息包内容。 + void Handle(object sender, Packet packet); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/IPacketHandler.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/IPacketHandler.cs.meta new file mode 100644 index 0000000..1e90777 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/IPacketHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: da90be0be6ea5ff448a860bed0a69368 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/IPacketHeader.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/IPacketHeader.cs new file mode 100644 index 0000000..b77b75b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/IPacketHeader.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Network +{ + /// + /// 网络消息包头接口。 + /// + public interface IPacketHeader + { + /// + /// 获取网络消息包长度。 + /// + int PacketLength + { + get; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/IPacketHeader.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/IPacketHeader.cs.meta new file mode 100644 index 0000000..679c719 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/IPacketHeader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2622209275a293f4fa5e7a3e751347c1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkClosedEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkClosedEventArgs.cs new file mode 100644 index 0000000..86d0251 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkClosedEventArgs.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Network +{ + /// + /// 网络连接关闭事件。 + /// + public sealed class NetworkClosedEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化网络连接关闭事件的新实例。 + /// + public NetworkClosedEventArgs() + { + NetworkChannel = null; + } + + /// + /// 获取网络频道。 + /// + public INetworkChannel NetworkChannel + { + get; + private set; + } + + /// + /// 创建网络连接关闭事件。 + /// + /// 网络频道。 + /// 创建的网络连接关闭事件。 + public static NetworkClosedEventArgs Create(INetworkChannel networkChannel) + { + NetworkClosedEventArgs networkClosedEventArgs = ReferencePool.Acquire(); + networkClosedEventArgs.NetworkChannel = networkChannel; + return networkClosedEventArgs; + } + + /// + /// 清理网络连接关闭事件。 + /// + public override void Clear() + { + NetworkChannel = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkClosedEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkClosedEventArgs.cs.meta new file mode 100644 index 0000000..3828b9c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkClosedEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9d894e462cd9eae47850f1ebf70842a9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkConnectedEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkConnectedEventArgs.cs new file mode 100644 index 0000000..1329d87 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkConnectedEventArgs.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Network +{ + /// + /// 网络连接成功事件。 + /// + public sealed class NetworkConnectedEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化网络连接成功事件的新实例。 + /// + public NetworkConnectedEventArgs() + { + NetworkChannel = null; + UserData = null; + } + + /// + /// 获取网络频道。 + /// + public INetworkChannel NetworkChannel + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建网络连接成功事件。 + /// + /// 网络频道。 + /// 用户自定义数据。 + /// 创建的网络连接成功事件。 + public static NetworkConnectedEventArgs Create(INetworkChannel networkChannel, object userData) + { + NetworkConnectedEventArgs networkConnectedEventArgs = ReferencePool.Acquire(); + networkConnectedEventArgs.NetworkChannel = networkChannel; + networkConnectedEventArgs.UserData = userData; + return networkConnectedEventArgs; + } + + /// + /// 清理网络连接成功事件。 + /// + public override void Clear() + { + NetworkChannel = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkConnectedEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkConnectedEventArgs.cs.meta new file mode 100644 index 0000000..73e6a07 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkConnectedEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3a4a87c1fade1a441a9cff72c0349e3b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkCustomErrorEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkCustomErrorEventArgs.cs new file mode 100644 index 0000000..4883783 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkCustomErrorEventArgs.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Network +{ + /// + /// 用户自定义网络错误事件。 + /// + public sealed class NetworkCustomErrorEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化用户自定义网络错误事件的新实例。 + /// + public NetworkCustomErrorEventArgs() + { + NetworkChannel = null; + CustomErrorData = null; + } + + /// + /// 获取网络频道。 + /// + public INetworkChannel NetworkChannel + { + get; + private set; + } + + /// + /// 获取用户自定义错误数据。 + /// + public object CustomErrorData + { + get; + private set; + } + + /// + /// 创建用户自定义网络错误事件。 + /// + /// 网络频道。 + /// 用户自定义错误数据。 + /// 创建的用户自定义网络错误事件。 + public static NetworkCustomErrorEventArgs Create(INetworkChannel networkChannel, object customErrorData) + { + NetworkCustomErrorEventArgs networkCustomErrorEventArgs = ReferencePool.Acquire(); + networkCustomErrorEventArgs.NetworkChannel = networkChannel; + networkCustomErrorEventArgs.CustomErrorData = customErrorData; + return networkCustomErrorEventArgs; + } + + /// + /// 清理用户自定义网络错误事件。 + /// + public override void Clear() + { + NetworkChannel = null; + CustomErrorData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkCustomErrorEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkCustomErrorEventArgs.cs.meta new file mode 100644 index 0000000..41f124d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkCustomErrorEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7388271e006610648989d7bd7334888b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkErrorCode.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkErrorCode.cs new file mode 100644 index 0000000..3c7b0ba --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkErrorCode.cs @@ -0,0 +1,60 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Network +{ + /// + /// 网络错误码。 + /// + public enum NetworkErrorCode : byte + { + /// + /// 未知错误。 + /// + Unknown = 0, + + /// + /// 地址族错误。 + /// + AddressFamilyError, + + /// + /// Socket 错误。 + /// + SocketError, + + /// + /// 连接错误。 + /// + ConnectError, + + /// + /// 发送错误。 + /// + SendError, + + /// + /// 接收错误。 + /// + ReceiveError, + + /// + /// 序列化错误。 + /// + SerializeError, + + /// + /// 反序列化消息包头错误。 + /// + DeserializePacketHeaderError, + + /// + /// 反序列化消息包错误。 + /// + DeserializePacketError + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkErrorCode.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkErrorCode.cs.meta new file mode 100644 index 0000000..30e628b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkErrorCode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22aa127b860fbf843847ecd2e78c3b7b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkErrorEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkErrorEventArgs.cs new file mode 100644 index 0000000..9ffb2b6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkErrorEventArgs.cs @@ -0,0 +1,93 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Net.Sockets; + +namespace GameFramework.Network +{ + /// + /// 网络错误事件。 + /// + public sealed class NetworkErrorEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化网络错误事件的新实例。 + /// + public NetworkErrorEventArgs() + { + NetworkChannel = null; + ErrorCode = NetworkErrorCode.Unknown; + SocketErrorCode = SocketError.Success; + ErrorMessage = null; + } + + /// + /// 获取网络频道。 + /// + public INetworkChannel NetworkChannel + { + get; + private set; + } + + /// + /// 获取错误码。 + /// + public NetworkErrorCode ErrorCode + { + get; + private set; + } + + /// + /// 获取 Socket 错误码。 + /// + public SocketError SocketErrorCode + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 创建网络错误事件。 + /// + /// 网络频道。 + /// 错误码。 + /// Socket 错误码。 + /// 错误信息。 + /// 创建的网络错误事件。 + public static NetworkErrorEventArgs Create(INetworkChannel networkChannel, NetworkErrorCode errorCode, SocketError socketErrorCode, string errorMessage) + { + NetworkErrorEventArgs networkErrorEventArgs = ReferencePool.Acquire(); + networkErrorEventArgs.NetworkChannel = networkChannel; + networkErrorEventArgs.ErrorCode = errorCode; + networkErrorEventArgs.SocketErrorCode = socketErrorCode; + networkErrorEventArgs.ErrorMessage = errorMessage; + return networkErrorEventArgs; + } + + /// + /// 清理网络错误事件。 + /// + public override void Clear() + { + NetworkChannel = null; + ErrorCode = NetworkErrorCode.Unknown; + SocketErrorCode = SocketError.Success; + ErrorMessage = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkErrorEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkErrorEventArgs.cs.meta new file mode 100644 index 0000000..d6fffcb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkErrorEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1da767b6c52678744bf340fcabc74fb1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.ConnectState.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.ConnectState.cs new file mode 100644 index 0000000..3252f97 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.ConnectState.cs @@ -0,0 +1,42 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Net.Sockets; + +namespace GameFramework.Network +{ + internal sealed partial class NetworkManager : GameFrameworkModule, INetworkManager + { + private sealed class ConnectState + { + private readonly Socket m_Socket; + private readonly object m_UserData; + + public ConnectState(Socket socket, object userData) + { + m_Socket = socket; + m_UserData = userData; + } + + public Socket Socket + { + get + { + return m_Socket; + } + } + + public object UserData + { + get + { + return m_UserData; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.ConnectState.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.ConnectState.cs.meta new file mode 100644 index 0000000..6717be7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.ConnectState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d05dbcab6c1fb8544b73bdd23ba11f87 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.HeartBeatState.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.HeartBeatState.cs new file mode 100644 index 0000000..922cb4b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.HeartBeatState.cs @@ -0,0 +1,58 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Network +{ + internal sealed partial class NetworkManager : GameFrameworkModule, INetworkManager + { + private sealed class HeartBeatState + { + private float m_HeartBeatElapseSeconds; + private int m_MissHeartBeatCount; + + public HeartBeatState() + { + m_HeartBeatElapseSeconds = 0f; + m_MissHeartBeatCount = 0; + } + + public float HeartBeatElapseSeconds + { + get + { + return m_HeartBeatElapseSeconds; + } + set + { + m_HeartBeatElapseSeconds = value; + } + } + + public int MissHeartBeatCount + { + get + { + return m_MissHeartBeatCount; + } + set + { + m_MissHeartBeatCount = value; + } + } + + public void Reset(bool resetHeartBeatElapseSeconds) + { + if (resetHeartBeatElapseSeconds) + { + m_HeartBeatElapseSeconds = 0f; + } + + m_MissHeartBeatCount = 0; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.HeartBeatState.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.HeartBeatState.cs.meta new file mode 100644 index 0000000..5494e20 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.HeartBeatState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7a09e9bbabba8f04d9499ec8e6d12a65 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.NetworkChannelBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.NetworkChannelBase.cs new file mode 100644 index 0000000..58cd1c0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.NetworkChannelBase.cs @@ -0,0 +1,636 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; + +namespace GameFramework.Network +{ + internal sealed partial class NetworkManager : GameFrameworkModule, INetworkManager + { + /// + /// 网络频道基类。 + /// + private abstract class NetworkChannelBase : INetworkChannel, IDisposable + { + private const float DefaultHeartBeatInterval = 30f; + + private readonly string m_Name; + protected readonly Queue m_SendPacketPool; + protected readonly EventPool m_ReceivePacketPool; + protected readonly INetworkChannelHelper m_NetworkChannelHelper; + protected AddressFamily m_AddressFamily; + protected bool m_ResetHeartBeatElapseSecondsWhenReceivePacket; + protected float m_HeartBeatInterval; + protected Socket m_Socket; + protected readonly SendState m_SendState; + protected readonly ReceiveState m_ReceiveState; + protected readonly HeartBeatState m_HeartBeatState; + protected int m_SentPacketCount; + protected int m_ReceivedPacketCount; + protected bool m_Active; + private bool m_Disposed; + + public GameFrameworkAction NetworkChannelConnected; + public GameFrameworkAction NetworkChannelClosed; + public GameFrameworkAction NetworkChannelMissHeartBeat; + public GameFrameworkAction NetworkChannelError; + public GameFrameworkAction NetworkChannelCustomError; + + /// + /// 初始化网络频道基类的新实例。 + /// + /// 网络频道名称。 + /// 网络频道辅助器。 + public NetworkChannelBase(string name, INetworkChannelHelper networkChannelHelper) + { + m_Name = name ?? string.Empty; + m_SendPacketPool = new Queue(); + m_ReceivePacketPool = new EventPool(EventPoolMode.Default); + m_NetworkChannelHelper = networkChannelHelper; + m_AddressFamily = AddressFamily.Unknown; + m_ResetHeartBeatElapseSecondsWhenReceivePacket = false; + m_HeartBeatInterval = DefaultHeartBeatInterval; + m_Socket = null; + m_SendState = new SendState(); + m_ReceiveState = new ReceiveState(); + m_HeartBeatState = new HeartBeatState(); + m_SentPacketCount = 0; + m_ReceivedPacketCount = 0; + m_Active = false; + m_Disposed = false; + + NetworkChannelConnected = null; + NetworkChannelClosed = null; + NetworkChannelMissHeartBeat = null; + NetworkChannelError = null; + NetworkChannelCustomError = null; + + networkChannelHelper.Initialize(this); + } + + /// + /// 获取网络频道名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取网络频道所使用的 Socket。 + /// + public Socket Socket + { + get + { + return m_Socket; + } + } + + /// + /// 获取是否已连接。 + /// + public bool Connected + { + get + { + if (m_Socket != null) + { + return m_Socket.Connected; + } + + return false; + } + } + + /// + /// 获取网络服务类型。 + /// + public abstract ServiceType ServiceType + { + get; + } + + /// + /// 获取网络地址类型。 + /// + public AddressFamily AddressFamily + { + get + { + return m_AddressFamily; + } + } + + /// + /// 获取要发送的消息包数量。 + /// + public int SendPacketCount + { + get + { + return m_SendPacketPool.Count; + } + } + + /// + /// 获取累计发送的消息包数量。 + /// + public int SentPacketCount + { + get + { + return m_SentPacketCount; + } + } + + /// + /// 获取已接收未处理的消息包数量。 + /// + public int ReceivePacketCount + { + get + { + return m_ReceivePacketPool.EventCount; + } + } + + /// + /// 获取累计已接收的消息包数量。 + /// + public int ReceivedPacketCount + { + get + { + return m_ReceivedPacketCount; + } + } + + /// + /// 获取或设置当收到消息包时是否重置心跳流逝时间。 + /// + public bool ResetHeartBeatElapseSecondsWhenReceivePacket + { + get + { + return m_ResetHeartBeatElapseSecondsWhenReceivePacket; + } + set + { + m_ResetHeartBeatElapseSecondsWhenReceivePacket = value; + } + } + + /// + /// 获取丢失心跳的次数。 + /// + public int MissHeartBeatCount + { + get + { + return m_HeartBeatState.MissHeartBeatCount; + } + } + + /// + /// 获取或设置心跳间隔时长,以秒为单位。 + /// + public float HeartBeatInterval + { + get + { + return m_HeartBeatInterval; + } + set + { + m_HeartBeatInterval = value; + } + } + + /// + /// 获取心跳等待时长,以秒为单位。 + /// + public float HeartBeatElapseSeconds + { + get + { + return m_HeartBeatState.HeartBeatElapseSeconds; + } + } + + /// + /// 网络频道轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public virtual void Update(float elapseSeconds, float realElapseSeconds) + { + if (m_Socket == null || !m_Active) + { + return; + } + + ProcessSend(); + ProcessReceive(); + if (m_Socket == null || !m_Active) + { + return; + } + + m_ReceivePacketPool.Update(elapseSeconds, realElapseSeconds); + + if (m_HeartBeatInterval > 0f) + { + bool sendHeartBeat = false; + int missHeartBeatCount = 0; + lock (m_HeartBeatState) + { + if (m_Socket == null || !m_Active) + { + return; + } + + m_HeartBeatState.HeartBeatElapseSeconds += realElapseSeconds; + if (m_HeartBeatState.HeartBeatElapseSeconds >= m_HeartBeatInterval) + { + sendHeartBeat = true; + missHeartBeatCount = m_HeartBeatState.MissHeartBeatCount; + m_HeartBeatState.HeartBeatElapseSeconds = 0f; + m_HeartBeatState.MissHeartBeatCount++; + } + } + + if (sendHeartBeat && m_NetworkChannelHelper.SendHeartBeat()) + { + if (missHeartBeatCount > 0 && NetworkChannelMissHeartBeat != null) + { + NetworkChannelMissHeartBeat(this, missHeartBeatCount); + } + } + } + } + + /// + /// 关闭网络频道。 + /// + public virtual void Shutdown() + { + Close(); + m_ReceivePacketPool.Shutdown(); + m_NetworkChannelHelper.Shutdown(); + } + + /// + /// 注册网络消息包处理函数。 + /// + /// 要注册的网络消息包处理函数。 + public void RegisterHandler(IPacketHandler handler) + { + if (handler == null) + { + throw new GameFrameworkException("Packet handler is invalid."); + } + + m_ReceivePacketPool.Subscribe(handler.Id, handler.Handle); + } + + /// + /// 设置默认事件处理函数。 + /// + /// 要设置的默认事件处理函数。 + public void SetDefaultHandler(EventHandler handler) + { + m_ReceivePacketPool.SetDefaultHandler(handler); + } + + /// + /// 连接到远程主机。 + /// + /// 远程主机的 IP 地址。 + /// 远程主机的端口号。 + public void Connect(IPAddress ipAddress, int port) + { + Connect(ipAddress, port, null); + } + + /// + /// 连接到远程主机。 + /// + /// 远程主机的 IP 地址。 + /// 远程主机的端口号。 + /// 用户自定义数据。 + public virtual void Connect(IPAddress ipAddress, int port, object userData) + { + if (m_Socket != null) + { + Close(); + m_Socket = null; + } + + switch (ipAddress.AddressFamily) + { + case System.Net.Sockets.AddressFamily.InterNetwork: + m_AddressFamily = AddressFamily.IPv4; + break; + + case System.Net.Sockets.AddressFamily.InterNetworkV6: + m_AddressFamily = AddressFamily.IPv6; + break; + + default: + string errorMessage = Utility.Text.Format("Not supported address family '{0}'.", ipAddress.AddressFamily); + if (NetworkChannelError != null) + { + NetworkChannelError(this, NetworkErrorCode.AddressFamilyError, SocketError.Success, errorMessage); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + m_SendState.Reset(); + m_ReceiveState.PrepareForPacketHeader(m_NetworkChannelHelper.PacketHeaderLength); + } + + /// + /// 关闭连接并释放所有相关资源。 + /// + public void Close() + { + lock (this) + { + if (m_Socket == null) + { + return; + } + + m_Active = false; + + try + { + m_Socket.Shutdown(SocketShutdown.Both); + } + catch + { + } + finally + { + m_Socket.Close(); + m_Socket = null; + + if (NetworkChannelClosed != null) + { + NetworkChannelClosed(this); + } + } + + m_SentPacketCount = 0; + m_ReceivedPacketCount = 0; + + lock (m_SendPacketPool) + { + m_SendPacketPool.Clear(); + } + + m_ReceivePacketPool.Clear(); + + lock (m_HeartBeatState) + { + m_HeartBeatState.Reset(true); + } + } + } + + /// + /// 向远程主机发送消息包。 + /// + /// 消息包类型。 + /// 要发送的消息包。 + public void Send(T packet) where T : Packet + { + if (m_Socket == null) + { + string errorMessage = "You must connect first."; + if (NetworkChannelError != null) + { + NetworkChannelError(this, NetworkErrorCode.SendError, SocketError.Success, errorMessage); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + if (!m_Active) + { + string errorMessage = "Socket is not active."; + if (NetworkChannelError != null) + { + NetworkChannelError(this, NetworkErrorCode.SendError, SocketError.Success, errorMessage); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + if (packet == null) + { + string errorMessage = "Packet is invalid."; + if (NetworkChannelError != null) + { + NetworkChannelError(this, NetworkErrorCode.SendError, SocketError.Success, errorMessage); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + lock (m_SendPacketPool) + { + m_SendPacketPool.Enqueue(packet); + } + } + + /// + /// 释放资源。 + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// 释放资源。 + /// + /// 释放资源标记。 + private void Dispose(bool disposing) + { + if (m_Disposed) + { + return; + } + + if (disposing) + { + Close(); + m_SendState.Dispose(); + m_ReceiveState.Dispose(); + } + + m_Disposed = true; + } + + protected virtual bool ProcessSend() + { + if (m_SendState.Stream.Length > 0 || m_SendPacketPool.Count <= 0) + { + return false; + } + + while (m_SendPacketPool.Count > 0) + { + Packet packet = null; + lock (m_SendPacketPool) + { + packet = m_SendPacketPool.Dequeue(); + } + + bool serializeResult = false; + try + { + serializeResult = m_NetworkChannelHelper.Serialize(packet, m_SendState.Stream); + } + catch (Exception exception) + { + m_Active = false; + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.SerializeError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return false; + } + + throw; + } + + if (!serializeResult) + { + string errorMessage = "Serialized packet failure."; + if (NetworkChannelError != null) + { + NetworkChannelError(this, NetworkErrorCode.SerializeError, SocketError.Success, errorMessage); + return false; + } + + throw new GameFrameworkException(errorMessage); + } + } + + m_SendState.Stream.Position = 0L; + return true; + } + + protected virtual void ProcessReceive() + { + } + + protected virtual bool ProcessPacketHeader() + { + try + { + object customErrorData = null; + IPacketHeader packetHeader = m_NetworkChannelHelper.DeserializePacketHeader(m_ReceiveState.Stream, out customErrorData); + + if (customErrorData != null && NetworkChannelCustomError != null) + { + NetworkChannelCustomError(this, customErrorData); + } + + if (packetHeader == null) + { + string errorMessage = "Packet header is invalid."; + if (NetworkChannelError != null) + { + NetworkChannelError(this, NetworkErrorCode.DeserializePacketHeaderError, SocketError.Success, errorMessage); + return false; + } + + throw new GameFrameworkException(errorMessage); + } + + m_ReceiveState.PrepareForPacket(packetHeader); + if (packetHeader.PacketLength <= 0) + { + bool processSuccess = ProcessPacket(); + m_ReceivedPacketCount++; + return processSuccess; + } + } + catch (Exception exception) + { + m_Active = false; + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.DeserializePacketHeaderError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return false; + } + + throw; + } + + return true; + } + + protected virtual bool ProcessPacket() + { + lock (m_HeartBeatState) + { + m_HeartBeatState.Reset(m_ResetHeartBeatElapseSecondsWhenReceivePacket); + } + + try + { + object customErrorData = null; + Packet packet = m_NetworkChannelHelper.DeserializePacket(m_ReceiveState.PacketHeader, m_ReceiveState.Stream, out customErrorData); + + if (customErrorData != null && NetworkChannelCustomError != null) + { + NetworkChannelCustomError(this, customErrorData); + } + + if (packet != null) + { + m_ReceivePacketPool.Fire(this, packet); + } + + m_ReceiveState.PrepareForPacketHeader(m_NetworkChannelHelper.PacketHeaderLength); + } + catch (Exception exception) + { + m_Active = false; + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.DeserializePacketError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return false; + } + + throw; + } + + return true; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.NetworkChannelBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.NetworkChannelBase.cs.meta new file mode 100644 index 0000000..ab0f778 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.NetworkChannelBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 376ac86dbb44e5e4e9da8427a7326a75 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.ReceiveState.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.ReceiveState.cs new file mode 100644 index 0000000..231299d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.ReceiveState.cs @@ -0,0 +1,98 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.IO; + +namespace GameFramework.Network +{ + internal sealed partial class NetworkManager : GameFrameworkModule, INetworkManager + { + private sealed class ReceiveState : IDisposable + { + private const int DefaultBufferLength = 1024 * 64; + private MemoryStream m_Stream; + private IPacketHeader m_PacketHeader; + private bool m_Disposed; + + public ReceiveState() + { + m_Stream = new MemoryStream(DefaultBufferLength); + m_PacketHeader = null; + m_Disposed = false; + } + + public MemoryStream Stream + { + get + { + return m_Stream; + } + } + + public IPacketHeader PacketHeader + { + get + { + return m_PacketHeader; + } + } + + public void PrepareForPacketHeader(int packetHeaderLength) + { + Reset(packetHeaderLength, null); + } + + public void PrepareForPacket(IPacketHeader packetHeader) + { + if (packetHeader == null) + { + throw new GameFrameworkException("Packet header is invalid."); + } + + Reset(packetHeader.PacketLength, packetHeader); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (m_Disposed) + { + return; + } + + if (disposing) + { + if (m_Stream != null) + { + m_Stream.Dispose(); + m_Stream = null; + } + } + + m_Disposed = true; + } + + private void Reset(int targetLength, IPacketHeader packetHeader) + { + if (targetLength < 0) + { + throw new GameFrameworkException("Target length is invalid."); + } + + m_Stream.Position = 0L; + m_Stream.SetLength(targetLength); + m_PacketHeader = packetHeader; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.ReceiveState.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.ReceiveState.cs.meta new file mode 100644 index 0000000..60bf2ec --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.ReceiveState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 14ef71f81fbf8474d88e8c15e157a478 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.SendState.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.SendState.cs new file mode 100644 index 0000000..05f84ed --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.SendState.cs @@ -0,0 +1,67 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.IO; + +namespace GameFramework.Network +{ + internal sealed partial class NetworkManager : GameFrameworkModule, INetworkManager + { + private sealed class SendState : IDisposable + { + private const int DefaultBufferLength = 1024 * 64; + private MemoryStream m_Stream; + private bool m_Disposed; + + public SendState() + { + m_Stream = new MemoryStream(DefaultBufferLength); + m_Disposed = false; + } + + public MemoryStream Stream + { + get + { + return m_Stream; + } + } + + public void Reset() + { + m_Stream.Position = 0L; + m_Stream.SetLength(0L); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (m_Disposed) + { + return; + } + + if (disposing) + { + if (m_Stream != null) + { + m_Stream.Dispose(); + m_Stream = null; + } + } + + m_Disposed = true; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.SendState.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.SendState.cs.meta new file mode 100644 index 0000000..15a8bc2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.SendState.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1f6aa63097e24ec4ea4bb256a3174562 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.TcpNetworkChannel.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.TcpNetworkChannel.cs new file mode 100644 index 0000000..65d6f06 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.TcpNetworkChannel.cs @@ -0,0 +1,290 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Net; +using System.Net.Sockets; + +namespace GameFramework.Network +{ + internal sealed partial class NetworkManager : GameFrameworkModule, INetworkManager + { + /// + /// TCP 网络频道。 + /// + private sealed class TcpNetworkChannel : NetworkChannelBase + { + private readonly AsyncCallback m_ConnectCallback; + private readonly AsyncCallback m_SendCallback; + private readonly AsyncCallback m_ReceiveCallback; + + /// + /// 初始化网络频道的新实例。 + /// + /// 网络频道名称。 + /// 网络频道辅助器。 + public TcpNetworkChannel(string name, INetworkChannelHelper networkChannelHelper) + : base(name, networkChannelHelper) + { + m_ConnectCallback = ConnectCallback; + m_SendCallback = SendCallback; + m_ReceiveCallback = ReceiveCallback; + } + + /// + /// 获取网络服务类型。 + /// + public override ServiceType ServiceType + { + get + { + return ServiceType.Tcp; + } + } + + /// + /// 连接到远程主机。 + /// + /// 远程主机的 IP 地址。 + /// 远程主机的端口号。 + /// 用户自定义数据。 + public override void Connect(IPAddress ipAddress, int port, object userData) + { + base.Connect(ipAddress, port, userData); + m_Socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + if (m_Socket == null) + { + string errorMessage = "Initialize network channel failure."; + if (NetworkChannelError != null) + { + NetworkChannelError(this, NetworkErrorCode.SocketError, SocketError.Success, errorMessage); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + m_NetworkChannelHelper.PrepareForConnecting(); + ConnectAsync(ipAddress, port, userData); + } + + protected override bool ProcessSend() + { + if (base.ProcessSend()) + { + SendAsync(); + return true; + } + + return false; + } + + private void ConnectAsync(IPAddress ipAddress, int port, object userData) + { + try + { + m_Socket.BeginConnect(ipAddress, port, m_ConnectCallback, new ConnectState(m_Socket, userData)); + } + catch (Exception exception) + { + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.ConnectError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return; + } + + throw; + } + } + + private void ConnectCallback(IAsyncResult ar) + { + ConnectState socketUserData = (ConnectState)ar.AsyncState; + try + { + socketUserData.Socket.EndConnect(ar); + } + catch (ObjectDisposedException) + { + return; + } + catch (Exception exception) + { + m_Active = false; + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.ConnectError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return; + } + + throw; + } + + m_SentPacketCount = 0; + m_ReceivedPacketCount = 0; + + lock (m_SendPacketPool) + { + m_SendPacketPool.Clear(); + } + + m_ReceivePacketPool.Clear(); + + lock (m_HeartBeatState) + { + m_HeartBeatState.Reset(true); + } + + if (NetworkChannelConnected != null) + { + NetworkChannelConnected(this, socketUserData.UserData); + } + + m_Active = true; + ReceiveAsync(); + } + + private void SendAsync() + { + try + { + m_Socket.BeginSend(m_SendState.Stream.GetBuffer(), (int)m_SendState.Stream.Position, (int)(m_SendState.Stream.Length - m_SendState.Stream.Position), SocketFlags.None, m_SendCallback, m_Socket); + } + catch (Exception exception) + { + m_Active = false; + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.SendError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return; + } + + throw; + } + } + + private void SendCallback(IAsyncResult ar) + { + Socket socket = (Socket)ar.AsyncState; + if (!socket.Connected) + { + return; + } + + int bytesSent = 0; + try + { + bytesSent = socket.EndSend(ar); + } + catch (Exception exception) + { + m_Active = false; + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.SendError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return; + } + + throw; + } + + m_SendState.Stream.Position += bytesSent; + if (m_SendState.Stream.Position < m_SendState.Stream.Length) + { + SendAsync(); + return; + } + + m_SentPacketCount++; + m_SendState.Reset(); + } + + private void ReceiveAsync() + { + try + { + m_Socket.BeginReceive(m_ReceiveState.Stream.GetBuffer(), (int)m_ReceiveState.Stream.Position, (int)(m_ReceiveState.Stream.Length - m_ReceiveState.Stream.Position), SocketFlags.None, m_ReceiveCallback, m_Socket); + } + catch (Exception exception) + { + m_Active = false; + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.ReceiveError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return; + } + + throw; + } + } + + private void ReceiveCallback(IAsyncResult ar) + { + Socket socket = (Socket)ar.AsyncState; + if (!socket.Connected) + { + return; + } + + int bytesReceived = 0; + try + { + bytesReceived = socket.EndReceive(ar); + } + catch (Exception exception) + { + m_Active = false; + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.ReceiveError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return; + } + + throw; + } + + if (bytesReceived <= 0) + { + Close(); + return; + } + + m_ReceiveState.Stream.Position += bytesReceived; + if (m_ReceiveState.Stream.Position < m_ReceiveState.Stream.Length) + { + ReceiveAsync(); + return; + } + + m_ReceiveState.Stream.Position = 0L; + + bool processSuccess = false; + if (m_ReceiveState.PacketHeader != null) + { + processSuccess = ProcessPacket(); + m_ReceivedPacketCount++; + } + else + { + processSuccess = ProcessPacketHeader(); + } + + if (processSuccess) + { + ReceiveAsync(); + return; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.TcpNetworkChannel.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.TcpNetworkChannel.cs.meta new file mode 100644 index 0000000..5ede615 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.TcpNetworkChannel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c3cb93e6d4e800748b05863cfb195203 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.TcpWithSyncReceiveNetworkChannel.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.TcpWithSyncReceiveNetworkChannel.cs new file mode 100644 index 0000000..6afe5ca --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.TcpWithSyncReceiveNetworkChannel.cs @@ -0,0 +1,266 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Net; +using System.Net.Sockets; + +namespace GameFramework.Network +{ + internal sealed partial class NetworkManager : GameFrameworkModule, INetworkManager + { + /// + /// 使用同步接收的 TCP 网络频道。 + /// + private sealed class TcpWithSyncReceiveNetworkChannel : NetworkChannelBase + { + private readonly AsyncCallback m_ConnectCallback; + private readonly AsyncCallback m_SendCallback; + + /// + /// 初始化网络频道的新实例。 + /// + /// 网络频道名称。 + /// 网络频道辅助器。 + public TcpWithSyncReceiveNetworkChannel(string name, INetworkChannelHelper networkChannelHelper) + : base(name, networkChannelHelper) + { + m_ConnectCallback = ConnectCallback; + m_SendCallback = SendCallback; + } + + /// + /// 获取网络服务类型。 + /// + public override ServiceType ServiceType + { + get + { + return ServiceType.TcpWithSyncReceive; + } + } + + /// + /// 连接到远程主机。 + /// + /// 远程主机的 IP 地址。 + /// 远程主机的端口号。 + /// 用户自定义数据。 + public override void Connect(IPAddress ipAddress, int port, object userData) + { + base.Connect(ipAddress, port, userData); + m_Socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + if (m_Socket == null) + { + string errorMessage = "Initialize network channel failure."; + if (NetworkChannelError != null) + { + NetworkChannelError(this, NetworkErrorCode.SocketError, SocketError.Success, errorMessage); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + m_NetworkChannelHelper.PrepareForConnecting(); + ConnectAsync(ipAddress, port, userData); + } + + protected override bool ProcessSend() + { + if (base.ProcessSend()) + { + SendAsync(); + return true; + } + + return false; + } + + protected override void ProcessReceive() + { + base.ProcessReceive(); + while (m_Socket.Available > 0) + { + if (!ReceiveSync()) + { + break; + } + } + } + + private void ConnectAsync(IPAddress ipAddress, int port, object userData) + { + try + { + m_Socket.BeginConnect(ipAddress, port, m_ConnectCallback, new ConnectState(m_Socket, userData)); + } + catch (Exception exception) + { + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.ConnectError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return; + } + + throw; + } + } + + private void ConnectCallback(IAsyncResult ar) + { + ConnectState socketUserData = (ConnectState)ar.AsyncState; + try + { + socketUserData.Socket.EndConnect(ar); + } + catch (ObjectDisposedException) + { + return; + } + catch (Exception exception) + { + m_Active = false; + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.ConnectError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return; + } + + throw; + } + + m_SentPacketCount = 0; + m_ReceivedPacketCount = 0; + + lock (m_SendPacketPool) + { + m_SendPacketPool.Clear(); + } + + m_ReceivePacketPool.Clear(); + + lock (m_HeartBeatState) + { + m_HeartBeatState.Reset(true); + } + + if (NetworkChannelConnected != null) + { + NetworkChannelConnected(this, socketUserData.UserData); + } + + m_Active = true; + } + + private void SendAsync() + { + try + { + m_Socket.BeginSend(m_SendState.Stream.GetBuffer(), (int)m_SendState.Stream.Position, (int)(m_SendState.Stream.Length - m_SendState.Stream.Position), SocketFlags.None, m_SendCallback, m_Socket); + } + catch (Exception exception) + { + m_Active = false; + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.SendError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return; + } + + throw; + } + } + + private void SendCallback(IAsyncResult ar) + { + Socket socket = (Socket)ar.AsyncState; + if (!socket.Connected) + { + return; + } + + int bytesSent = 0; + try + { + bytesSent = socket.EndSend(ar); + } + catch (Exception exception) + { + m_Active = false; + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.SendError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return; + } + + throw; + } + + m_SendState.Stream.Position += bytesSent; + if (m_SendState.Stream.Position < m_SendState.Stream.Length) + { + SendAsync(); + return; + } + + m_SentPacketCount++; + m_SendState.Reset(); + } + + private bool ReceiveSync() + { + try + { + int bytesReceived = m_Socket.Receive(m_ReceiveState.Stream.GetBuffer(), (int)m_ReceiveState.Stream.Position, (int)(m_ReceiveState.Stream.Length - m_ReceiveState.Stream.Position), SocketFlags.None); + if (bytesReceived <= 0) + { + Close(); + return false; + } + + m_ReceiveState.Stream.Position += bytesReceived; + if (m_ReceiveState.Stream.Position < m_ReceiveState.Stream.Length) + { + return false; + } + + m_ReceiveState.Stream.Position = 0L; + + bool processSuccess = false; + if (m_ReceiveState.PacketHeader != null) + { + processSuccess = ProcessPacket(); + m_ReceivedPacketCount++; + } + else + { + processSuccess = ProcessPacketHeader(); + } + + return processSuccess; + } + catch (Exception exception) + { + m_Active = false; + if (NetworkChannelError != null) + { + SocketException socketException = exception as SocketException; + NetworkChannelError(this, NetworkErrorCode.ReceiveError, socketException != null ? socketException.SocketErrorCode : SocketError.Success, exception.ToString()); + return false; + } + + throw; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.TcpWithSyncReceiveNetworkChannel.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.TcpWithSyncReceiveNetworkChannel.cs.meta new file mode 100644 index 0000000..0f2e3a2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.TcpWithSyncReceiveNetworkChannel.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d44da6da8c3fe4f4c90e27436059e3fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.cs new file mode 100644 index 0000000..5ad7562 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.cs @@ -0,0 +1,353 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.Net.Sockets; + +namespace GameFramework.Network +{ + /// + /// 网络管理器。 + /// + internal sealed partial class NetworkManager : GameFrameworkModule, INetworkManager + { + private readonly Dictionary m_NetworkChannels; + + private EventHandler m_NetworkConnectedEventHandler; + private EventHandler m_NetworkClosedEventHandler; + private EventHandler m_NetworkMissHeartBeatEventHandler; + private EventHandler m_NetworkErrorEventHandler; + private EventHandler m_NetworkCustomErrorEventHandler; + + /// + /// 初始化网络管理器的新实例。 + /// + public NetworkManager() + { + m_NetworkChannels = new Dictionary(StringComparer.Ordinal); + m_NetworkConnectedEventHandler = null; + m_NetworkClosedEventHandler = null; + m_NetworkMissHeartBeatEventHandler = null; + m_NetworkErrorEventHandler = null; + m_NetworkCustomErrorEventHandler = null; + } + + /// + /// 获取网络频道数量。 + /// + public int NetworkChannelCount + { + get + { + return m_NetworkChannels.Count; + } + } + + /// + /// 网络连接成功事件。 + /// + public event EventHandler NetworkConnected + { + add + { + m_NetworkConnectedEventHandler += value; + } + remove + { + m_NetworkConnectedEventHandler -= value; + } + } + + /// + /// 网络连接关闭事件。 + /// + public event EventHandler NetworkClosed + { + add + { + m_NetworkClosedEventHandler += value; + } + remove + { + m_NetworkClosedEventHandler -= value; + } + } + + /// + /// 网络心跳包丢失事件。 + /// + public event EventHandler NetworkMissHeartBeat + { + add + { + m_NetworkMissHeartBeatEventHandler += value; + } + remove + { + m_NetworkMissHeartBeatEventHandler -= value; + } + } + + /// + /// 网络错误事件。 + /// + public event EventHandler NetworkError + { + add + { + m_NetworkErrorEventHandler += value; + } + remove + { + m_NetworkErrorEventHandler -= value; + } + } + + /// + /// 用户自定义网络错误事件。 + /// + public event EventHandler NetworkCustomError + { + add + { + m_NetworkCustomErrorEventHandler += value; + } + remove + { + m_NetworkCustomErrorEventHandler -= value; + } + } + + /// + /// 网络管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + foreach (KeyValuePair networkChannel in m_NetworkChannels) + { + networkChannel.Value.Update(elapseSeconds, realElapseSeconds); + } + } + + /// + /// 关闭并清理网络管理器。 + /// + internal override void Shutdown() + { + foreach (KeyValuePair networkChannel in m_NetworkChannels) + { + NetworkChannelBase networkChannelBase = networkChannel.Value; + networkChannelBase.NetworkChannelConnected -= OnNetworkChannelConnected; + networkChannelBase.NetworkChannelClosed -= OnNetworkChannelClosed; + networkChannelBase.NetworkChannelMissHeartBeat -= OnNetworkChannelMissHeartBeat; + networkChannelBase.NetworkChannelError -= OnNetworkChannelError; + networkChannelBase.NetworkChannelCustomError -= OnNetworkChannelCustomError; + networkChannelBase.Shutdown(); + } + + m_NetworkChannels.Clear(); + } + + /// + /// 检查是否存在网络频道。 + /// + /// 网络频道名称。 + /// 是否存在网络频道。 + public bool HasNetworkChannel(string name) + { + return m_NetworkChannels.ContainsKey(name ?? string.Empty); + } + + /// + /// 获取网络频道。 + /// + /// 网络频道名称。 + /// 要获取的网络频道。 + public INetworkChannel GetNetworkChannel(string name) + { + NetworkChannelBase networkChannel = null; + if (m_NetworkChannels.TryGetValue(name ?? string.Empty, out networkChannel)) + { + return networkChannel; + } + + return null; + } + + /// + /// 获取所有网络频道。 + /// + /// 所有网络频道。 + public INetworkChannel[] GetAllNetworkChannels() + { + int index = 0; + INetworkChannel[] results = new INetworkChannel[m_NetworkChannels.Count]; + foreach (KeyValuePair networkChannel in m_NetworkChannels) + { + results[index++] = networkChannel.Value; + } + + return results; + } + + /// + /// 获取所有网络频道。 + /// + /// 所有网络频道。 + public void GetAllNetworkChannels(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair networkChannel in m_NetworkChannels) + { + results.Add(networkChannel.Value); + } + } + + /// + /// 创建网络频道。 + /// + /// 网络频道名称。 + /// 网络服务类型。 + /// 网络频道辅助器。 + /// 要创建的网络频道。 + public INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType, INetworkChannelHelper networkChannelHelper) + { + if (networkChannelHelper == null) + { + throw new GameFrameworkException("Network channel helper is invalid."); + } + + if (networkChannelHelper.PacketHeaderLength < 0) + { + throw new GameFrameworkException("Packet header length is invalid."); + } + + if (HasNetworkChannel(name)) + { + throw new GameFrameworkException(Utility.Text.Format("Already exist network channel '{0}'.", name ?? string.Empty)); + } + + NetworkChannelBase networkChannel = null; + switch (serviceType) + { + case ServiceType.Tcp: + networkChannel = new TcpNetworkChannel(name, networkChannelHelper); + break; + + case ServiceType.TcpWithSyncReceive: + networkChannel = new TcpWithSyncReceiveNetworkChannel(name, networkChannelHelper); + break; + + default: + throw new GameFrameworkException(Utility.Text.Format("Not supported service type '{0}'.", serviceType)); + } + + networkChannel.NetworkChannelConnected += OnNetworkChannelConnected; + networkChannel.NetworkChannelClosed += OnNetworkChannelClosed; + networkChannel.NetworkChannelMissHeartBeat += OnNetworkChannelMissHeartBeat; + networkChannel.NetworkChannelError += OnNetworkChannelError; + networkChannel.NetworkChannelCustomError += OnNetworkChannelCustomError; + m_NetworkChannels.Add(name, networkChannel); + return networkChannel; + } + + /// + /// 销毁网络频道。 + /// + /// 网络频道名称。 + /// 是否销毁网络频道成功。 + public bool DestroyNetworkChannel(string name) + { + NetworkChannelBase networkChannel = null; + if (m_NetworkChannels.TryGetValue(name ?? string.Empty, out networkChannel)) + { + networkChannel.NetworkChannelConnected -= OnNetworkChannelConnected; + networkChannel.NetworkChannelClosed -= OnNetworkChannelClosed; + networkChannel.NetworkChannelMissHeartBeat -= OnNetworkChannelMissHeartBeat; + networkChannel.NetworkChannelError -= OnNetworkChannelError; + networkChannel.NetworkChannelCustomError -= OnNetworkChannelCustomError; + networkChannel.Shutdown(); + return m_NetworkChannels.Remove(name); + } + + return false; + } + + private void OnNetworkChannelConnected(NetworkChannelBase networkChannel, object userData) + { + if (m_NetworkConnectedEventHandler != null) + { + lock (m_NetworkConnectedEventHandler) + { + NetworkConnectedEventArgs networkConnectedEventArgs = NetworkConnectedEventArgs.Create(networkChannel, userData); + m_NetworkConnectedEventHandler(this, networkConnectedEventArgs); + ReferencePool.Release(networkConnectedEventArgs); + } + } + } + + private void OnNetworkChannelClosed(NetworkChannelBase networkChannel) + { + if (m_NetworkClosedEventHandler != null) + { + lock (m_NetworkClosedEventHandler) + { + NetworkClosedEventArgs networkClosedEventArgs = NetworkClosedEventArgs.Create(networkChannel); + m_NetworkClosedEventHandler(this, networkClosedEventArgs); + ReferencePool.Release(networkClosedEventArgs); + } + } + } + + private void OnNetworkChannelMissHeartBeat(NetworkChannelBase networkChannel, int missHeartBeatCount) + { + if (m_NetworkMissHeartBeatEventHandler != null) + { + lock (m_NetworkMissHeartBeatEventHandler) + { + NetworkMissHeartBeatEventArgs networkMissHeartBeatEventArgs = NetworkMissHeartBeatEventArgs.Create(networkChannel, missHeartBeatCount); + m_NetworkMissHeartBeatEventHandler(this, networkMissHeartBeatEventArgs); + ReferencePool.Release(networkMissHeartBeatEventArgs); + } + } + } + + private void OnNetworkChannelError(NetworkChannelBase networkChannel, NetworkErrorCode errorCode, SocketError socketErrorCode, string errorMessage) + { + if (m_NetworkErrorEventHandler != null) + { + lock (m_NetworkErrorEventHandler) + { + NetworkErrorEventArgs networkErrorEventArgs = NetworkErrorEventArgs.Create(networkChannel, errorCode, socketErrorCode, errorMessage); + m_NetworkErrorEventHandler(this, networkErrorEventArgs); + ReferencePool.Release(networkErrorEventArgs); + } + } + } + + private void OnNetworkChannelCustomError(NetworkChannelBase networkChannel, object customErrorData) + { + if (m_NetworkCustomErrorEventHandler != null) + { + lock (m_NetworkCustomErrorEventHandler) + { + NetworkCustomErrorEventArgs networkCustomErrorEventArgs = NetworkCustomErrorEventArgs.Create(networkChannel, customErrorData); + m_NetworkCustomErrorEventHandler(this, networkCustomErrorEventArgs); + ReferencePool.Release(networkCustomErrorEventArgs); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.cs.meta new file mode 100644 index 0000000..b8ee58e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 236059f35ec1d9e4db5b2b163e94a203 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkMissHeartBeatEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkMissHeartBeatEventArgs.cs new file mode 100644 index 0000000..1554709 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkMissHeartBeatEventArgs.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Network +{ + /// + /// 网络心跳包丢失事件。 + /// + public sealed class NetworkMissHeartBeatEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化网络心跳包丢失事件的新实例。 + /// + public NetworkMissHeartBeatEventArgs() + { + NetworkChannel = null; + MissCount = 0; + } + + /// + /// 获取网络频道。 + /// + public INetworkChannel NetworkChannel + { + get; + private set; + } + + /// + /// 获取心跳包已丢失次数。 + /// + public int MissCount + { + get; + private set; + } + + /// + /// 创建网络心跳包丢失事件。 + /// + /// 网络频道。 + /// 心跳包已丢失次数。 + /// 创建的网络心跳包丢失事件。 + public static NetworkMissHeartBeatEventArgs Create(INetworkChannel networkChannel, int missCount) + { + NetworkMissHeartBeatEventArgs networkMissHeartBeatEventArgs = ReferencePool.Acquire(); + networkMissHeartBeatEventArgs.NetworkChannel = networkChannel; + networkMissHeartBeatEventArgs.MissCount = missCount; + return networkMissHeartBeatEventArgs; + } + + /// + /// 清理网络心跳包丢失事件。 + /// + public override void Clear() + { + NetworkChannel = null; + MissCount = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkMissHeartBeatEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkMissHeartBeatEventArgs.cs.meta new file mode 100644 index 0000000..bc548f7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/NetworkMissHeartBeatEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2ddaae9937a6f8943abbc13dc6893472 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/Packet.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/Packet.cs new file mode 100644 index 0000000..bf3904e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/Packet.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Network +{ + /// + /// 网络消息包基类。 + /// + public abstract class Packet : BaseEventArgs + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/Packet.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/Packet.cs.meta new file mode 100644 index 0000000..e1e9f55 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/Packet.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eb5da4bb10dc80c4a9f9fb025ea3a1c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/ServiceType.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/ServiceType.cs new file mode 100644 index 0000000..691cb64 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/ServiceType.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Network +{ + /// + /// 网络服务类型。 + /// + public enum ServiceType : byte + { + /// + /// TCP 网络服务。 + /// + Tcp = 0, + + /// + /// 使用同步接收的 TCP 网络服务。 + /// + TcpWithSyncReceive + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/ServiceType.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/ServiceType.cs.meta new file mode 100644 index 0000000..f5411a8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Network/ServiceType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 589497222629cc3478a8126164285750 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool.meta new file mode 100644 index 0000000..a4c3fa2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fce8ee9a896d4e944b00c72652ce67e6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/IObjectPool.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/IObjectPool.cs new file mode 100644 index 0000000..b24da05 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/IObjectPool.cs @@ -0,0 +1,218 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.ObjectPool +{ + /// + /// 对象池接口。 + /// + /// 对象类型。 + public interface IObjectPool where T : ObjectBase + { + /// + /// 获取对象池名称。 + /// + string Name + { + get; + } + + /// + /// 获取对象池完整名称。 + /// + string FullName + { + get; + } + + /// + /// 获取对象池对象类型。 + /// + Type ObjectType + { + get; + } + + /// + /// 获取对象池中对象的数量。 + /// + int Count + { + get; + } + + /// + /// 获取对象池中能被释放的对象的数量。 + /// + int CanReleaseCount + { + get; + } + + /// + /// 获取是否允许对象被多次获取。 + /// + bool AllowMultiSpawn + { + get; + } + + /// + /// 获取或设置对象池自动释放可释放对象的间隔秒数。 + /// + float AutoReleaseInterval + { + get; + set; + } + + /// + /// 获取或设置对象池的容量。 + /// + int Capacity + { + get; + set; + } + + /// + /// 获取或设置对象池对象过期秒数。 + /// + float ExpireTime + { + get; + set; + } + + /// + /// 获取或设置对象池的优先级。 + /// + int Priority + { + get; + set; + } + + /// + /// 创建对象。 + /// + /// 对象。 + /// 对象是否已被获取。 + void Register(T obj, bool spawned); + + /// + /// 检查对象。 + /// + /// 要检查的对象是否存在。 + bool CanSpawn(); + + /// + /// 检查对象。 + /// + /// 对象名称。 + /// 要检查的对象是否存在。 + bool CanSpawn(string name); + + /// + /// 获取对象。 + /// + /// 要获取的对象。 + T Spawn(); + + /// + /// 获取对象。 + /// + /// 对象名称。 + /// 要获取的对象。 + T Spawn(string name); + + /// + /// 回收对象。 + /// + /// 要回收的对象。 + void Unspawn(T obj); + + /// + /// 回收对象。 + /// + /// 要回收的对象。 + void Unspawn(object target); + + /// + /// 设置对象是否被加锁。 + /// + /// 要设置被加锁的对象。 + /// 是否被加锁。 + void SetLocked(T obj, bool locked); + + /// + /// 设置对象是否被加锁。 + /// + /// 要设置被加锁的对象。 + /// 是否被加锁。 + void SetLocked(object target, bool locked); + + /// + /// 设置对象的优先级。 + /// + /// 要设置优先级的对象。 + /// 优先级。 + void SetPriority(T obj, int priority); + + /// + /// 设置对象的优先级。 + /// + /// 要设置优先级的对象。 + /// 优先级。 + void SetPriority(object target, int priority); + + /// + /// 释放对象。 + /// + /// 要释放的对象。 + /// 释放对象是否成功。 + bool ReleaseObject(T obj); + + /// + /// 释放对象。 + /// + /// 要释放的对象。 + /// 释放对象是否成功。 + bool ReleaseObject(object target); + + /// + /// 释放对象池中的可释放对象。 + /// + void Release(); + + /// + /// 释放对象池中的可释放对象。 + /// + /// 尝试释放对象数量。 + void Release(int toReleaseCount); + + /// + /// 释放对象池中的可释放对象。 + /// + /// 释放对象筛选函数。 + void Release(ReleaseObjectFilterCallback releaseObjectFilterCallback); + + /// + /// 释放对象池中的可释放对象。 + /// + /// 尝试释放对象数量。 + /// 释放对象筛选函数。 + void Release(int toReleaseCount, ReleaseObjectFilterCallback releaseObjectFilterCallback); + + /// + /// 释放对象池中的所有未使用对象。 + /// + void ReleaseAllUnused(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/IObjectPool.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/IObjectPool.cs.meta new file mode 100644 index 0000000..2c42f7a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/IObjectPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5d7f4534c9efc814bbebec8e658429f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/IObjectPoolManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/IObjectPoolManager.cs new file mode 100644 index 0000000..3b9477c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/IObjectPoolManager.cs @@ -0,0 +1,751 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.ObjectPool +{ + /// + /// 对象池管理器。 + /// + public interface IObjectPoolManager + { + /// + /// 获取对象池数量。 + /// + int Count + { + get; + } + + /// + /// 检查是否存在对象池。 + /// + /// 对象类型。 + /// 是否存在对象池。 + bool HasObjectPool() where T : ObjectBase; + + /// + /// 检查是否存在对象池。 + /// + /// 对象类型。 + /// 是否存在对象池。 + bool HasObjectPool(Type objectType); + + /// + /// 检查是否存在对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 是否存在对象池。 + bool HasObjectPool(string name) where T : ObjectBase; + + /// + /// 检查是否存在对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 是否存在对象池。 + bool HasObjectPool(Type objectType, string name); + + /// + /// 检查是否存在对象池。 + /// + /// 要检查的条件。 + /// 是否存在对象池。 + bool HasObjectPool(Predicate condition); + + /// + /// 获取对象池。 + /// + /// 对象类型。 + /// 要获取的对象池。 + IObjectPool GetObjectPool() where T : ObjectBase; + + /// + /// 获取对象池。 + /// + /// 对象类型。 + /// 要获取的对象池。 + ObjectPoolBase GetObjectPool(Type objectType); + + /// + /// 获取对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要获取的对象池。 + IObjectPool GetObjectPool(string name) where T : ObjectBase; + + /// + /// 获取对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要获取的对象池。 + ObjectPoolBase GetObjectPool(Type objectType, string name); + + /// + /// 获取对象池。 + /// + /// 要检查的条件。 + /// 要获取的对象池。 + ObjectPoolBase GetObjectPool(Predicate condition); + + /// + /// 获取对象池。 + /// + /// 要检查的条件。 + /// 要获取的对象池。 + ObjectPoolBase[] GetObjectPools(Predicate condition); + + /// + /// 获取对象池。 + /// + /// 要检查的条件。 + /// 要获取的对象池。 + void GetObjectPools(Predicate condition, List results); + + /// + /// 获取所有对象池。 + /// + /// 所有对象池。 + ObjectPoolBase[] GetAllObjectPools(); + + /// + /// 获取所有对象池。 + /// + /// 所有对象池。 + void GetAllObjectPools(List results); + + /// + /// 获取所有对象池。 + /// + /// 是否根据对象池的优先级排序。 + /// 所有对象池。 + ObjectPoolBase[] GetAllObjectPools(bool sort); + + /// + /// 获取所有对象池。 + /// + /// 是否根据对象池的优先级排序。 + /// 所有对象池。 + void GetAllObjectPools(bool sort, List results); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool() where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(string name) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(int capacity) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, int capacity); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(float expireTime) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, float expireTime); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(string name, int capacity) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, int capacity); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(string name, float expireTime) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, float expireTime); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(int capacity, float expireTime) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, int capacity, float expireTime); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(int capacity, int priority) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, int capacity, int priority); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(float expireTime, int priority) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, float expireTime, int priority); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(string name, int capacity, float expireTime) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, int capacity, float expireTime); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(string name, int capacity, int priority) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, int capacity, int priority); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(string name, float expireTime, int priority) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, float expireTime, int priority); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(int capacity, float expireTime, int priority) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, int capacity, float expireTime, int priority); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(string name, int capacity, float expireTime, int priority) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, int capacity, float expireTime, int priority); + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + IObjectPool CreateSingleSpawnObjectPool(string name, float autoReleaseInterval, int capacity, float expireTime, int priority) where T : ObjectBase; + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, float autoReleaseInterval, int capacity, float expireTime, int priority); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool() where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(string name) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(int capacity) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, int capacity); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(float expireTime) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, float expireTime); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(string name, int capacity) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, int capacity); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(string name, float expireTime) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, float expireTime); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(int capacity, float expireTime) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, int capacity, float expireTime); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(int capacity, int priority) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, int capacity, int priority); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(float expireTime, int priority) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, float expireTime, int priority); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(string name, int capacity, float expireTime) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, int capacity, float expireTime); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(string name, int capacity, int priority) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, int capacity, int priority); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(string name, float expireTime, int priority) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, float expireTime, int priority); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(int capacity, float expireTime, int priority) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, int capacity, float expireTime, int priority); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(string name, int capacity, float expireTime, int priority) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, int capacity, float expireTime, int priority); + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + IObjectPool CreateMultiSpawnObjectPool(string name, float autoReleaseInterval, int capacity, float expireTime, int priority) where T : ObjectBase; + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, float autoReleaseInterval, int capacity, float expireTime, int priority); + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 是否销毁对象池成功。 + bool DestroyObjectPool() where T : ObjectBase; + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 是否销毁对象池成功。 + bool DestroyObjectPool(Type objectType); + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 要销毁的对象池名称。 + /// 是否销毁对象池成功。 + bool DestroyObjectPool(string name) where T : ObjectBase; + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 要销毁的对象池名称。 + /// 是否销毁对象池成功。 + bool DestroyObjectPool(Type objectType, string name); + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 要销毁的对象池。 + /// 是否销毁对象池成功。 + bool DestroyObjectPool(IObjectPool objectPool) where T : ObjectBase; + + /// + /// 销毁对象池。 + /// + /// 要销毁的对象池。 + /// 是否销毁对象池成功。 + bool DestroyObjectPool(ObjectPoolBase objectPool); + + /// + /// 释放对象池中的可释放对象。 + /// + void Release(); + + /// + /// 释放对象池中的所有未使用对象。 + /// + void ReleaseAllUnused(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/IObjectPoolManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/IObjectPoolManager.cs.meta new file mode 100644 index 0000000..42691f2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/IObjectPoolManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef5c4eae53bb52e42a90d1c942b95714 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectBase.cs new file mode 100644 index 0000000..b7d3a78 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectBase.cs @@ -0,0 +1,207 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.ObjectPool +{ + /// + /// 对象基类。 + /// + public abstract class ObjectBase : IReference + { + private string m_Name; + private object m_Target; + private bool m_Locked; + private int m_Priority; + private DateTime m_LastUseTime; + + /// + /// 初始化对象基类的新实例。 + /// + public ObjectBase() + { + m_Name = null; + m_Target = null; + m_Locked = false; + m_Priority = 0; + m_LastUseTime = default(DateTime); + } + + /// + /// 获取对象名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取对象。 + /// + public object Target + { + get + { + return m_Target; + } + } + + /// + /// 获取或设置对象是否被加锁。 + /// + public bool Locked + { + get + { + return m_Locked; + } + set + { + m_Locked = value; + } + } + + /// + /// 获取或设置对象的优先级。 + /// + public int Priority + { + get + { + return m_Priority; + } + set + { + m_Priority = value; + } + } + + /// + /// 获取自定义释放检查标记。 + /// + public virtual bool CustomCanReleaseFlag + { + get + { + return true; + } + } + + /// + /// 获取对象上次使用时间。 + /// + public DateTime LastUseTime + { + get + { + return m_LastUseTime; + } + internal set + { + m_LastUseTime = value; + } + } + + /// + /// 初始化对象基类。 + /// + /// 对象。 + protected void Initialize(object target) + { + Initialize(null, target, false, 0); + } + + /// + /// 初始化对象基类。 + /// + /// 对象名称。 + /// 对象。 + protected void Initialize(string name, object target) + { + Initialize(name, target, false, 0); + } + + /// + /// 初始化对象基类。 + /// + /// 对象名称。 + /// 对象。 + /// 对象是否被加锁。 + protected void Initialize(string name, object target, bool locked) + { + Initialize(name, target, locked, 0); + } + + /// + /// 初始化对象基类。 + /// + /// 对象名称。 + /// 对象。 + /// 对象的优先级。 + protected void Initialize(string name, object target, int priority) + { + Initialize(name, target, false, priority); + } + + /// + /// 初始化对象基类。 + /// + /// 对象名称。 + /// 对象。 + /// 对象是否被加锁。 + /// 对象的优先级。 + protected void Initialize(string name, object target, bool locked, int priority) + { + if (target == null) + { + throw new GameFrameworkException(Utility.Text.Format("Target '{0}' is invalid.", name)); + } + + m_Name = name ?? string.Empty; + m_Target = target; + m_Locked = locked; + m_Priority = priority; + m_LastUseTime = DateTime.UtcNow; + } + + /// + /// 清理对象基类。 + /// + public virtual void Clear() + { + m_Name = null; + m_Target = null; + m_Locked = false; + m_Priority = 0; + m_LastUseTime = default(DateTime); + } + + /// + /// 获取对象时的事件。 + /// + protected internal virtual void OnSpawn() + { + } + + /// + /// 回收对象时的事件。 + /// + protected internal virtual void OnUnspawn() + { + } + + /// + /// 释放对象。 + /// + /// 是否是关闭对象池时触发。 + protected internal abstract void Release(bool isShutdown); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectBase.cs.meta new file mode 100644 index 0000000..01b6c8a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8ef716dcc078cbf4cbe1a2b3bf2fc584 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectInfo.cs new file mode 100644 index 0000000..e2105cf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectInfo.cs @@ -0,0 +1,122 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Runtime.InteropServices; + +namespace GameFramework.ObjectPool +{ + /// + /// 对象信息。 + /// + [StructLayout(LayoutKind.Auto)] + public struct ObjectInfo + { + private readonly string m_Name; + private readonly bool m_Locked; + private readonly bool m_CustomCanReleaseFlag; + private readonly int m_Priority; + private readonly DateTime m_LastUseTime; + private readonly int m_SpawnCount; + + /// + /// 初始化对象信息的新实例。 + /// + /// 对象名称。 + /// 对象是否被加锁。 + /// 对象自定义释放检查标记。 + /// 对象的优先级。 + /// 对象上次使用时间。 + /// 对象的获取计数。 + public ObjectInfo(string name, bool locked, bool customCanReleaseFlag, int priority, DateTime lastUseTime, int spawnCount) + { + m_Name = name; + m_Locked = locked; + m_CustomCanReleaseFlag = customCanReleaseFlag; + m_Priority = priority; + m_LastUseTime = lastUseTime; + m_SpawnCount = spawnCount; + } + + /// + /// 获取对象名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取对象是否被加锁。 + /// + public bool Locked + { + get + { + return m_Locked; + } + } + + /// + /// 获取对象自定义释放检查标记。 + /// + public bool CustomCanReleaseFlag + { + get + { + return m_CustomCanReleaseFlag; + } + } + + /// + /// 获取对象的优先级。 + /// + public int Priority + { + get + { + return m_Priority; + } + } + + /// + /// 获取对象上次使用时间。 + /// + public DateTime LastUseTime + { + get + { + return m_LastUseTime; + } + } + + /// + /// 获取对象是否正在使用。 + /// + public bool IsInUse + { + get + { + return m_SpawnCount > 0; + } + } + + /// + /// 获取对象的获取计数。 + /// + public int SpawnCount + { + get + { + return m_SpawnCount; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectInfo.cs.meta new file mode 100644 index 0000000..cbb6c9e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b2841a08993aedf46aa28f1a1c219585 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolBase.cs new file mode 100644 index 0000000..d70b6fa --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolBase.cs @@ -0,0 +1,152 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.ObjectPool +{ + /// + /// 对象池基类。 + /// + public abstract class ObjectPoolBase + { + private readonly string m_Name; + + /// + /// 初始化对象池基类的新实例。 + /// + public ObjectPoolBase() + : this(null) + { + } + + /// + /// 初始化对象池基类的新实例。 + /// + /// 对象池名称。 + public ObjectPoolBase(string name) + { + m_Name = name ?? string.Empty; + } + + /// + /// 获取对象池名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取对象池完整名称。 + /// + public string FullName + { + get + { + return new TypeNamePair(ObjectType, m_Name).ToString(); + } + } + + /// + /// 获取对象池对象类型。 + /// + public abstract Type ObjectType + { + get; + } + + /// + /// 获取对象池中对象的数量。 + /// + public abstract int Count + { + get; + } + + /// + /// 获取对象池中能被释放的对象的数量。 + /// + public abstract int CanReleaseCount + { + get; + } + + /// + /// 获取是否允许对象被多次获取。 + /// + public abstract bool AllowMultiSpawn + { + get; + } + + /// + /// 获取或设置对象池自动释放可释放对象的间隔秒数。 + /// + public abstract float AutoReleaseInterval + { + get; + set; + } + + /// + /// 获取或设置对象池的容量。 + /// + public abstract int Capacity + { + get; + set; + } + + /// + /// 获取或设置对象池对象过期秒数。 + /// + public abstract float ExpireTime + { + get; + set; + } + + /// + /// 获取或设置对象池的优先级。 + /// + public abstract int Priority + { + get; + set; + } + + /// + /// 释放对象池中的可释放对象。 + /// + public abstract void Release(); + + /// + /// 释放对象池中的可释放对象。 + /// + /// 尝试释放对象数量。 + public abstract void Release(int toReleaseCount); + + /// + /// 释放对象池中的所有未使用对象。 + /// + public abstract void ReleaseAllUnused(); + + /// + /// 获取所有对象信息。 + /// + /// 所有对象信息。 + public abstract ObjectInfo[] GetAllObjectInfos(); + + internal abstract void Update(float elapseSeconds, float realElapseSeconds); + + internal abstract void Shutdown(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolBase.cs.meta new file mode 100644 index 0000000..b0af2f1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eb3ff0b617109874fbc72b070d8a3c68 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.Object.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.Object.cs new file mode 100644 index 0000000..e20d765 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.Object.cs @@ -0,0 +1,196 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.ObjectPool +{ + internal sealed partial class ObjectPoolManager : GameFrameworkModule, IObjectPoolManager + { + /// + /// 内部对象。 + /// + /// 对象类型。 + private sealed class Object : IReference where T : ObjectBase + { + private T m_Object; + private int m_SpawnCount; + + /// + /// 初始化内部对象的新实例。 + /// + public Object() + { + m_Object = null; + m_SpawnCount = 0; + } + + /// + /// 获取对象名称。 + /// + public string Name + { + get + { + return m_Object.Name; + } + } + + /// + /// 获取对象是否被加锁。 + /// + public bool Locked + { + get + { + return m_Object.Locked; + } + internal set + { + m_Object.Locked = value; + } + } + + /// + /// 获取对象的优先级。 + /// + public int Priority + { + get + { + return m_Object.Priority; + } + internal set + { + m_Object.Priority = value; + } + } + + /// + /// 获取自定义释放检查标记。 + /// + public bool CustomCanReleaseFlag + { + get + { + return m_Object.CustomCanReleaseFlag; + } + } + + /// + /// 获取对象上次使用时间。 + /// + public DateTime LastUseTime + { + get + { + return m_Object.LastUseTime; + } + } + + /// + /// 获取对象是否正在使用。 + /// + public bool IsInUse + { + get + { + return m_SpawnCount > 0; + } + } + + /// + /// 获取对象的获取计数。 + /// + public int SpawnCount + { + get + { + return m_SpawnCount; + } + } + + /// + /// 创建内部对象。 + /// + /// 对象。 + /// 对象是否已被获取。 + /// 创建的内部对象。 + public static Object Create(T obj, bool spawned) + { + if (obj == null) + { + throw new GameFrameworkException("Object is invalid."); + } + + Object internalObject = ReferencePool.Acquire>(); + internalObject.m_Object = obj; + internalObject.m_SpawnCount = spawned ? 1 : 0; + if (spawned) + { + obj.OnSpawn(); + } + + return internalObject; + } + + /// + /// 清理内部对象。 + /// + public void Clear() + { + m_Object = null; + m_SpawnCount = 0; + } + + /// + /// 查看对象。 + /// + /// 对象。 + public T Peek() + { + return m_Object; + } + + /// + /// 获取对象。 + /// + /// 对象。 + public T Spawn() + { + m_SpawnCount++; + m_Object.LastUseTime = DateTime.UtcNow; + m_Object.OnSpawn(); + return m_Object; + } + + /// + /// 回收对象。 + /// + public void Unspawn() + { + m_Object.OnUnspawn(); + m_Object.LastUseTime = DateTime.UtcNow; + m_SpawnCount--; + if (m_SpawnCount < 0) + { + throw new GameFrameworkException(Utility.Text.Format("Object '{0}' spawn count is less than 0.", Name)); + } + } + + /// + /// 释放对象。 + /// + /// 是否是关闭对象池时触发。 + public void Release(bool isShutdown) + { + m_Object.Release(isShutdown); + ReferencePool.Release(m_Object); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.Object.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.Object.cs.meta new file mode 100644 index 0000000..a399596 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.Object.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7d25239d5d55ea74fb9c08d9d8b14f71 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.ObjectPool.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.ObjectPool.cs new file mode 100644 index 0000000..0cee3a6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.ObjectPool.cs @@ -0,0 +1,637 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.ObjectPool +{ + internal sealed partial class ObjectPoolManager : GameFrameworkModule, IObjectPoolManager + { + /// + /// 对象池。 + /// + /// 对象类型。 + private sealed class ObjectPool : ObjectPoolBase, IObjectPool where T : ObjectBase + { + private readonly GameFrameworkMultiDictionary> m_Objects; + private readonly Dictionary> m_ObjectMap; + private readonly ReleaseObjectFilterCallback m_DefaultReleaseObjectFilterCallback; + private readonly List m_CachedCanReleaseObjects; + private readonly List m_CachedToReleaseObjects; + private readonly bool m_AllowMultiSpawn; + private float m_AutoReleaseInterval; + private int m_Capacity; + private float m_ExpireTime; + private int m_Priority; + private float m_AutoReleaseTime; + + /// + /// 初始化对象池的新实例。 + /// + /// 对象池名称。 + /// 是否允许对象被多次获取。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + public ObjectPool(string name, bool allowMultiSpawn, float autoReleaseInterval, int capacity, float expireTime, int priority) + : base(name) + { + m_Objects = new GameFrameworkMultiDictionary>(); + m_ObjectMap = new Dictionary>(); + m_DefaultReleaseObjectFilterCallback = DefaultReleaseObjectFilterCallback; + m_CachedCanReleaseObjects = new List(); + m_CachedToReleaseObjects = new List(); + m_AllowMultiSpawn = allowMultiSpawn; + m_AutoReleaseInterval = autoReleaseInterval; + Capacity = capacity; + ExpireTime = expireTime; + m_Priority = priority; + m_AutoReleaseTime = 0f; + } + + /// + /// 获取对象池对象类型。 + /// + public override Type ObjectType + { + get + { + return typeof(T); + } + } + + /// + /// 获取对象池中对象的数量。 + /// + public override int Count + { + get + { + return m_ObjectMap.Count; + } + } + + /// + /// 获取对象池中能被释放的对象的数量。 + /// + public override int CanReleaseCount + { + get + { + GetCanReleaseObjects(m_CachedCanReleaseObjects); + return m_CachedCanReleaseObjects.Count; + } + } + + /// + /// 获取是否允许对象被多次获取。 + /// + public override bool AllowMultiSpawn + { + get + { + return m_AllowMultiSpawn; + } + } + + /// + /// 获取或设置对象池自动释放可释放对象的间隔秒数。 + /// + public override float AutoReleaseInterval + { + get + { + return m_AutoReleaseInterval; + } + set + { + m_AutoReleaseInterval = value; + } + } + + /// + /// 获取或设置对象池的容量。 + /// + public override int Capacity + { + get + { + return m_Capacity; + } + set + { + if (value < 0) + { + throw new GameFrameworkException("Capacity is invalid."); + } + + if (m_Capacity == value) + { + return; + } + + m_Capacity = value; + Release(); + } + } + + /// + /// 获取或设置对象池对象过期秒数。 + /// + public override float ExpireTime + { + get + { + return m_ExpireTime; + } + + set + { + if (value < 0f) + { + throw new GameFrameworkException("ExpireTime is invalid."); + } + + if (ExpireTime == value) + { + return; + } + + m_ExpireTime = value; + Release(); + } + } + + /// + /// 获取或设置对象池的优先级。 + /// + public override int Priority + { + get + { + return m_Priority; + } + set + { + m_Priority = value; + } + } + + /// + /// 创建对象。 + /// + /// 对象。 + /// 对象是否已被获取。 + public void Register(T obj, bool spawned) + { + if (obj == null) + { + throw new GameFrameworkException("Object is invalid."); + } + + Object internalObject = Object.Create(obj, spawned); + m_Objects.Add(obj.Name, internalObject); + m_ObjectMap.Add(obj.Target, internalObject); + + if (Count > m_Capacity) + { + Release(); + } + } + + /// + /// 检查对象。 + /// + /// 要检查的对象是否存在。 + public bool CanSpawn() + { + return CanSpawn(string.Empty); + } + + /// + /// 检查对象。 + /// + /// 对象名称。 + /// 要检查的对象是否存在。 + public bool CanSpawn(string name) + { + if (name == null) + { + throw new GameFrameworkException("Name is invalid."); + } + + GameFrameworkLinkedListRange> objectRange = default(GameFrameworkLinkedListRange>); + if (m_Objects.TryGetValue(name, out objectRange)) + { + foreach (Object internalObject in objectRange) + { + if (m_AllowMultiSpawn || !internalObject.IsInUse) + { + return true; + } + } + } + + return false; + } + + /// + /// 获取对象。 + /// + /// 要获取的对象。 + public T Spawn() + { + return Spawn(string.Empty); + } + + /// + /// 获取对象。 + /// + /// 对象名称。 + /// 要获取的对象。 + public T Spawn(string name) + { + if (name == null) + { + throw new GameFrameworkException("Name is invalid."); + } + + GameFrameworkLinkedListRange> objectRange = default(GameFrameworkLinkedListRange>); + if (m_Objects.TryGetValue(name, out objectRange)) + { + foreach (Object internalObject in objectRange) + { + if (m_AllowMultiSpawn || !internalObject.IsInUse) + { + return internalObject.Spawn(); + } + } + } + + return null; + } + + /// + /// 回收对象。 + /// + /// 要回收的对象。 + public void Unspawn(T obj) + { + if (obj == null) + { + throw new GameFrameworkException("Object is invalid."); + } + + Unspawn(obj.Target); + } + + /// + /// 回收对象。 + /// + /// 要回收的对象。 + public void Unspawn(object target) + { + if (target == null) + { + throw new GameFrameworkException("Target is invalid."); + } + + Object internalObject = GetObject(target); + if (internalObject != null) + { + internalObject.Unspawn(); + if (Count > m_Capacity && internalObject.SpawnCount <= 0) + { + Release(); + } + } + else + { + throw new GameFrameworkException(Utility.Text.Format("Can not find target in object pool '{0}', target type is '{1}', target value is '{2}'.", new TypeNamePair(typeof(T), Name), target.GetType().FullName, target)); + } + } + + /// + /// 设置对象是否被加锁。 + /// + /// 要设置被加锁的对象。 + /// 是否被加锁。 + public void SetLocked(T obj, bool locked) + { + if (obj == null) + { + throw new GameFrameworkException("Object is invalid."); + } + + SetLocked(obj.Target, locked); + } + + /// + /// 设置对象是否被加锁。 + /// + /// 要设置被加锁的对象。 + /// 是否被加锁。 + public void SetLocked(object target, bool locked) + { + if (target == null) + { + throw new GameFrameworkException("Target is invalid."); + } + + Object internalObject = GetObject(target); + if (internalObject != null) + { + internalObject.Locked = locked; + } + else + { + throw new GameFrameworkException(Utility.Text.Format("Can not find target in object pool '{0}', target type is '{1}', target value is '{2}'.", new TypeNamePair(typeof(T), Name), target.GetType().FullName, target)); + } + } + + /// + /// 设置对象的优先级。 + /// + /// 要设置优先级的对象。 + /// 优先级。 + public void SetPriority(T obj, int priority) + { + if (obj == null) + { + throw new GameFrameworkException("Object is invalid."); + } + + SetPriority(obj.Target, priority); + } + + /// + /// 设置对象的优先级。 + /// + /// 要设置优先级的对象。 + /// 优先级。 + public void SetPriority(object target, int priority) + { + if (target == null) + { + throw new GameFrameworkException("Target is invalid."); + } + + Object internalObject = GetObject(target); + if (internalObject != null) + { + internalObject.Priority = priority; + } + else + { + throw new GameFrameworkException(Utility.Text.Format("Can not find target in object pool '{0}', target type is '{1}', target value is '{2}'.", new TypeNamePair(typeof(T), Name), target.GetType().FullName, target)); + } + } + + /// + /// 释放对象。 + /// + /// 要释放的对象。 + /// 释放对象是否成功。 + public bool ReleaseObject(T obj) + { + if (obj == null) + { + throw new GameFrameworkException("Object is invalid."); + } + + return ReleaseObject(obj.Target); + } + + /// + /// 释放对象。 + /// + /// 要释放的对象。 + /// 释放对象是否成功。 + public bool ReleaseObject(object target) + { + if (target == null) + { + throw new GameFrameworkException("Target is invalid."); + } + + Object internalObject = GetObject(target); + if (internalObject == null) + { + return false; + } + + if (internalObject.IsInUse || internalObject.Locked || !internalObject.CustomCanReleaseFlag) + { + return false; + } + + m_Objects.Remove(internalObject.Name, internalObject); + m_ObjectMap.Remove(internalObject.Peek().Target); + + internalObject.Release(false); + ReferencePool.Release(internalObject); + return true; + } + + /// + /// 释放对象池中的可释放对象。 + /// + public override void Release() + { + Release(Count - m_Capacity, m_DefaultReleaseObjectFilterCallback); + } + + /// + /// 释放对象池中的可释放对象。 + /// + /// 尝试释放对象数量。 + public override void Release(int toReleaseCount) + { + Release(toReleaseCount, m_DefaultReleaseObjectFilterCallback); + } + + /// + /// 释放对象池中的可释放对象。 + /// + /// 释放对象筛选函数。 + public void Release(ReleaseObjectFilterCallback releaseObjectFilterCallback) + { + Release(Count - m_Capacity, releaseObjectFilterCallback); + } + + /// + /// 释放对象池中的可释放对象。 + /// + /// 尝试释放对象数量。 + /// 释放对象筛选函数。 + public void Release(int toReleaseCount, ReleaseObjectFilterCallback releaseObjectFilterCallback) + { + if (releaseObjectFilterCallback == null) + { + throw new GameFrameworkException("Release object filter callback is invalid."); + } + + if (toReleaseCount < 0) + { + toReleaseCount = 0; + } + + DateTime expireTime = DateTime.MinValue; + if (m_ExpireTime < float.MaxValue) + { + expireTime = DateTime.UtcNow.AddSeconds(-m_ExpireTime); + } + + m_AutoReleaseTime = 0f; + GetCanReleaseObjects(m_CachedCanReleaseObjects); + List toReleaseObjects = releaseObjectFilterCallback(m_CachedCanReleaseObjects, toReleaseCount, expireTime); + if (toReleaseObjects == null || toReleaseObjects.Count <= 0) + { + return; + } + + foreach (T toReleaseObject in toReleaseObjects) + { + ReleaseObject(toReleaseObject); + } + } + + /// + /// 释放对象池中的所有未使用对象。 + /// + public override void ReleaseAllUnused() + { + m_AutoReleaseTime = 0f; + GetCanReleaseObjects(m_CachedCanReleaseObjects); + foreach (T toReleaseObject in m_CachedCanReleaseObjects) + { + ReleaseObject(toReleaseObject); + } + } + + /// + /// 获取所有对象信息。 + /// + /// 所有对象信息。 + public override ObjectInfo[] GetAllObjectInfos() + { + List results = new List(); + foreach (KeyValuePair>> objectRanges in m_Objects) + { + foreach (Object internalObject in objectRanges.Value) + { + results.Add(new ObjectInfo(internalObject.Name, internalObject.Locked, internalObject.CustomCanReleaseFlag, internalObject.Priority, internalObject.LastUseTime, internalObject.SpawnCount)); + } + } + + return results.ToArray(); + } + + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + m_AutoReleaseTime += realElapseSeconds; + if (m_AutoReleaseTime < m_AutoReleaseInterval) + { + return; + } + + Release(); + } + + internal override void Shutdown() + { + foreach (KeyValuePair> objectInMap in m_ObjectMap) + { + objectInMap.Value.Release(true); + ReferencePool.Release(objectInMap.Value); + } + + m_Objects.Clear(); + m_ObjectMap.Clear(); + m_CachedCanReleaseObjects.Clear(); + m_CachedToReleaseObjects.Clear(); + } + + private Object GetObject(object target) + { + if (target == null) + { + throw new GameFrameworkException("Target is invalid."); + } + + Object internalObject = null; + if (m_ObjectMap.TryGetValue(target, out internalObject)) + { + return internalObject; + } + + return null; + } + + private void GetCanReleaseObjects(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair> objectInMap in m_ObjectMap) + { + Object internalObject = objectInMap.Value; + if (internalObject.IsInUse || internalObject.Locked || !internalObject.CustomCanReleaseFlag) + { + continue; + } + + results.Add(internalObject.Peek()); + } + } + + private List DefaultReleaseObjectFilterCallback(List candidateObjects, int toReleaseCount, DateTime expireTime) + { + m_CachedToReleaseObjects.Clear(); + + if (expireTime > DateTime.MinValue) + { + for (int i = candidateObjects.Count - 1; i >= 0; i--) + { + if (candidateObjects[i].LastUseTime <= expireTime) + { + m_CachedToReleaseObjects.Add(candidateObjects[i]); + candidateObjects.RemoveAt(i); + continue; + } + } + + toReleaseCount -= m_CachedToReleaseObjects.Count; + } + + for (int i = 0; toReleaseCount > 0 && i < candidateObjects.Count; i++) + { + for (int j = i + 1; j < candidateObjects.Count; j++) + { + if (candidateObjects[i].Priority > candidateObjects[j].Priority + || candidateObjects[i].Priority == candidateObjects[j].Priority && candidateObjects[i].LastUseTime > candidateObjects[j].LastUseTime) + { + T temp = candidateObjects[i]; + candidateObjects[i] = candidateObjects[j]; + candidateObjects[j] = temp; + } + } + + m_CachedToReleaseObjects.Add(candidateObjects[i]); + toReleaseCount--; + } + + return m_CachedToReleaseObjects; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.ObjectPool.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.ObjectPool.cs.meta new file mode 100644 index 0000000..ed5ac4a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.ObjectPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b63a7ea745699464db6e85a2535c2a56 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.cs new file mode 100644 index 0000000..9ec71bf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.cs @@ -0,0 +1,1303 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.ObjectPool +{ + /// + /// 对象池管理器。 + /// + internal sealed partial class ObjectPoolManager : GameFrameworkModule, IObjectPoolManager + { + private const int DefaultCapacity = int.MaxValue; + private const float DefaultExpireTime = float.MaxValue; + private const int DefaultPriority = 0; + + private readonly Dictionary m_ObjectPools; + private readonly List m_CachedAllObjectPools; + private readonly Comparison m_ObjectPoolComparer; + + /// + /// 初始化对象池管理器的新实例。 + /// + public ObjectPoolManager() + { + m_ObjectPools = new Dictionary(); + m_CachedAllObjectPools = new List(); + m_ObjectPoolComparer = ObjectPoolComparer; + } + + /// + /// 获取游戏框架模块优先级。 + /// + /// 优先级较高的模块会优先轮询,并且关闭操作会后进行。 + internal override int Priority + { + get + { + return 6; + } + } + + /// + /// 获取对象池数量。 + /// + public int Count + { + get + { + return m_ObjectPools.Count; + } + } + + /// + /// 对象池管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + foreach (KeyValuePair objectPool in m_ObjectPools) + { + objectPool.Value.Update(elapseSeconds, realElapseSeconds); + } + } + + /// + /// 关闭并清理对象池管理器。 + /// + internal override void Shutdown() + { + foreach (KeyValuePair objectPool in m_ObjectPools) + { + objectPool.Value.Shutdown(); + } + + m_ObjectPools.Clear(); + m_CachedAllObjectPools.Clear(); + } + + /// + /// 检查是否存在对象池。 + /// + /// 对象类型。 + /// 是否存在对象池。 + public bool HasObjectPool() where T : ObjectBase + { + return InternalHasObjectPool(new TypeNamePair(typeof(T))); + } + + /// + /// 检查是否存在对象池。 + /// + /// 对象类型。 + /// 是否存在对象池。 + public bool HasObjectPool(Type objectType) + { + if (objectType == null) + { + throw new GameFrameworkException("Object type is invalid."); + } + + if (!typeof(ObjectBase).IsAssignableFrom(objectType)) + { + throw new GameFrameworkException(Utility.Text.Format("Object type '{0}' is invalid.", objectType.FullName)); + } + + return InternalHasObjectPool(new TypeNamePair(objectType)); + } + + /// + /// 检查是否存在对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 是否存在对象池。 + public bool HasObjectPool(string name) where T : ObjectBase + { + return InternalHasObjectPool(new TypeNamePair(typeof(T), name)); + } + + /// + /// 检查是否存在对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 是否存在对象池。 + public bool HasObjectPool(Type objectType, string name) + { + if (objectType == null) + { + throw new GameFrameworkException("Object type is invalid."); + } + + if (!typeof(ObjectBase).IsAssignableFrom(objectType)) + { + throw new GameFrameworkException(Utility.Text.Format("Object type '{0}' is invalid.", objectType.FullName)); + } + + return InternalHasObjectPool(new TypeNamePair(objectType, name)); + } + + /// + /// 检查是否存在对象池。 + /// + /// 要检查的条件。 + /// 是否存在对象池。 + public bool HasObjectPool(Predicate condition) + { + if (condition == null) + { + throw new GameFrameworkException("Condition is invalid."); + } + + foreach (KeyValuePair objectPool in m_ObjectPools) + { + if (condition(objectPool.Value)) + { + return true; + } + } + + return false; + } + + /// + /// 获取对象池。 + /// + /// 对象类型。 + /// 要获取的对象池。 + public IObjectPool GetObjectPool() where T : ObjectBase + { + return (IObjectPool)InternalGetObjectPool(new TypeNamePair(typeof(T))); + } + + /// + /// 获取对象池。 + /// + /// 对象类型。 + /// 要获取的对象池。 + public ObjectPoolBase GetObjectPool(Type objectType) + { + if (objectType == null) + { + throw new GameFrameworkException("Object type is invalid."); + } + + if (!typeof(ObjectBase).IsAssignableFrom(objectType)) + { + throw new GameFrameworkException(Utility.Text.Format("Object type '{0}' is invalid.", objectType.FullName)); + } + + return InternalGetObjectPool(new TypeNamePair(objectType)); + } + + /// + /// 获取对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要获取的对象池。 + public IObjectPool GetObjectPool(string name) where T : ObjectBase + { + return (IObjectPool)InternalGetObjectPool(new TypeNamePair(typeof(T), name)); + } + + /// + /// 获取对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要获取的对象池。 + public ObjectPoolBase GetObjectPool(Type objectType, string name) + { + if (objectType == null) + { + throw new GameFrameworkException("Object type is invalid."); + } + + if (!typeof(ObjectBase).IsAssignableFrom(objectType)) + { + throw new GameFrameworkException(Utility.Text.Format("Object type '{0}' is invalid.", objectType.FullName)); + } + + return InternalGetObjectPool(new TypeNamePair(objectType, name)); + } + + /// + /// 获取对象池。 + /// + /// 要检查的条件。 + /// 要获取的对象池。 + public ObjectPoolBase GetObjectPool(Predicate condition) + { + if (condition == null) + { + throw new GameFrameworkException("Condition is invalid."); + } + + foreach (KeyValuePair objectPool in m_ObjectPools) + { + if (condition(objectPool.Value)) + { + return objectPool.Value; + } + } + + return null; + } + + /// + /// 获取对象池。 + /// + /// 要检查的条件。 + /// 要获取的对象池。 + public ObjectPoolBase[] GetObjectPools(Predicate condition) + { + if (condition == null) + { + throw new GameFrameworkException("Condition is invalid."); + } + + List results = new List(); + foreach (KeyValuePair objectPool in m_ObjectPools) + { + if (condition(objectPool.Value)) + { + results.Add(objectPool.Value); + } + } + + return results.ToArray(); + } + + /// + /// 获取对象池。 + /// + /// 要检查的条件。 + /// 要获取的对象池。 + public void GetObjectPools(Predicate condition, List results) + { + if (condition == null) + { + throw new GameFrameworkException("Condition is invalid."); + } + + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair objectPool in m_ObjectPools) + { + if (condition(objectPool.Value)) + { + results.Add(objectPool.Value); + } + } + } + + /// + /// 获取所有对象池。 + /// + /// 所有对象池。 + public ObjectPoolBase[] GetAllObjectPools() + { + return GetAllObjectPools(false); + } + + /// + /// 获取所有对象池。 + /// + /// 所有对象池。 + public void GetAllObjectPools(List results) + { + GetAllObjectPools(false, results); + } + + /// + /// 获取所有对象池。 + /// + /// 是否根据对象池的优先级排序。 + /// 所有对象池。 + public ObjectPoolBase[] GetAllObjectPools(bool sort) + { + if (sort) + { + List results = new List(); + foreach (KeyValuePair objectPool in m_ObjectPools) + { + results.Add(objectPool.Value); + } + + results.Sort(m_ObjectPoolComparer); + return results.ToArray(); + } + else + { + int index = 0; + ObjectPoolBase[] results = new ObjectPoolBase[m_ObjectPools.Count]; + foreach (KeyValuePair objectPool in m_ObjectPools) + { + results[index++] = objectPool.Value; + } + + return results; + } + } + + /// + /// 获取所有对象池。 + /// + /// 是否根据对象池的优先级排序。 + /// 所有对象池。 + public void GetAllObjectPools(bool sort, List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair objectPool in m_ObjectPools) + { + results.Add(objectPool.Value); + } + + if (sort) + { + results.Sort(m_ObjectPoolComparer); + } + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool() where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, false, DefaultExpireTime, DefaultCapacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType) + { + return InternalCreateObjectPool(objectType, string.Empty, false, DefaultExpireTime, DefaultCapacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name) where T : ObjectBase + { + return InternalCreateObjectPool(name, false, DefaultExpireTime, DefaultCapacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name) + { + return InternalCreateObjectPool(objectType, name, false, DefaultExpireTime, DefaultCapacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(int capacity) where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, false, DefaultExpireTime, capacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, int capacity) + { + return InternalCreateObjectPool(objectType, string.Empty, false, DefaultExpireTime, capacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(float expireTime) where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, false, expireTime, DefaultCapacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, float expireTime) + { + return InternalCreateObjectPool(objectType, string.Empty, false, expireTime, DefaultCapacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, int capacity) where T : ObjectBase + { + return InternalCreateObjectPool(name, false, DefaultExpireTime, capacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, int capacity) + { + return InternalCreateObjectPool(objectType, name, false, DefaultExpireTime, capacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, float expireTime) where T : ObjectBase + { + return InternalCreateObjectPool(name, false, expireTime, DefaultCapacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, float expireTime) + { + return InternalCreateObjectPool(objectType, name, false, expireTime, DefaultCapacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(int capacity, float expireTime) where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, false, expireTime, capacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, int capacity, float expireTime) + { + return InternalCreateObjectPool(objectType, string.Empty, false, expireTime, capacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(int capacity, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, false, DefaultExpireTime, capacity, DefaultExpireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, int capacity, int priority) + { + return InternalCreateObjectPool(objectType, string.Empty, false, DefaultExpireTime, capacity, DefaultExpireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(float expireTime, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, false, expireTime, DefaultCapacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, float expireTime, int priority) + { + return InternalCreateObjectPool(objectType, string.Empty, false, expireTime, DefaultCapacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, int capacity, float expireTime) where T : ObjectBase + { + return InternalCreateObjectPool(name, false, expireTime, capacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, int capacity, float expireTime) + { + return InternalCreateObjectPool(objectType, name, false, expireTime, capacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, int capacity, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(name, false, DefaultExpireTime, capacity, DefaultExpireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, int capacity, int priority) + { + return InternalCreateObjectPool(objectType, name, false, DefaultExpireTime, capacity, DefaultExpireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, float expireTime, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(name, false, expireTime, DefaultCapacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, float expireTime, int priority) + { + return InternalCreateObjectPool(objectType, name, false, expireTime, DefaultCapacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(int capacity, float expireTime, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, false, expireTime, capacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, int capacity, float expireTime, int priority) + { + return InternalCreateObjectPool(objectType, string.Empty, false, expireTime, capacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, int capacity, float expireTime, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(name, false, expireTime, capacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, int capacity, float expireTime, int priority) + { + return InternalCreateObjectPool(objectType, name, false, expireTime, capacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, float autoReleaseInterval, int capacity, float expireTime, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(name, false, autoReleaseInterval, capacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, float autoReleaseInterval, int capacity, float expireTime, int priority) + { + return InternalCreateObjectPool(objectType, name, false, autoReleaseInterval, capacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool() where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, true, DefaultExpireTime, DefaultCapacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType) + { + return InternalCreateObjectPool(objectType, string.Empty, true, DefaultExpireTime, DefaultCapacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name) where T : ObjectBase + { + return InternalCreateObjectPool(name, true, DefaultExpireTime, DefaultCapacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name) + { + return InternalCreateObjectPool(objectType, name, true, DefaultExpireTime, DefaultCapacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(int capacity) where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, true, DefaultExpireTime, capacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, int capacity) + { + return InternalCreateObjectPool(objectType, string.Empty, true, DefaultExpireTime, capacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(float expireTime) where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, true, expireTime, DefaultCapacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, float expireTime) + { + return InternalCreateObjectPool(objectType, string.Empty, true, expireTime, DefaultCapacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, int capacity) where T : ObjectBase + { + return InternalCreateObjectPool(name, true, DefaultExpireTime, capacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, int capacity) + { + return InternalCreateObjectPool(objectType, name, true, DefaultExpireTime, capacity, DefaultExpireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, float expireTime) where T : ObjectBase + { + return InternalCreateObjectPool(name, true, expireTime, DefaultCapacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, float expireTime) + { + return InternalCreateObjectPool(objectType, name, true, expireTime, DefaultCapacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(int capacity, float expireTime) where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, true, expireTime, capacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, int capacity, float expireTime) + { + return InternalCreateObjectPool(objectType, string.Empty, true, expireTime, capacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(int capacity, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, true, DefaultExpireTime, capacity, DefaultExpireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, int capacity, int priority) + { + return InternalCreateObjectPool(objectType, string.Empty, true, DefaultExpireTime, capacity, DefaultExpireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(float expireTime, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, true, expireTime, DefaultCapacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, float expireTime, int priority) + { + return InternalCreateObjectPool(objectType, string.Empty, true, expireTime, DefaultCapacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, int capacity, float expireTime) where T : ObjectBase + { + return InternalCreateObjectPool(name, true, expireTime, capacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, int capacity, float expireTime) + { + return InternalCreateObjectPool(objectType, name, true, expireTime, capacity, expireTime, DefaultPriority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, int capacity, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(name, true, DefaultExpireTime, capacity, DefaultExpireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, int capacity, int priority) + { + return InternalCreateObjectPool(objectType, name, true, DefaultExpireTime, capacity, DefaultExpireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, float expireTime, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(name, true, expireTime, DefaultCapacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, float expireTime, int priority) + { + return InternalCreateObjectPool(objectType, name, true, expireTime, DefaultCapacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(int capacity, float expireTime, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(string.Empty, true, expireTime, capacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, int capacity, float expireTime, int priority) + { + return InternalCreateObjectPool(objectType, string.Empty, true, expireTime, capacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, int capacity, float expireTime, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(name, true, expireTime, capacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, int capacity, float expireTime, int priority) + { + return InternalCreateObjectPool(objectType, name, true, expireTime, capacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, float autoReleaseInterval, int capacity, float expireTime, int priority) where T : ObjectBase + { + return InternalCreateObjectPool(name, true, autoReleaseInterval, capacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, float autoReleaseInterval, int capacity, float expireTime, int priority) + { + return InternalCreateObjectPool(objectType, name, true, autoReleaseInterval, capacity, expireTime, priority); + } + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 是否销毁对象池成功。 + public bool DestroyObjectPool() where T : ObjectBase + { + return InternalDestroyObjectPool(new TypeNamePair(typeof(T))); + } + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 是否销毁对象池成功。 + public bool DestroyObjectPool(Type objectType) + { + if (objectType == null) + { + throw new GameFrameworkException("Object type is invalid."); + } + + if (!typeof(ObjectBase).IsAssignableFrom(objectType)) + { + throw new GameFrameworkException(Utility.Text.Format("Object type '{0}' is invalid.", objectType.FullName)); + } + + return InternalDestroyObjectPool(new TypeNamePair(objectType)); + } + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 要销毁的对象池名称。 + /// 是否销毁对象池成功。 + public bool DestroyObjectPool(string name) where T : ObjectBase + { + return InternalDestroyObjectPool(new TypeNamePair(typeof(T), name)); + } + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 要销毁的对象池名称。 + /// 是否销毁对象池成功。 + public bool DestroyObjectPool(Type objectType, string name) + { + if (objectType == null) + { + throw new GameFrameworkException("Object type is invalid."); + } + + if (!typeof(ObjectBase).IsAssignableFrom(objectType)) + { + throw new GameFrameworkException(Utility.Text.Format("Object type '{0}' is invalid.", objectType.FullName)); + } + + return InternalDestroyObjectPool(new TypeNamePair(objectType, name)); + } + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 要销毁的对象池。 + /// 是否销毁对象池成功。 + public bool DestroyObjectPool(IObjectPool objectPool) where T : ObjectBase + { + if (objectPool == null) + { + throw new GameFrameworkException("Object pool is invalid."); + } + + return InternalDestroyObjectPool(new TypeNamePair(typeof(T), objectPool.Name)); + } + + /// + /// 销毁对象池。 + /// + /// 要销毁的对象池。 + /// 是否销毁对象池成功。 + public bool DestroyObjectPool(ObjectPoolBase objectPool) + { + if (objectPool == null) + { + throw new GameFrameworkException("Object pool is invalid."); + } + + return InternalDestroyObjectPool(new TypeNamePair(objectPool.ObjectType, objectPool.Name)); + } + + /// + /// 释放对象池中的可释放对象。 + /// + public void Release() + { + GetAllObjectPools(true, m_CachedAllObjectPools); + foreach (ObjectPoolBase objectPool in m_CachedAllObjectPools) + { + objectPool.Release(); + } + } + + /// + /// 释放对象池中的所有未使用对象。 + /// + public void ReleaseAllUnused() + { + GetAllObjectPools(true, m_CachedAllObjectPools); + foreach (ObjectPoolBase objectPool in m_CachedAllObjectPools) + { + objectPool.ReleaseAllUnused(); + } + } + + private bool InternalHasObjectPool(TypeNamePair typeNamePair) + { + return m_ObjectPools.ContainsKey(typeNamePair); + } + + private ObjectPoolBase InternalGetObjectPool(TypeNamePair typeNamePair) + { + ObjectPoolBase objectPool = null; + if (m_ObjectPools.TryGetValue(typeNamePair, out objectPool)) + { + return objectPool; + } + + return null; + } + + private IObjectPool InternalCreateObjectPool(string name, bool allowMultiSpawn, float autoReleaseInterval, int capacity, float expireTime, int priority) where T : ObjectBase + { + TypeNamePair typeNamePair = new TypeNamePair(typeof(T), name); + if (HasObjectPool(name)) + { + throw new GameFrameworkException(Utility.Text.Format("Already exist object pool '{0}'.", typeNamePair)); + } + + ObjectPool objectPool = new ObjectPool(name, allowMultiSpawn, autoReleaseInterval, capacity, expireTime, priority); + m_ObjectPools.Add(typeNamePair, objectPool); + return objectPool; + } + + private ObjectPoolBase InternalCreateObjectPool(Type objectType, string name, bool allowMultiSpawn, float autoReleaseInterval, int capacity, float expireTime, int priority) + { + if (objectType == null) + { + throw new GameFrameworkException("Object type is invalid."); + } + + if (!typeof(ObjectBase).IsAssignableFrom(objectType)) + { + throw new GameFrameworkException(Utility.Text.Format("Object type '{0}' is invalid.", objectType.FullName)); + } + + TypeNamePair typeNamePair = new TypeNamePair(objectType, name); + if (HasObjectPool(objectType, name)) + { + throw new GameFrameworkException(Utility.Text.Format("Already exist object pool '{0}'.", typeNamePair)); + } + + Type objectPoolType = typeof(ObjectPool<>).MakeGenericType(objectType); + ObjectPoolBase objectPool = (ObjectPoolBase)Activator.CreateInstance(objectPoolType, name, allowMultiSpawn, autoReleaseInterval, capacity, expireTime, priority); + m_ObjectPools.Add(typeNamePair, objectPool); + return objectPool; + } + + private bool InternalDestroyObjectPool(TypeNamePair typeNamePair) + { + ObjectPoolBase objectPool = null; + if (m_ObjectPools.TryGetValue(typeNamePair, out objectPool)) + { + objectPool.Shutdown(); + return m_ObjectPools.Remove(typeNamePair); + } + + return false; + } + + private static int ObjectPoolComparer(ObjectPoolBase a, ObjectPoolBase b) + { + return a.Priority.CompareTo(b.Priority); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.cs.meta new file mode 100644 index 0000000..8b8dc2d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ObjectPoolManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4fe6f236a504e4540be4c54618813794 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ReleaseObjectFilterCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ReleaseObjectFilterCallback.cs new file mode 100644 index 0000000..a14a741 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ReleaseObjectFilterCallback.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.ObjectPool +{ + /// + /// 释放对象筛选函数。 + /// + /// 对象类型。 + /// 要筛选的对象集合。 + /// 需要释放的对象数量。 + /// 对象过期参考时间。 + /// 经筛选需要释放的对象集合。 + public delegate List ReleaseObjectFilterCallback(List candidateObjects, int toReleaseCount, DateTime expireTime) where T : ObjectBase; +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ReleaseObjectFilterCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ReleaseObjectFilterCallback.cs.meta new file mode 100644 index 0000000..c4220ed --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/ObjectPool/ReleaseObjectFilterCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 316950f903642e140b28a98d191593d6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure.meta new file mode 100644 index 0000000..09c2911 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 93f42ccdf732d444eb45acfdebe91cf3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/IProcedureManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/IProcedureManager.cs new file mode 100644 index 0000000..0a07dcc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/IProcedureManager.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Fsm; +using System; + +namespace GameFramework.Procedure +{ + /// + /// 流程管理器接口。 + /// + public interface IProcedureManager + { + /// + /// 获取当前流程。 + /// + ProcedureBase CurrentProcedure + { + get; + } + + /// + /// 获取当前流程持续时间。 + /// + float CurrentProcedureTime + { + get; + } + + /// + /// 初始化流程管理器。 + /// + /// 有限状态机管理器。 + /// 流程管理器包含的流程。 + void Initialize(IFsmManager fsmManager, params ProcedureBase[] procedures); + + /// + /// 开始流程。 + /// + /// 要开始的流程类型。 + void StartProcedure() where T : ProcedureBase; + + /// + /// 开始流程。 + /// + /// 要开始的流程类型。 + void StartProcedure(Type procedureType); + + /// + /// 是否存在流程。 + /// + /// 要检查的流程类型。 + /// 是否存在流程。 + bool HasProcedure() where T : ProcedureBase; + + /// + /// 是否存在流程。 + /// + /// 要检查的流程类型。 + /// 是否存在流程。 + bool HasProcedure(Type procedureType); + + /// + /// 获取流程。 + /// + /// 要获取的流程类型。 + /// 要获取的流程。 + ProcedureBase GetProcedure() where T : ProcedureBase; + + /// + /// 获取流程。 + /// + /// 要获取的流程类型。 + /// 要获取的流程。 + ProcedureBase GetProcedure(Type procedureType); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/IProcedureManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/IProcedureManager.cs.meta new file mode 100644 index 0000000..ec5a277 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/IProcedureManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4634353942ca3345a4b6f8854aff84f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/ProcedureBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/ProcedureBase.cs new file mode 100644 index 0000000..fe12b37 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/ProcedureBase.cs @@ -0,0 +1,66 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Fsm; +using ProcedureOwner = GameFramework.Fsm.IFsm; + +namespace GameFramework.Procedure +{ + /// + /// 流程基类。 + /// + public abstract class ProcedureBase : FsmState + { + /// + /// 状态初始化时调用。 + /// + /// 流程持有者。 + protected internal override void OnInit(ProcedureOwner procedureOwner) + { + base.OnInit(procedureOwner); + } + + /// + /// 进入状态时调用。 + /// + /// 流程持有者。 + protected internal override void OnEnter(ProcedureOwner procedureOwner) + { + base.OnEnter(procedureOwner); + } + + /// + /// 状态轮询时调用。 + /// + /// 流程持有者。 + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + protected internal override void OnUpdate(ProcedureOwner procedureOwner, float elapseSeconds, float realElapseSeconds) + { + base.OnUpdate(procedureOwner, elapseSeconds, realElapseSeconds); + } + + /// + /// 离开状态时调用。 + /// + /// 流程持有者。 + /// 是否是关闭状态机时触发。 + protected internal override void OnLeave(ProcedureOwner procedureOwner, bool isShutdown) + { + base.OnLeave(procedureOwner, isShutdown); + } + + /// + /// 状态销毁时调用。 + /// + /// 流程持有者。 + protected internal override void OnDestroy(ProcedureOwner procedureOwner) + { + base.OnDestroy(procedureOwner); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/ProcedureBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/ProcedureBase.cs.meta new file mode 100644 index 0000000..34f4ce0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/ProcedureBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 034fbfe11d07865408f726f3e06434b5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/ProcedureManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/ProcedureManager.cs new file mode 100644 index 0000000..8741258 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/ProcedureManager.cs @@ -0,0 +1,204 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Fsm; +using System; + +namespace GameFramework.Procedure +{ + /// + /// 流程管理器。 + /// + internal sealed class ProcedureManager : GameFrameworkModule, IProcedureManager + { + private IFsmManager m_FsmManager; + private IFsm m_ProcedureFsm; + + /// + /// 初始化流程管理器的新实例。 + /// + public ProcedureManager() + { + m_FsmManager = null; + m_ProcedureFsm = null; + } + + /// + /// 获取游戏框架模块优先级。 + /// + /// 优先级较高的模块会优先轮询,并且关闭操作会后进行。 + internal override int Priority + { + get + { + return -2; + } + } + + /// + /// 获取当前流程。 + /// + public ProcedureBase CurrentProcedure + { + get + { + if (m_ProcedureFsm == null) + { + throw new GameFrameworkException("You must initialize procedure first."); + } + + return (ProcedureBase)m_ProcedureFsm.CurrentState; + } + } + + /// + /// 获取当前流程持续时间。 + /// + public float CurrentProcedureTime + { + get + { + if (m_ProcedureFsm == null) + { + throw new GameFrameworkException("You must initialize procedure first."); + } + + return m_ProcedureFsm.CurrentStateTime; + } + } + + /// + /// 流程管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 关闭并清理流程管理器。 + /// + internal override void Shutdown() + { + if (m_FsmManager != null) + { + if (m_ProcedureFsm != null) + { + m_FsmManager.DestroyFsm(m_ProcedureFsm); + m_ProcedureFsm = null; + } + + m_FsmManager = null; + } + } + + /// + /// 初始化流程管理器。 + /// + /// 有限状态机管理器。 + /// 流程管理器包含的流程。 + public void Initialize(IFsmManager fsmManager, params ProcedureBase[] procedures) + { + if (fsmManager == null) + { + throw new GameFrameworkException("FSM manager is invalid."); + } + + m_FsmManager = fsmManager; + m_ProcedureFsm = m_FsmManager.CreateFsm(this, procedures); + } + + /// + /// 开始流程。 + /// + /// 要开始的流程类型。 + public void StartProcedure() where T : ProcedureBase + { + if (m_ProcedureFsm == null) + { + throw new GameFrameworkException("You must initialize procedure first."); + } + + m_ProcedureFsm.Start(); + } + + /// + /// 开始流程。 + /// + /// 要开始的流程类型。 + public void StartProcedure(Type procedureType) + { + if (m_ProcedureFsm == null) + { + throw new GameFrameworkException("You must initialize procedure first."); + } + + m_ProcedureFsm.Start(procedureType); + } + + /// + /// 是否存在流程。 + /// + /// 要检查的流程类型。 + /// 是否存在流程。 + public bool HasProcedure() where T : ProcedureBase + { + if (m_ProcedureFsm == null) + { + throw new GameFrameworkException("You must initialize procedure first."); + } + + return m_ProcedureFsm.HasState(); + } + + /// + /// 是否存在流程。 + /// + /// 要检查的流程类型。 + /// 是否存在流程。 + public bool HasProcedure(Type procedureType) + { + if (m_ProcedureFsm == null) + { + throw new GameFrameworkException("You must initialize procedure first."); + } + + return m_ProcedureFsm.HasState(procedureType); + } + + /// + /// 获取流程。 + /// + /// 要获取的流程类型。 + /// 要获取的流程。 + public ProcedureBase GetProcedure() where T : ProcedureBase + { + if (m_ProcedureFsm == null) + { + throw new GameFrameworkException("You must initialize procedure first."); + } + + return m_ProcedureFsm.GetState(); + } + + /// + /// 获取流程。 + /// + /// 要获取的流程类型。 + /// 要获取的流程。 + public ProcedureBase GetProcedure(Type procedureType) + { + if (m_ProcedureFsm == null) + { + throw new GameFrameworkException("You must initialize procedure first."); + } + + return (ProcedureBase)m_ProcedureFsm.GetState(procedureType); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/ProcedureManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/ProcedureManager.cs.meta new file mode 100644 index 0000000..8cb020f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Procedure/ProcedureManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c71102ea3b618ee428cac01413a34a3c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Properties.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Properties.meta new file mode 100644 index 0000000..72badde --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Properties.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f1103f49fa0c4ea4a9adb776206038b3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Properties/AssemblyInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7ba21ca --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Reflection; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下控制。更改这些特性值可修改与程序集关联的信息。 +[assembly: AssemblyTitle("Game Framework")] +[assembly: AssemblyDescription("Game Framework")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Jiang Yin")] +[assembly: AssemblyProduct("Game Framework")] +[assembly: AssemblyCopyright("Copyright © 2013-2021 Jiang Yin")] +[assembly: AssemblyTrademark("Copyright © 2013-2021 Jiang Yin")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 将使此程序集中的类型对 COM 组件不可见。 +// 如果需要从 COM 访问此程序集中的类型,请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID。 +[assembly: Guid("109d7f39-79ab-4862-9f73-0b8c638930c6")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,方法是按如下所示使用“*”: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.0.0.0")] +[assembly: AssemblyFileVersion("0.0.0.0")] diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Properties/AssemblyInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Properties/AssemblyInfo.cs.meta new file mode 100644 index 0000000..d55b663 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Properties/AssemblyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9894300a237340c449a5a61a97c5528c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource.meta new file mode 100644 index 0000000..e33e842 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 548190345212e474b9b0d55b43627105 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ApplyResourcesCompleteCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ApplyResourcesCompleteCallback.cs new file mode 100644 index 0000000..ac3cf34 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ApplyResourcesCompleteCallback.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 使用可更新模式并应用资源包资源完成时的回调函数。 + /// + /// 应用的资源包路径。 + /// 应用资源包资源结果,全部成功为 true,否则为 false。 + public delegate void ApplyResourcesCompleteCallback(string resourcePackPath, bool result); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ApplyResourcesCompleteCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ApplyResourcesCompleteCallback.cs.meta new file mode 100644 index 0000000..d09b76c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ApplyResourcesCompleteCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e9d27a65d627b6c4facd67c3371e85f6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/CheckResourcesCompleteCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/CheckResourcesCompleteCallback.cs new file mode 100644 index 0000000..5077a9a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/CheckResourcesCompleteCallback.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 使用可更新模式并检查资源完成时的回调函数。 + /// + /// 已移动的资源数量。 + /// 已移除的资源数量。 + /// 可更新的资源数量。 + /// 可更新的资源总大小。 + /// 可更新的压缩后总大小。 + public delegate void CheckResourcesCompleteCallback(int movedCount, int removedCount, int updateCount, long updateTotalLength, long updateTotalCompressedLength); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/CheckResourcesCompleteCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/CheckResourcesCompleteCallback.cs.meta new file mode 100644 index 0000000..aab0b02 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/CheckResourcesCompleteCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 44b378c75bd47654e8269f1a95775e36 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/CheckVersionListResult.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/CheckVersionListResult.cs new file mode 100644 index 0000000..5ca6d37 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/CheckVersionListResult.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 检查版本资源列表结果。 + /// + public enum CheckVersionListResult : byte + { + /// + /// 已经是最新的。 + /// + Updated = 0, + + /// + /// 需要更新。 + /// + NeedUpdate + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/CheckVersionListResult.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/CheckVersionListResult.cs.meta new file mode 100644 index 0000000..a9bfc16 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/CheckVersionListResult.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0011c07ad50f9d4428874a8b1191e5af +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/Constant.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/Constant.cs new file mode 100644 index 0000000..7cda805 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/Constant.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源相关常量。 + /// + internal static class Constant + { + /// + /// 默认资源加载优先级。 + /// + internal const int DefaultPriority = 0; + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/Constant.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/Constant.cs.meta new file mode 100644 index 0000000..c462ec9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/Constant.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8568e897065730448853b7e92432a01a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/DecryptResourceCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/DecryptResourceCallback.cs new file mode 100644 index 0000000..88febfe --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/DecryptResourceCallback.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 解密资源回调函数。 + /// + /// 要解密的资源二进制流。 + /// 解密二进制流的起始位置。 + /// 解密二进制流的长度。 + /// 资源名称。 + /// 变体名称。 + /// 扩展名称。 + /// 资源是否在只读区。 + /// 文件系统名称。 + /// 资源加载方式。 + /// 资源大小。 + /// 资源哈希值。 + public delegate void DecryptResourceCallback(byte[] bytes, int startIndex, int count, string name, string variant, string extension, bool storageInReadOnly, string fileSystem, byte loadType, int length, int hashCode); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/DecryptResourceCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/DecryptResourceCallback.cs.meta new file mode 100644 index 0000000..6bf8649 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/DecryptResourceCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5ff1c45ec7e055346aab3793b995ce9c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/HasAssetResult.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/HasAssetResult.cs new file mode 100644 index 0000000..ca472de --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/HasAssetResult.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 检查资源是否存在的结果。 + /// + public enum HasAssetResult : byte + { + /// + /// 资源不存在。 + /// + NotExist = 0, + + /// + /// 资源尚未准备完毕。 + /// + NotReady, + + /// + /// 存在资源且存储在磁盘上。 + /// + AssetOnDisk, + + /// + /// 存在资源且存储在文件系统里。 + /// + AssetOnFileSystem, + + /// + /// 存在二进制资源且存储在磁盘上。 + /// + BinaryOnDisk, + + /// + /// 存在二进制资源且存储在文件系统里。 + /// + BinaryOnFileSystem + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/HasAssetResult.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/HasAssetResult.cs.meta new file mode 100644 index 0000000..49bcdc5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/HasAssetResult.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 20a6f68e61643af4f97dc4bc326a65be +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ILoadResourceAgentHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ILoadResourceAgentHelper.cs new file mode 100644 index 0000000..a01b1cb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ILoadResourceAgentHelper.cs @@ -0,0 +1,94 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.FileSystem; +using System; + +namespace GameFramework.Resource +{ + /// + /// 加载资源代理辅助器接口。 + /// + public interface ILoadResourceAgentHelper + { + /// + /// 加载资源代理辅助器异步加载资源更新事件。 + /// + event EventHandler LoadResourceAgentHelperUpdate; + + /// + /// 加载资源代理辅助器异步读取资源文件完成事件。 + /// + event EventHandler LoadResourceAgentHelperReadFileComplete; + + /// + /// 加载资源代理辅助器异步读取资源二进制流完成事件。 + /// + event EventHandler LoadResourceAgentHelperReadBytesComplete; + + /// + /// 加载资源代理辅助器异步将资源二进制流转换为加载对象完成事件。 + /// + event EventHandler LoadResourceAgentHelperParseBytesComplete; + + /// + /// 加载资源代理辅助器异步加载资源完成事件。 + /// + event EventHandler LoadResourceAgentHelperLoadComplete; + + /// + /// 加载资源代理辅助器错误事件。 + /// + event EventHandler LoadResourceAgentHelperError; + + /// + /// 通过加载资源代理辅助器开始异步读取资源文件。 + /// + /// 要加载资源的完整路径名。 + void ReadFile(string fullPath); + + /// + /// 通过加载资源代理辅助器开始异步读取资源文件。 + /// + /// 要加载资源的文件系统。 + /// 要加载资源的名称。 + void ReadFile(IFileSystem fileSystem, string name); + + /// + /// 通过加载资源代理辅助器开始异步读取资源二进制流。 + /// + /// 要加载资源的完整路径名。 + void ReadBytes(string fullPath); + + /// + /// 通过加载资源代理辅助器开始异步读取资源二进制流。 + /// + /// 要加载资源的文件系统。 + /// 要加载资源的名称。 + void ReadBytes(IFileSystem fileSystem, string name); + + /// + /// 通过加载资源代理辅助器开始异步将资源二进制流转换为加载对象。 + /// + /// 要加载资源的二进制流。 + void ParseBytes(byte[] bytes); + + /// + /// 通过加载资源代理辅助器开始异步加载资源。 + /// + /// 资源。 + /// 要加载的资源名称。 + /// 要加载资源的类型。 + /// 要加载的资源是否是场景。 + void LoadAsset(object resource, string assetName, Type assetType, bool isScene); + + /// + /// 重置加载资源代理辅助器。 + /// + void Reset(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ILoadResourceAgentHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ILoadResourceAgentHelper.cs.meta new file mode 100644 index 0000000..852f4ca --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ILoadResourceAgentHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc60073224fc84140b3b9ce17514d213 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceGroup.cs new file mode 100644 index 0000000..fc42fd3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceGroup.cs @@ -0,0 +1,101 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.Resource +{ + /// + /// 资源组接口。 + /// + public interface IResourceGroup + { + /// + /// 获取资源组名称。 + /// + string Name + { + get; + } + + /// + /// 获取资源组是否准备完毕。 + /// + bool Ready + { + get; + } + + /// + /// 获取资源组包含资源数量。 + /// + int TotalCount + { + get; + } + + /// + /// 获取资源组中已准备完成资源数量。 + /// + int ReadyCount + { + get; + } + + /// + /// 获取资源组包含资源的总大小。 + /// + long TotalLength + { + get; + } + + /// + /// 获取资源组包含资源压缩后的总大小。 + /// + long TotalCompressedLength + { + get; + } + + /// + /// 获取资源组中已准备完成资源的总大小。 + /// + long ReadyLength + { + get; + } + + /// + /// 获取资源组中已准备完成资源压缩后的总大小。 + /// + long ReadyCompressedLength + { + get; + } + + /// + /// 获取资源组的完成进度。 + /// + float Progress + { + get; + } + + /// + /// 获取资源组包含的资源名称列表。 + /// + /// 资源组包含的资源名称列表。 + string[] GetResourceNames(); + + /// + /// 获取资源组包含的资源名称列表。 + /// + /// 资源组包含的资源名称列表。 + void GetResourceNames(List results); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceGroup.cs.meta new file mode 100644 index 0000000..125812e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae9d786f449ccf5489209e287238c2fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceGroupCollection.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceGroupCollection.cs new file mode 100644 index 0000000..0ad3972 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceGroupCollection.cs @@ -0,0 +1,99 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.Resource +{ + /// + /// 资源组集合接口。 + /// + public interface IResourceGroupCollection + { + /// + /// 获取资源组集合是否准备完毕。 + /// + bool Ready + { + get; + } + + /// + /// 获取资源组集合包含资源数量。 + /// + int TotalCount + { + get; + } + + /// + /// 获取资源组集合中已准备完成资源数量。 + /// + int ReadyCount + { + get; + } + + /// + /// 获取资源组集合包含资源的总大小。 + /// + long TotalLength + { + get; + } + + /// + /// 获取资源组集合包含资源压缩后的总大小。 + /// + long TotalCompressedLength + { + get; + } + + /// + /// 获取资源组集合中已准备完成资源的总大小。 + /// + long ReadyLength + { + get; + } + + /// + /// 获取资源组集合中已准备完成资源压缩后的总大小。 + /// + long ReadyCompressedLength + { + get; + } + + /// + /// 获取资源组集合的完成进度。 + /// + float Progress + { + get; + } + + /// + /// 获取资源组集合包含的资源组列表。 + /// + /// 资源组包含的资源名称列表。 + IResourceGroup[] GetResourceGroups(); + + /// + /// 获取资源组集合包含的资源名称列表。 + /// + /// 资源组包含的资源名称列表。 + string[] GetResourceNames(); + + /// + /// 获取资源组集合包含的资源名称列表。 + /// + /// 资源组包含的资源名称列表。 + void GetResourceNames(List results); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceGroupCollection.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceGroupCollection.cs.meta new file mode 100644 index 0000000..88b3266 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceGroupCollection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e7ed56b1f5e4f9848998342ccd35e44c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceHelper.cs new file mode 100644 index 0000000..23b5e93 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceHelper.cs @@ -0,0 +1,37 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源辅助器接口。 + /// + public interface IResourceHelper + { + /// + /// 直接从指定文件路径加载数据流。 + /// + /// 文件路径。 + /// 加载数据流回调函数集。 + /// 用户自定义数据。 + void LoadBytes(string fileUri, LoadBytesCallbacks loadBytesCallbacks, object userData); + + /// + /// 卸载场景。 + /// + /// 场景资源名称。 + /// 卸载场景回调函数集。 + /// 用户自定义数据。 + void UnloadScene(string sceneAssetName, UnloadSceneCallbacks unloadSceneCallbacks, object userData); + + /// + /// 释放资源。 + /// + /// 要释放的资源。 + void Release(object objectToRelease); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceHelper.cs.meta new file mode 100644 index 0000000..ca146a2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 10986f8d788aa364a8147a56449ebf8a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceManager.cs new file mode 100644 index 0000000..15ac7d7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceManager.cs @@ -0,0 +1,832 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Download; +using GameFramework.FileSystem; +using GameFramework.ObjectPool; +using System; +using System.Collections.Generic; + +namespace GameFramework.Resource +{ + /// + /// 资源管理器接口。 + /// + public interface IResourceManager + { + /// + /// 获取资源只读区路径。 + /// + string ReadOnlyPath + { + get; + } + + /// + /// 获取资源读写区路径。 + /// + string ReadWritePath + { + get; + } + + /// + /// 获取资源模式。 + /// + ResourceMode ResourceMode + { + get; + } + + /// + /// 获取当前变体。 + /// + string CurrentVariant + { + get; + } + + /// + /// 获取单机模式版本资源列表序列化器。 + /// + PackageVersionListSerializer PackageVersionListSerializer + { + get; + } + + /// + /// 获取可更新模式版本资源列表序列化器。 + /// + UpdatableVersionListSerializer UpdatableVersionListSerializer + { + get; + } + + /// + /// 获取本地只读区版本资源列表序列化器。 + /// + ReadOnlyVersionListSerializer ReadOnlyVersionListSerializer + { + get; + } + + /// + /// 获取本地读写区版本资源列表序列化器。 + /// + ReadWriteVersionListSerializer ReadWriteVersionListSerializer + { + get; + } + + /// + /// 获取资源包版本资源列表序列化器。 + /// + ResourcePackVersionListSerializer ResourcePackVersionListSerializer + { + get; + } + + /// + /// 获取当前资源适用的游戏版本号。 + /// + string ApplicableGameVersion + { + get; + } + + /// + /// 获取当前内部资源版本号。 + /// + int InternalResourceVersion + { + get; + } + + /// + /// 获取资源数量。 + /// + int AssetCount + { + get; + } + + /// + /// 获取资源数量。 + /// + int ResourceCount + { + get; + } + + /// + /// 获取资源组数量。 + /// + int ResourceGroupCount + { + get; + } + + /// + /// 获取或设置资源更新下载地址。 + /// + string UpdatePrefixUri + { + get; + set; + } + + /// + /// 获取或设置每更新多少字节的资源,重新生成一次版本资源列表。 + /// + int GenerateReadWriteVersionListLength + { + get; + set; + } + + /// + /// 获取正在应用的资源包路径。 + /// + string ApplyingResourcePackPath + { + get; + } + + /// + /// 获取等待应用资源数量。 + /// + int ApplyWaitingCount + { + get; + } + + /// + /// 获取或设置资源更新重试次数。 + /// + int UpdateRetryCount + { + get; + set; + } + + /// + /// 获取正在更新的资源组。 + /// + IResourceGroup UpdatingResourceGroup + { + get; + } + + /// + /// 获取等待更新资源数量。 + /// + int UpdateWaitingCount + { + get; + } + + /// + /// 获取使用时下载的等待更新资源数量。 + /// + int UpdateWaitingWhilePlayingCount + { + get; + } + + /// + /// 获取候选更新资源数量。 + /// + int UpdateCandidateCount + { + get; + } + + /// + /// 获取加载资源代理总数量。 + /// + int LoadTotalAgentCount + { + get; + } + + /// + /// 获取可用加载资源代理数量。 + /// + int LoadFreeAgentCount + { + get; + } + + /// + /// 获取工作中加载资源代理数量。 + /// + int LoadWorkingAgentCount + { + get; + } + + /// + /// 获取等待加载资源任务数量。 + /// + int LoadWaitingTaskCount + { + get; + } + + /// + /// 获取或设置资源对象池自动释放可释放对象的间隔秒数。 + /// + float AssetAutoReleaseInterval + { + get; + set; + } + + /// + /// 获取或设置资源对象池的容量。 + /// + int AssetCapacity + { + get; + set; + } + + /// + /// 获取或设置资源对象池对象过期秒数。 + /// + float AssetExpireTime + { + get; + set; + } + + /// + /// 获取或设置资源对象池的优先级。 + /// + int AssetPriority + { + get; + set; + } + + /// + /// 获取或设置资源对象池自动释放可释放对象的间隔秒数。 + /// + float ResourceAutoReleaseInterval + { + get; + set; + } + + /// + /// 获取或设置资源对象池的容量。 + /// + int ResourceCapacity + { + get; + set; + } + + /// + /// 获取或设置资源对象池对象过期秒数。 + /// + float ResourceExpireTime + { + get; + set; + } + + /// + /// 获取或设置资源对象池的优先级。 + /// + int ResourcePriority + { + get; + set; + } + + /// + /// 资源校验开始事件。 + /// + event EventHandler ResourceVerifyStart; + + /// + /// 资源校验成功事件。 + /// + event EventHandler ResourceVerifySuccess; + + /// + /// 资源校验失败事件。 + /// + event EventHandler ResourceVerifyFailure; + + /// + /// 资源应用开始事件。 + /// + event EventHandler ResourceApplyStart; + + /// + /// 资源应用成功事件。 + /// + event EventHandler ResourceApplySuccess; + + /// + /// 资源应用失败事件。 + /// + event EventHandler ResourceApplyFailure; + + /// + /// 资源更新开始事件。 + /// + event EventHandler ResourceUpdateStart; + + /// + /// 资源更新改变事件。 + /// + event EventHandler ResourceUpdateChanged; + + /// + /// 资源更新成功事件。 + /// + event EventHandler ResourceUpdateSuccess; + + /// + /// 资源更新失败事件。 + /// + event EventHandler ResourceUpdateFailure; + + /// + /// 资源更新全部完成事件。 + /// + event EventHandler ResourceUpdateAllComplete; + + /// + /// 设置资源只读区路径。 + /// + /// 资源只读区路径。 + void SetReadOnlyPath(string readOnlyPath); + + /// + /// 设置资源读写区路径。 + /// + /// 资源读写区路径。 + void SetReadWritePath(string readWritePath); + + /// + /// 设置资源模式。 + /// + /// 资源模式。 + void SetResourceMode(ResourceMode resourceMode); + + /// + /// 设置当前变体。 + /// + /// 当前变体。 + void SetCurrentVariant(string currentVariant); + + /// + /// 设置对象池管理器。 + /// + /// 对象池管理器。 + void SetObjectPoolManager(IObjectPoolManager objectPoolManager); + + /// + /// 设置文件系统管理器。 + /// + /// 文件系统管理器。 + void SetFileSystemManager(IFileSystemManager fileSystemManager); + + /// + /// 设置下载管理器。 + /// + /// 下载管理器。 + void SetDownloadManager(IDownloadManager downloadManager); + + /// + /// 设置解密资源回调函数。 + /// + /// 要设置的解密资源回调函数。 + /// 如果不设置,将使用默认的解密资源回调函数。 + void SetDecryptResourceCallback(DecryptResourceCallback decryptResourceCallback); + + /// + /// 设置资源辅助器。 + /// + /// 资源辅助器。 + void SetResourceHelper(IResourceHelper resourceHelper); + + /// + /// 增加加载资源代理辅助器。 + /// + /// 要增加的加载资源代理辅助器。 + void AddLoadResourceAgentHelper(ILoadResourceAgentHelper loadResourceAgentHelper); + + /// + /// 使用单机模式并初始化资源。 + /// + /// 使用单机模式并初始化资源完成时的回调函数。 + void InitResources(InitResourcesCompleteCallback initResourcesCompleteCallback); + + /// + /// 使用可更新模式并检查版本资源列表。 + /// + /// 最新的内部资源版本号。 + /// 检查版本资源列表结果。 + CheckVersionListResult CheckVersionList(int latestInternalResourceVersion); + + /// + /// 使用可更新模式并更新版本资源列表。 + /// + /// 版本资源列表大小。 + /// 版本资源列表哈希值。 + /// 版本资源列表压缩后大小。 + /// 版本资源列表压缩后哈希值。 + /// 版本资源列表更新回调函数集。 + void UpdateVersionList(int versionListLength, int versionListHashCode, int versionListCompressedLength, int versionListCompressedHashCode, UpdateVersionListCallbacks updateVersionListCallbacks); + + /// + /// 使用可更新模式并校验资源。 + /// + /// 每帧至少校验资源的大小,以字节为单位。 + /// 使用可更新模式并校验资源完成时的回调函数。 + void VerifyResources(int verifyResourceLengthPerFrame, VerifyResourcesCompleteCallback verifyResourcesCompleteCallback); + + /// + /// 使用可更新模式并检查资源。 + /// + /// 是否忽略处理其它变体的资源,若不忽略,将会移除其它变体的资源。 + /// 使用可更新模式并检查资源完成时的回调函数。 + void CheckResources(bool ignoreOtherVariant, CheckResourcesCompleteCallback checkResourcesCompleteCallback); + + /// + /// 使用可更新模式并应用资源包资源。 + /// + /// 要应用的资源包路径。 + /// 使用可更新模式并应用资源包资源完成时的回调函数。 + void ApplyResources(string resourcePackPath, ApplyResourcesCompleteCallback applyResourcesCompleteCallback); + + /// + /// 使用可更新模式并更新所有资源。 + /// + /// 使用可更新模式并更新默认资源组完成时的回调函数。 + void UpdateResources(UpdateResourcesCompleteCallback updateResourcesCompleteCallback); + + /// + /// 使用可更新模式并更新指定资源组的资源。 + /// + /// 要更新的资源组名称。 + /// 使用可更新模式并更新指定资源组完成时的回调函数。 + void UpdateResources(string resourceGroupName, UpdateResourcesCompleteCallback updateResourcesCompleteCallback); + + /// + /// 停止更新资源。 + /// + void StopUpdateResources(); + + /// + /// 校验资源包。 + /// + /// 要校验的资源包路径。 + /// 是否校验资源包成功。 + bool VerifyResourcePack(string resourcePackPath); + + /// + /// 获取所有加载资源任务的信息。 + /// + /// 所有加载资源任务的信息。 + TaskInfo[] GetAllLoadAssetInfos(); + + /// + /// 获取所有加载资源任务的信息。 + /// + /// 所有加载资源任务的信息。 + void GetAllLoadAssetInfos(List results); + + /// + /// 检查资源是否存在。 + /// + /// 要检查资源的名称。 + /// 检查资源是否存在的结果。 + HasAssetResult HasAsset(string assetName); + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源回调函数集。 + void LoadAsset(string assetName, LoadAssetCallbacks loadAssetCallbacks); + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源回调函数集。 + void LoadAsset(string assetName, Type assetType, LoadAssetCallbacks loadAssetCallbacks); + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + void LoadAsset(string assetName, int priority, LoadAssetCallbacks loadAssetCallbacks); + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + void LoadAsset(string assetName, LoadAssetCallbacks loadAssetCallbacks, object userData); + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + void LoadAsset(string assetName, Type assetType, int priority, LoadAssetCallbacks loadAssetCallbacks); + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + void LoadAsset(string assetName, Type assetType, LoadAssetCallbacks loadAssetCallbacks, object userData); + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + void LoadAsset(string assetName, int priority, LoadAssetCallbacks loadAssetCallbacks, object userData); + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + void LoadAsset(string assetName, Type assetType, int priority, LoadAssetCallbacks loadAssetCallbacks, object userData); + + /// + /// 卸载资源。 + /// + /// 要卸载的资源。 + void UnloadAsset(object asset); + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景回调函数集。 + void LoadScene(string sceneAssetName, LoadSceneCallbacks loadSceneCallbacks); + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景资源的优先级。 + /// 加载场景回调函数集。 + void LoadScene(string sceneAssetName, int priority, LoadSceneCallbacks loadSceneCallbacks); + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景回调函数集。 + /// 用户自定义数据。 + void LoadScene(string sceneAssetName, LoadSceneCallbacks loadSceneCallbacks, object userData); + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景资源的优先级。 + /// 加载场景回调函数集。 + /// 用户自定义数据。 + void LoadScene(string sceneAssetName, int priority, LoadSceneCallbacks loadSceneCallbacks, object userData); + + /// + /// 异步卸载场景。 + /// + /// 要卸载场景资源的名称。 + /// 卸载场景回调函数集。 + void UnloadScene(string sceneAssetName, UnloadSceneCallbacks unloadSceneCallbacks); + + /// + /// 异步卸载场景。 + /// + /// 要卸载场景资源的名称。 + /// 卸载场景回调函数集。 + /// 用户自定义数据。 + void UnloadScene(string sceneAssetName, UnloadSceneCallbacks unloadSceneCallbacks, object userData); + + /// + /// 获取二进制资源的实际路径。 + /// + /// 要获取实际路径的二进制资源的名称。 + /// 二进制资源的实际路径。 + /// 此方法仅适用于二进制资源存储在磁盘(而非文件系统)中的情况。若二进制资源存储在文件系统中时,返回值将始终为空。 + string GetBinaryPath(string binaryAssetName); + + /// + /// 获取二进制资源的实际路径。 + /// + /// 要获取实际路径的二进制资源的名称。 + /// 二进制资源是否存储在只读区中。 + /// 二进制资源是否存储在文件系统中。 + /// 二进制资源或存储二进制资源的文件系统,相对于只读区或者读写区的相对路径。 + /// 若二进制资源存储在文件系统中,则指示二进制资源在文件系统中的名称,否则此参数返回空。 + /// 是否获取二进制资源的实际路径成功。 + bool GetBinaryPath(string binaryAssetName, out bool storageInReadOnly, out bool storageInFileSystem, out string relativePath, out string fileName); + + /// + /// 获取二进制资源的长度。 + /// + /// 要获取长度的二进制资源的名称。 + /// 二进制资源的长度。 + int GetBinaryLength(string binaryAssetName); + + /// + /// 异步加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 加载二进制资源回调函数集。 + void LoadBinary(string binaryAssetName, LoadBinaryCallbacks loadBinaryCallbacks); + + /// + /// 异步加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 加载二进制资源回调函数集。 + /// 用户自定义数据。 + void LoadBinary(string binaryAssetName, LoadBinaryCallbacks loadBinaryCallbacks, object userData); + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + byte[] LoadBinaryFromFileSystem(string binaryAssetName); + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 实际加载了多少字节。 + int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer); + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 存储加载二进制资源的二进制流的起始位置。 + /// 实际加载了多少字节。 + int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex); + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 存储加载二进制资源的二进制流的起始位置。 + /// 存储加载二进制资源的二进制流的长度。 + /// 实际加载了多少字节。 + int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex, int length); + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的长度。 + /// 存储加载二进制资源片段内容的二进制流。 + byte[] LoadBinarySegmentFromFileSystem(string binaryAssetName, int length); + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 要加载片段的长度。 + /// 存储加载二进制资源片段内容的二进制流。 + byte[] LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, int length); + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 实际加载了多少字节。 + int LoadBinarySegmentFromFileSystem(string binaryAssetName, byte[] buffer); + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + int LoadBinarySegmentFromFileSystem(string binaryAssetName, byte[] buffer, int length); + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 存储加载二进制资源片段内容的二进制流的起始位置。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + int LoadBinarySegmentFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex, int length); + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 实际加载了多少字节。 + int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer); + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer, int length); + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 存储加载二进制资源片段内容的二进制流的起始位置。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer, int startIndex, int length); + + /// + /// 检查资源组是否存在。 + /// + /// 要检查资源组的名称。 + /// 资源组是否存在。 + bool HasResourceGroup(string resourceGroupName); + + /// + /// 获取默认资源组。 + /// + /// 默认资源组。 + IResourceGroup GetResourceGroup(); + + /// + /// 获取资源组。 + /// + /// 要获取的资源组名称。 + /// 要获取的资源组。 + IResourceGroup GetResourceGroup(string resourceGroupName); + + /// + /// 获取所有资源组。 + /// + /// 所有资源组。 + IResourceGroup[] GetAllResourceGroups(); + + /// + /// 获取所有资源组。 + /// + /// 所有资源组。 + void GetAllResourceGroups(List results); + + /// + /// 获取资源组集合。 + /// + /// 要获取的资源组名称的集合。 + /// 要获取的资源组集合。 + IResourceGroupCollection GetResourceGroupCollection(params string[] resourceGroupNames); + + /// + /// 获取资源组集合。 + /// + /// 要获取的资源组名称的集合。 + /// 要获取的资源组集合。 + IResourceGroupCollection GetResourceGroupCollection(List resourceGroupNames); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceManager.cs.meta new file mode 100644 index 0000000..5a29a4f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/IResourceManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 038760ab28b316644b1791632030d586 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/InitResourcesCompleteCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/InitResourcesCompleteCallback.cs new file mode 100644 index 0000000..e2554f3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/InitResourcesCompleteCallback.cs @@ -0,0 +1,14 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 使用单机模式并初始化资源完成时的回调函数。 + /// + public delegate void InitResourcesCompleteCallback(); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/InitResourcesCompleteCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/InitResourcesCompleteCallback.cs.meta new file mode 100644 index 0000000..4e5cbaf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/InitResourcesCompleteCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d9c4e61d606a9af4087fc5a0aa1e305f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetCallbacks.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetCallbacks.cs new file mode 100644 index 0000000..a5015d6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetCallbacks.cs @@ -0,0 +1,145 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源回调函数集。 + /// + public sealed class LoadAssetCallbacks + { + private readonly LoadAssetSuccessCallback m_LoadAssetSuccessCallback; + private readonly LoadAssetFailureCallback m_LoadAssetFailureCallback; + private readonly LoadAssetUpdateCallback m_LoadAssetUpdateCallback; + private readonly LoadAssetDependencyAssetCallback m_LoadAssetDependencyAssetCallback; + + /// + /// 初始化加载资源回调函数集的新实例。 + /// + /// 加载资源成功回调函数。 + public LoadAssetCallbacks(LoadAssetSuccessCallback loadAssetSuccessCallback) + : this(loadAssetSuccessCallback, null, null, null) + { + } + + /// + /// 初始化加载资源回调函数集的新实例。 + /// + /// 加载资源成功回调函数。 + /// 加载资源失败回调函数。 + public LoadAssetCallbacks(LoadAssetSuccessCallback loadAssetSuccessCallback, LoadAssetFailureCallback loadAssetFailureCallback) + : this(loadAssetSuccessCallback, loadAssetFailureCallback, null, null) + { + } + + /// + /// 初始化加载资源回调函数集的新实例。 + /// + /// 加载资源成功回调函数。 + /// 加载资源更新回调函数。 + public LoadAssetCallbacks(LoadAssetSuccessCallback loadAssetSuccessCallback, LoadAssetUpdateCallback loadAssetUpdateCallback) + : this(loadAssetSuccessCallback, null, loadAssetUpdateCallback, null) + { + } + + /// + /// 初始化加载资源回调函数集的新实例。 + /// + /// 加载资源成功回调函数。 + /// 加载资源时加载依赖资源回调函数。 + public LoadAssetCallbacks(LoadAssetSuccessCallback loadAssetSuccessCallback, LoadAssetDependencyAssetCallback loadAssetDependencyAssetCallback) + : this(loadAssetSuccessCallback, null, null, loadAssetDependencyAssetCallback) + { + } + + /// + /// 初始化加载资源回调函数集的新实例。 + /// + /// 加载资源成功回调函数。 + /// 加载资源失败回调函数。 + /// 加载资源更新回调函数。 + public LoadAssetCallbacks(LoadAssetSuccessCallback loadAssetSuccessCallback, LoadAssetFailureCallback loadAssetFailureCallback, LoadAssetUpdateCallback loadAssetUpdateCallback) + : this(loadAssetSuccessCallback, loadAssetFailureCallback, loadAssetUpdateCallback, null) + { + } + + /// + /// 初始化加载资源回调函数集的新实例。 + /// + /// 加载资源成功回调函数。 + /// 加载资源失败回调函数。 + /// 加载资源时加载依赖资源回调函数。 + public LoadAssetCallbacks(LoadAssetSuccessCallback loadAssetSuccessCallback, LoadAssetFailureCallback loadAssetFailureCallback, LoadAssetDependencyAssetCallback loadAssetDependencyAssetCallback) + : this(loadAssetSuccessCallback, loadAssetFailureCallback, null, loadAssetDependencyAssetCallback) + { + } + + /// + /// 初始化加载资源回调函数集的新实例。 + /// + /// 加载资源成功回调函数。 + /// 加载资源失败回调函数。 + /// 加载资源更新回调函数。 + /// 加载资源时加载依赖资源回调函数。 + public LoadAssetCallbacks(LoadAssetSuccessCallback loadAssetSuccessCallback, LoadAssetFailureCallback loadAssetFailureCallback, LoadAssetUpdateCallback loadAssetUpdateCallback, LoadAssetDependencyAssetCallback loadAssetDependencyAssetCallback) + { + if (loadAssetSuccessCallback == null) + { + throw new GameFrameworkException("Load asset success callback is invalid."); + } + + m_LoadAssetSuccessCallback = loadAssetSuccessCallback; + m_LoadAssetFailureCallback = loadAssetFailureCallback; + m_LoadAssetUpdateCallback = loadAssetUpdateCallback; + m_LoadAssetDependencyAssetCallback = loadAssetDependencyAssetCallback; + } + + /// + /// 获取加载资源成功回调函数。 + /// + public LoadAssetSuccessCallback LoadAssetSuccessCallback + { + get + { + return m_LoadAssetSuccessCallback; + } + } + + /// + /// 获取加载资源失败回调函数。 + /// + public LoadAssetFailureCallback LoadAssetFailureCallback + { + get + { + return m_LoadAssetFailureCallback; + } + } + + /// + /// 获取加载资源更新回调函数。 + /// + public LoadAssetUpdateCallback LoadAssetUpdateCallback + { + get + { + return m_LoadAssetUpdateCallback; + } + } + + /// + /// 获取加载资源时加载依赖资源回调函数。 + /// + public LoadAssetDependencyAssetCallback LoadAssetDependencyAssetCallback + { + get + { + return m_LoadAssetDependencyAssetCallback; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetCallbacks.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetCallbacks.cs.meta new file mode 100644 index 0000000..5ba0ef5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetCallbacks.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4652225d9b1288b4a89731266c2449b6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetDependencyAssetCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetDependencyAssetCallback.cs new file mode 100644 index 0000000..d27644f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetDependencyAssetCallback.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源时加载依赖资源回调函数。 + /// + /// 要加载的资源名称。 + /// 被加载的依赖资源名称。 + /// 当前已加载依赖资源数量。 + /// 总共加载依赖资源数量。 + /// 用户自定义数据。 + public delegate void LoadAssetDependencyAssetCallback(string assetName, string dependencyAssetName, int loadedCount, int totalCount, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetDependencyAssetCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetDependencyAssetCallback.cs.meta new file mode 100644 index 0000000..ead2a06 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetDependencyAssetCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0922e8a04dfc4c74ab36c5761b282458 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetFailureCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetFailureCallback.cs new file mode 100644 index 0000000..6bbf320 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetFailureCallback.cs @@ -0,0 +1,18 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源失败回调函数。 + /// + /// 要加载的资源名称。 + /// 加载资源状态。 + /// 错误信息。 + /// 用户自定义数据。 + public delegate void LoadAssetFailureCallback(string assetName, LoadResourceStatus status, string errorMessage, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetFailureCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetFailureCallback.cs.meta new file mode 100644 index 0000000..2e83768 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetFailureCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1bbb5bf5a296c714fbb1e5ec319ab75d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetSuccessCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetSuccessCallback.cs new file mode 100644 index 0000000..42e1e2b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetSuccessCallback.cs @@ -0,0 +1,18 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源成功回调函数。 + /// + /// 要加载的资源名称。 + /// 已加载的资源。 + /// 加载持续时间。 + /// 用户自定义数据。 + public delegate void LoadAssetSuccessCallback(string assetName, object asset, float duration, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetSuccessCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetSuccessCallback.cs.meta new file mode 100644 index 0000000..11b3ddf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetSuccessCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 525f9ed1013d56a4c803f50014a31798 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetUpdateCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetUpdateCallback.cs new file mode 100644 index 0000000..c974418 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetUpdateCallback.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源更新回调函数。 + /// + /// 要加载的资源名称。 + /// 加载资源进度。 + /// 用户自定义数据。 + public delegate void LoadAssetUpdateCallback(string assetName, float progress, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetUpdateCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetUpdateCallback.cs.meta new file mode 100644 index 0000000..3254e80 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadAssetUpdateCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f013846d09e1cc3459459323f413f7a2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinaryCallbacks.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinaryCallbacks.cs new file mode 100644 index 0000000..6f48103 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinaryCallbacks.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载二进制资源回调函数集。 + /// + public sealed class LoadBinaryCallbacks + { + private readonly LoadBinarySuccessCallback m_LoadBinarySuccessCallback; + private readonly LoadBinaryFailureCallback m_LoadBinaryFailureCallback; + + /// + /// 初始化加载二进制资源回调函数集的新实例。 + /// + /// 加载二进制资源成功回调函数。 + public LoadBinaryCallbacks(LoadBinarySuccessCallback loadBinarySuccessCallback) + : this(loadBinarySuccessCallback, null) + { + } + + /// + /// 初始化加载二进制资源回调函数集的新实例。 + /// + /// 加载二进制资源成功回调函数。 + /// 加载二进制资源失败回调函数。 + public LoadBinaryCallbacks(LoadBinarySuccessCallback loadBinarySuccessCallback, LoadBinaryFailureCallback loadBinaryFailureCallback) + { + if (loadBinarySuccessCallback == null) + { + throw new GameFrameworkException("Load binary success callback is invalid."); + } + + m_LoadBinarySuccessCallback = loadBinarySuccessCallback; + m_LoadBinaryFailureCallback = loadBinaryFailureCallback; + } + + /// + /// 获取加载二进制资源成功回调函数。 + /// + public LoadBinarySuccessCallback LoadBinarySuccessCallback + { + get + { + return m_LoadBinarySuccessCallback; + } + } + + /// + /// 获取加载二进制资源失败回调函数。 + /// + public LoadBinaryFailureCallback LoadBinaryFailureCallback + { + get + { + return m_LoadBinaryFailureCallback; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinaryCallbacks.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinaryCallbacks.cs.meta new file mode 100644 index 0000000..b31ddbb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinaryCallbacks.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d93de184ed0e7994890f43c306afacc1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinaryFailureCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinaryFailureCallback.cs new file mode 100644 index 0000000..b082502 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinaryFailureCallback.cs @@ -0,0 +1,18 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载二进制资源失败回调函数。 + /// + /// 要加载的二进制资源名称。 + /// 加载二进制资源状态。 + /// 错误信息。 + /// 用户自定义数据。 + public delegate void LoadBinaryFailureCallback(string binaryAssetName, LoadResourceStatus status, string errorMessage, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinaryFailureCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinaryFailureCallback.cs.meta new file mode 100644 index 0000000..8a20c3d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinaryFailureCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bcc38546a41000f4f8793fc9e7641920 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinarySuccessCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinarySuccessCallback.cs new file mode 100644 index 0000000..d6c9476 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinarySuccessCallback.cs @@ -0,0 +1,18 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载二进制资源成功回调函数。 + /// + /// 要加载的二进制资源名称。 + /// 已加载的二进制资源。 + /// 加载持续时间。 + /// 用户自定义数据。 + public delegate void LoadBinarySuccessCallback(string binaryAssetName, byte[] binaryBytes, float duration, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinarySuccessCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinarySuccessCallback.cs.meta new file mode 100644 index 0000000..8cf5290 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBinarySuccessCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc3d41c2d26b7fb4bb704cdbf76cf614 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesCallbacks.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesCallbacks.cs new file mode 100644 index 0000000..0e371b3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesCallbacks.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载数据流回调函数集。 + /// + public sealed class LoadBytesCallbacks + { + private readonly LoadBytesSuccessCallback m_LoadBytesSuccessCallback; + private readonly LoadBytesFailureCallback m_LoadBytesFailureCallback; + + /// + /// 初始化加载数据流回调函数集的新实例。 + /// + /// 加载数据流成功回调函数。 + public LoadBytesCallbacks(LoadBytesSuccessCallback loadBinarySuccessCallback) + : this(loadBinarySuccessCallback, null) + { + } + + /// + /// 初始化加载数据流回调函数集的新实例。 + /// + /// 加载数据流成功回调函数。 + /// 加载数据流失败回调函数。 + public LoadBytesCallbacks(LoadBytesSuccessCallback loadBytesSuccessCallback, LoadBytesFailureCallback loadBytesFailureCallback) + { + if (loadBytesSuccessCallback == null) + { + throw new GameFrameworkException("Load bytes success callback is invalid."); + } + + m_LoadBytesSuccessCallback = loadBytesSuccessCallback; + m_LoadBytesFailureCallback = loadBytesFailureCallback; + } + + /// + /// 获取加载数据流成功回调函数。 + /// + public LoadBytesSuccessCallback LoadBytesSuccessCallback + { + get + { + return m_LoadBytesSuccessCallback; + } + } + + /// + /// 获取加载数据流失败回调函数。 + /// + public LoadBytesFailureCallback LoadBytesFailureCallback + { + get + { + return m_LoadBytesFailureCallback; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesCallbacks.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesCallbacks.cs.meta new file mode 100644 index 0000000..4260c1a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesCallbacks.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6856785609b439b48b21edb6d85a8f0a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesFailureCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesFailureCallback.cs new file mode 100644 index 0000000..9195bf0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesFailureCallback.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载数据流失败回调函数。 + /// + /// 文件路径。 + /// 错误信息。 + /// 用户自定义数据。 + public delegate void LoadBytesFailureCallback(string fileUri, string errorMessage, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesFailureCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesFailureCallback.cs.meta new file mode 100644 index 0000000..c89bbed --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesFailureCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f161856940cb63340805028f4a59c78d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesSuccessCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesSuccessCallback.cs new file mode 100644 index 0000000..538a67b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesSuccessCallback.cs @@ -0,0 +1,18 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载数据流成功回调函数。 + /// + /// 文件路径。 + /// 数据流。 + /// 加载持续时间。 + /// 用户自定义数据。 + public delegate void LoadBytesSuccessCallback(string fileUri, byte[] bytes, float duration, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesSuccessCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesSuccessCallback.cs.meta new file mode 100644 index 0000000..7292201 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadBytesSuccessCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ccbac9811cf09cb4aa2df8e072fc371e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperErrorEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperErrorEventArgs.cs new file mode 100644 index 0000000..d6b7e7c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperErrorEventArgs.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源代理辅助器错误事件。 + /// + public sealed class LoadResourceAgentHelperErrorEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化加载资源代理辅助器错误事件的新实例。 + /// + public LoadResourceAgentHelperErrorEventArgs() + { + Status = LoadResourceStatus.Success; + ErrorMessage = null; + } + + /// + /// 获取加载资源状态。 + /// + public LoadResourceStatus Status + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 创建加载资源代理辅助器错误事件。 + /// + /// 加载资源状态。 + /// 错误信息。 + /// 创建的加载资源代理辅助器错误事件。 + public static LoadResourceAgentHelperErrorEventArgs Create(LoadResourceStatus status, string errorMessage) + { + LoadResourceAgentHelperErrorEventArgs loadResourceAgentHelperErrorEventArgs = ReferencePool.Acquire(); + loadResourceAgentHelperErrorEventArgs.Status = status; + loadResourceAgentHelperErrorEventArgs.ErrorMessage = errorMessage; + return loadResourceAgentHelperErrorEventArgs; + } + + /// + /// 清理加载资源代理辅助器错误事件。 + /// + public override void Clear() + { + Status = LoadResourceStatus.Success; + ErrorMessage = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperErrorEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperErrorEventArgs.cs.meta new file mode 100644 index 0000000..3687f79 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperErrorEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 279209080a115674681468071d5a31e4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperLoadCompleteEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperLoadCompleteEventArgs.cs new file mode 100644 index 0000000..24fbeaa --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperLoadCompleteEventArgs.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源代理辅助器异步加载资源完成事件。 + /// + public sealed class LoadResourceAgentHelperLoadCompleteEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化加载资源代理辅助器异步加载资源完成事件的新实例。 + /// + public LoadResourceAgentHelperLoadCompleteEventArgs() + { + Asset = null; + } + + /// + /// 获取加载的资源。 + /// + public object Asset + { + get; + private set; + } + + /// + /// 创建加载资源代理辅助器异步加载资源完成事件。 + /// + /// 加载的资源。 + /// 创建的加载资源代理辅助器异步加载资源完成事件。 + public static LoadResourceAgentHelperLoadCompleteEventArgs Create(object asset) + { + LoadResourceAgentHelperLoadCompleteEventArgs loadResourceAgentHelperLoadCompleteEventArgs = ReferencePool.Acquire(); + loadResourceAgentHelperLoadCompleteEventArgs.Asset = asset; + return loadResourceAgentHelperLoadCompleteEventArgs; + } + + /// + /// 清理加载资源代理辅助器异步加载资源完成事件。 + /// + public override void Clear() + { + Asset = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperLoadCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperLoadCompleteEventArgs.cs.meta new file mode 100644 index 0000000..9f36f63 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperLoadCompleteEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 098adbe9573d6c94bbf666d9e6e9d84b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperParseBytesCompleteEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperParseBytesCompleteEventArgs.cs new file mode 100644 index 0000000..c63d693 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperParseBytesCompleteEventArgs.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源代理辅助器异步将资源二进制流转换为加载对象完成事件。 + /// + public sealed class LoadResourceAgentHelperParseBytesCompleteEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化加载资源代理辅助器异步将资源二进制流转换为加载对象完成事件的新实例。 + /// + public LoadResourceAgentHelperParseBytesCompleteEventArgs() + { + Resource = null; + } + + /// + /// 获取加载对象。 + /// + public object Resource + { + get; + private set; + } + + /// + /// 创建加载资源代理辅助器异步将资源二进制流转换为加载对象完成事件。 + /// + /// 资源对象。 + /// 创建的加载资源代理辅助器异步将资源二进制流转换为加载对象完成事件。 + public static LoadResourceAgentHelperParseBytesCompleteEventArgs Create(object resource) + { + LoadResourceAgentHelperParseBytesCompleteEventArgs loadResourceAgentHelperParseBytesCompleteEventArgs = ReferencePool.Acquire(); + loadResourceAgentHelperParseBytesCompleteEventArgs.Resource = resource; + return loadResourceAgentHelperParseBytesCompleteEventArgs; + } + + /// + /// 清理加载资源代理辅助器异步将资源二进制流转换为加载对象完成事件。 + /// + public override void Clear() + { + Resource = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperParseBytesCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperParseBytesCompleteEventArgs.cs.meta new file mode 100644 index 0000000..cad4369 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperParseBytesCompleteEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: da3b1484d29aed049aeddfcba31917d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperReadBytesCompleteEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperReadBytesCompleteEventArgs.cs new file mode 100644 index 0000000..2dbec52 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperReadBytesCompleteEventArgs.cs @@ -0,0 +1,54 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源代理辅助器异步读取资源二进制流完成事件。 + /// + public sealed class LoadResourceAgentHelperReadBytesCompleteEventArgs : GameFrameworkEventArgs + { + private byte[] m_Bytes; + + /// + /// 初始化加载资源代理辅助器异步读取资源二进制流完成事件的新实例。 + /// + public LoadResourceAgentHelperReadBytesCompleteEventArgs() + { + m_Bytes = null; + } + + /// + /// 创建加载资源代理辅助器异步读取资源二进制流完成事件。 + /// + /// 资源的二进制流。 + /// 创建的加载资源代理辅助器异步读取资源二进制流完成事件。 + public static LoadResourceAgentHelperReadBytesCompleteEventArgs Create(byte[] bytes) + { + LoadResourceAgentHelperReadBytesCompleteEventArgs loadResourceAgentHelperReadBytesCompleteEventArgs = ReferencePool.Acquire(); + loadResourceAgentHelperReadBytesCompleteEventArgs.m_Bytes = bytes; + return loadResourceAgentHelperReadBytesCompleteEventArgs; + } + + /// + /// 清理加载资源代理辅助器异步读取资源二进制流完成事件。 + /// + public override void Clear() + { + m_Bytes = null; + } + + /// + /// 获取资源的二进制流。 + /// + /// 资源的二进制流。 + public byte[] GetBytes() + { + return m_Bytes; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperReadBytesCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperReadBytesCompleteEventArgs.cs.meta new file mode 100644 index 0000000..32060ad --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperReadBytesCompleteEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b5ae5dfbc2092c24194accb67b04a534 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperReadFileCompleteEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperReadFileCompleteEventArgs.cs new file mode 100644 index 0000000..62c39ee --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperReadFileCompleteEventArgs.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源代理辅助器异步将资源文件转换为加载对象完成事件。 + /// + public sealed class LoadResourceAgentHelperReadFileCompleteEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化加载资源代理辅助器异步将资源文件转换为加载对象完成事件的新实例。 + /// + public LoadResourceAgentHelperReadFileCompleteEventArgs() + { + Resource = null; + } + + /// + /// 获取加载对象。 + /// + public object Resource + { + get; + private set; + } + + /// + /// 创建加载资源代理辅助器异步将资源文件转换为加载对象完成事件。 + /// + /// 资源对象。 + /// 创建的加载资源代理辅助器异步将资源文件转换为加载对象完成事件。 + public static LoadResourceAgentHelperReadFileCompleteEventArgs Create(object resource) + { + LoadResourceAgentHelperReadFileCompleteEventArgs loadResourceAgentHelperReadFileCompleteEventArgs = ReferencePool.Acquire(); + loadResourceAgentHelperReadFileCompleteEventArgs.Resource = resource; + return loadResourceAgentHelperReadFileCompleteEventArgs; + } + + /// + /// 清理加载资源代理辅助器异步将资源文件转换为加载对象完成事件。 + /// + public override void Clear() + { + Resource = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperReadFileCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperReadFileCompleteEventArgs.cs.meta new file mode 100644 index 0000000..fe54932 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperReadFileCompleteEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c5b241a15eaa2cc44944bb30e9d06c24 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperUpdateEventArgs.cs new file mode 100644 index 0000000..fded812 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperUpdateEventArgs.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源代理辅助器更新事件。 + /// + public sealed class LoadResourceAgentHelperUpdateEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化加载资源代理辅助器更新事件的新实例。 + /// + public LoadResourceAgentHelperUpdateEventArgs() + { + Type = LoadResourceProgress.Unknown; + Progress = 0f; + } + + /// + /// 获取进度类型。 + /// + public LoadResourceProgress Type + { + get; + private set; + } + + /// + /// 获取进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 创建加载资源代理辅助器更新事件。 + /// + /// 进度类型。 + /// 进度。 + /// 创建的加载资源代理辅助器更新事件。 + public static LoadResourceAgentHelperUpdateEventArgs Create(LoadResourceProgress type, float progress) + { + LoadResourceAgentHelperUpdateEventArgs loadResourceAgentHelperUpdateEventArgs = ReferencePool.Acquire(); + loadResourceAgentHelperUpdateEventArgs.Type = type; + loadResourceAgentHelperUpdateEventArgs.Progress = progress; + return loadResourceAgentHelperUpdateEventArgs; + } + + /// + /// 清理加载资源代理辅助器更新事件。 + /// + public override void Clear() + { + Type = LoadResourceProgress.Unknown; + Progress = 0f; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperUpdateEventArgs.cs.meta new file mode 100644 index 0000000..e94c220 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceAgentHelperUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2e1510cd059e5a546b322c507ea78e46 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceProgress.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceProgress.cs new file mode 100644 index 0000000..6293362 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceProgress.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源进度类型。 + /// + public enum LoadResourceProgress : byte + { + /// + /// 未知类型。 + /// + Unknown = 0, + + /// + /// 读取资源包。 + /// + ReadResource, + + /// + /// 加载资源包。 + /// + LoadResource, + + /// + /// 加载资源。 + /// + LoadAsset, + + /// + /// 加载场景。 + /// + LoadScene + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceProgress.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceProgress.cs.meta new file mode 100644 index 0000000..223acb6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceProgress.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b1c2d2946a51a6947acb02068cc6405e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceStatus.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceStatus.cs new file mode 100644 index 0000000..ec8d2cc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceStatus.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载资源状态。 + /// + public enum LoadResourceStatus : byte + { + /// + /// 加载资源完成。 + /// + Success = 0, + + /// + /// 资源不存在。 + /// + NotExist, + + /// + /// 资源尚未准备完毕。 + /// + NotReady, + + /// + /// 依赖资源错误。 + /// + DependencyError, + + /// + /// 资源类型错误。 + /// + TypeError, + + /// + /// 加载资源错误。 + /// + AssetError + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceStatus.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceStatus.cs.meta new file mode 100644 index 0000000..c298ad8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadResourceStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e7789b800ae94a24e85b3a0b8f1960e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneCallbacks.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneCallbacks.cs new file mode 100644 index 0000000..bbccf88 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneCallbacks.cs @@ -0,0 +1,145 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载场景回调函数集。 + /// + public sealed class LoadSceneCallbacks + { + private readonly LoadSceneSuccessCallback m_LoadSceneSuccessCallback; + private readonly LoadSceneFailureCallback m_LoadSceneFailureCallback; + private readonly LoadSceneUpdateCallback m_LoadSceneUpdateCallback; + private readonly LoadSceneDependencyAssetCallback m_LoadSceneDependencyAssetCallback; + + /// + /// 初始化加载场景回调函数集的新实例。 + /// + /// 加载场景成功回调函数。 + public LoadSceneCallbacks(LoadSceneSuccessCallback loadSceneSuccessCallback) + : this(loadSceneSuccessCallback, null, null, null) + { + } + + /// + /// 初始化加载场景回调函数集的新实例。 + /// + /// 加载场景成功回调函数。 + /// 加载场景失败回调函数。 + public LoadSceneCallbacks(LoadSceneSuccessCallback loadSceneSuccessCallback, LoadSceneFailureCallback loadSceneFailureCallback) + : this(loadSceneSuccessCallback, loadSceneFailureCallback, null, null) + { + } + + /// + /// 初始化加载场景回调函数集的新实例。 + /// + /// 加载场景成功回调函数。 + /// 加载场景更新回调函数。 + public LoadSceneCallbacks(LoadSceneSuccessCallback loadSceneSuccessCallback, LoadSceneUpdateCallback loadSceneUpdateCallback) + : this(loadSceneSuccessCallback, null, loadSceneUpdateCallback, null) + { + } + + /// + /// 初始化加载场景回调函数集的新实例。 + /// + /// 加载场景成功回调函数。 + /// 加载场景时加载依赖资源回调函数。 + public LoadSceneCallbacks(LoadSceneSuccessCallback loadSceneSuccessCallback, LoadSceneDependencyAssetCallback loadSceneDependencyAssetCallback) + : this(loadSceneSuccessCallback, null, null, loadSceneDependencyAssetCallback) + { + } + + /// + /// 初始化加载场景回调函数集的新实例。 + /// + /// 加载场景成功回调函数。 + /// 加载场景失败回调函数。 + /// 加载场景更新回调函数。 + public LoadSceneCallbacks(LoadSceneSuccessCallback loadSceneSuccessCallback, LoadSceneFailureCallback loadSceneFailureCallback, LoadSceneUpdateCallback loadSceneUpdateCallback) + : this(loadSceneSuccessCallback, loadSceneFailureCallback, loadSceneUpdateCallback, null) + { + } + + /// + /// 初始化加载场景回调函数集的新实例。 + /// + /// 加载场景成功回调函数。 + /// 加载场景失败回调函数。 + /// 加载场景时加载依赖资源回调函数。 + public LoadSceneCallbacks(LoadSceneSuccessCallback loadSceneSuccessCallback, LoadSceneFailureCallback loadSceneFailureCallback, LoadSceneDependencyAssetCallback loadSceneDependencyAssetCallback) + : this(loadSceneSuccessCallback, loadSceneFailureCallback, null, loadSceneDependencyAssetCallback) + { + } + + /// + /// 初始化加载场景回调函数集的新实例。 + /// + /// 加载场景成功回调函数。 + /// 加载场景失败回调函数。 + /// 加载场景更新回调函数。 + /// 加载场景时加载依赖资源回调函数。 + public LoadSceneCallbacks(LoadSceneSuccessCallback loadSceneSuccessCallback, LoadSceneFailureCallback loadSceneFailureCallback, LoadSceneUpdateCallback loadSceneUpdateCallback, LoadSceneDependencyAssetCallback loadSceneDependencyAssetCallback) + { + if (loadSceneSuccessCallback == null) + { + throw new GameFrameworkException("Load scene success callback is invalid."); + } + + m_LoadSceneSuccessCallback = loadSceneSuccessCallback; + m_LoadSceneFailureCallback = loadSceneFailureCallback; + m_LoadSceneUpdateCallback = loadSceneUpdateCallback; + m_LoadSceneDependencyAssetCallback = loadSceneDependencyAssetCallback; + } + + /// + /// 获取加载场景成功回调函数。 + /// + public LoadSceneSuccessCallback LoadSceneSuccessCallback + { + get + { + return m_LoadSceneSuccessCallback; + } + } + + /// + /// 获取加载场景失败回调函数。 + /// + public LoadSceneFailureCallback LoadSceneFailureCallback + { + get + { + return m_LoadSceneFailureCallback; + } + } + + /// + /// 获取加载场景更新回调函数。 + /// + public LoadSceneUpdateCallback LoadSceneUpdateCallback + { + get + { + return m_LoadSceneUpdateCallback; + } + } + + /// + /// 获取加载场景时加载依赖资源回调函数。 + /// + public LoadSceneDependencyAssetCallback LoadSceneDependencyAssetCallback + { + get + { + return m_LoadSceneDependencyAssetCallback; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneCallbacks.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneCallbacks.cs.meta new file mode 100644 index 0000000..77ff4f1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneCallbacks.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5525ac1816e1f1845aabe4f837b1ff50 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneDependencyAssetCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneDependencyAssetCallback.cs new file mode 100644 index 0000000..17787a6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneDependencyAssetCallback.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载场景时加载依赖资源回调函数。 + /// + /// 要加载的场景资源名称。 + /// 被加载的依赖资源名称。 + /// 当前已加载依赖资源数量。 + /// 总共加载依赖资源数量。 + /// 用户自定义数据。 + public delegate void LoadSceneDependencyAssetCallback(string sceneAssetName, string dependencyAssetName, int loadedCount, int totalCount, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneDependencyAssetCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneDependencyAssetCallback.cs.meta new file mode 100644 index 0000000..8a2099f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneDependencyAssetCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 023c8a7245911b24696233abe6371d2a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneFailureCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneFailureCallback.cs new file mode 100644 index 0000000..4618031 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneFailureCallback.cs @@ -0,0 +1,18 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载场景失败回调函数。 + /// + /// 要加载的场景资源名称。 + /// 加载场景状态。 + /// 错误信息。 + /// 用户自定义数据。 + public delegate void LoadSceneFailureCallback(string sceneAssetName, LoadResourceStatus status, string errorMessage, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneFailureCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneFailureCallback.cs.meta new file mode 100644 index 0000000..5eccdf6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneFailureCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9077a5c3d364bea418216f6f09655127 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneSuccessCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneSuccessCallback.cs new file mode 100644 index 0000000..3fefc8a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneSuccessCallback.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载场景成功回调函数。 + /// + /// 要加载的场景资源名称。 + /// 加载持续时间。 + /// 用户自定义数据。 + public delegate void LoadSceneSuccessCallback(string sceneAssetName, float duration, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneSuccessCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneSuccessCallback.cs.meta new file mode 100644 index 0000000..712808f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneSuccessCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3d21d00ba1a130f49b33e4b598417355 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneUpdateCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneUpdateCallback.cs new file mode 100644 index 0000000..bfd5d7c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneUpdateCallback.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 加载场景更新回调函数。 + /// + /// 要加载的场景资源名称。 + /// 加载场景进度。 + /// 用户自定义数据。 + public delegate void LoadSceneUpdateCallback(string sceneAssetName, float progress, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneUpdateCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneUpdateCallback.cs.meta new file mode 100644 index 0000000..742141d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LoadSceneUpdateCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9ca48f93df40e6d45933f817943298d6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.FileSystem.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.FileSystem.cs new file mode 100644 index 0000000..7052cd0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.FileSystem.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + public partial struct LocalVersionList + { + /// + /// 文件系统。 + /// + [StructLayout(LayoutKind.Auto)] + public struct FileSystem + { + private static readonly int[] EmptyIntArray = new int[] { }; + + private readonly string m_Name; + private readonly int[] m_ResourceIndexes; + + /// + /// 初始化文件系统的新实例。 + /// + /// 文件系统名称。 + /// 文件系统包含的资源索引集合。 + public FileSystem(string name, int[] resourceIndexes) + { + if (name == null) + { + throw new GameFrameworkException("Name is invalid."); + } + + m_Name = name; + m_ResourceIndexes = resourceIndexes ?? EmptyIntArray; + } + + /// + /// 获取文件系统名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取文件系统包含的资源索引集合。 + /// + /// 文件系统包含的资源索引集合。 + public int[] GetResourceIndexes() + { + return m_ResourceIndexes; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.FileSystem.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.FileSystem.cs.meta new file mode 100644 index 0000000..da33378 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.FileSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ab4b9fefcd410fc4995cb00de14dfc2c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.Resource.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.Resource.cs new file mode 100644 index 0000000..945ebb7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.Resource.cs @@ -0,0 +1,118 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + public partial struct LocalVersionList + { + /// + /// 资源。 + /// + [StructLayout(LayoutKind.Auto)] + public struct Resource + { + private readonly string m_Name; + private readonly string m_Variant; + private readonly string m_Extension; + private readonly byte m_LoadType; + private readonly int m_Length; + private readonly int m_HashCode; + + /// + /// 初始化资源的新实例。 + /// + /// 资源名称。 + /// 资源变体名称。 + /// 资源扩展名称。 + /// 资源加载方式。 + /// 资源长度。 + /// 资源哈希值。 + public Resource(string name, string variant, string extension, byte loadType, int length, int hashCode) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + m_Name = name; + m_Variant = variant; + m_Extension = extension; + m_LoadType = loadType; + m_Length = length; + m_HashCode = hashCode; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取资源变体名称。 + /// + public string Variant + { + get + { + return m_Variant; + } + } + + /// + /// 获取资源扩展名称。 + /// + public string Extension + { + get + { + return m_Extension; + } + } + + /// + /// 获取资源加载方式。 + /// + public byte LoadType + { + get + { + return m_LoadType; + } + } + + /// + /// 获取资源长度。 + /// + public int Length + { + get + { + return m_Length; + } + } + + /// + /// 获取资源哈希值。 + /// + public int HashCode + { + get + { + return m_HashCode; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.Resource.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.Resource.cs.meta new file mode 100644 index 0000000..9a13f24 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.Resource.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3088ab3f3ff38df41a91100ec56a4c1b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.cs new file mode 100644 index 0000000..bfeafbc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.cs @@ -0,0 +1,76 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + /// + /// 本地版本资源列表。 + /// + [StructLayout(LayoutKind.Auto)] + public partial struct LocalVersionList + { + private static readonly Resource[] EmptyResourceArray = new Resource[] { }; + private static readonly FileSystem[] EmptyFileSystemArray = new FileSystem[] { }; + + private readonly bool m_IsValid; + private readonly Resource[] m_Resources; + private readonly FileSystem[] m_FileSystems; + + /// + /// 初始化本地版本资源列表的新实例。 + /// + /// 包含的资源集合。 + /// 包含的文件系统集合。 + public LocalVersionList(Resource[] resources, FileSystem[] fileSystems) + { + m_IsValid = true; + m_Resources = resources ?? EmptyResourceArray; + m_FileSystems = fileSystems ?? EmptyFileSystemArray; + } + + /// + /// 获取本地版本资源列表是否有效。 + /// + public bool IsValid + { + get + { + return m_IsValid; + } + } + + /// + /// 获取包含的资源集合。 + /// + /// 包含的资源集合。 + public Resource[] GetResources() + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_Resources; + } + + /// + /// 获取包含的文件系统集合。 + /// + /// 包含的文件系统集合。 + public FileSystem[] GetFileSystems() + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_FileSystems; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.cs.meta new file mode 100644 index 0000000..789e429 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/LocalVersionList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 96f54073a71bbd84ebe6a4bb2d652a05 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.Asset.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.Asset.cs new file mode 100644 index 0000000..2f35aa6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.Asset.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + public partial struct PackageVersionList + { + /// + /// 资源。 + /// + [StructLayout(LayoutKind.Auto)] + public struct Asset + { + private static readonly int[] EmptyIntArray = new int[] { }; + + private readonly string m_Name; + private readonly int[] m_DependencyAssetIndexes; + + /// + /// 初始化资源的新实例。 + /// + /// 资源名称。 + /// 资源包含的依赖资源索引集合。 + public Asset(string name, int[] dependencyAssetIndexes) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + m_Name = name; + m_DependencyAssetIndexes = dependencyAssetIndexes ?? EmptyIntArray; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取资源包含的依赖资源索引集合。 + /// + /// 资源包含的依赖资源索引集合。 + public int[] GetDependencyAssetIndexes() + { + return m_DependencyAssetIndexes; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.Asset.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.Asset.cs.meta new file mode 100644 index 0000000..6fd166b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.Asset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1c9e5247d2b8c234fb66e6c11d249ca6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.FileSystem.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.FileSystem.cs new file mode 100644 index 0000000..25e577c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.FileSystem.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + public partial struct PackageVersionList + { + /// + /// 文件系统。 + /// + [StructLayout(LayoutKind.Auto)] + public struct FileSystem + { + private static readonly int[] EmptyIntArray = new int[] { }; + + private readonly string m_Name; + private readonly int[] m_ResourceIndexes; + + /// + /// 初始化文件系统的新实例。 + /// + /// 文件系统名称。 + /// 文件系统包含的资源索引集合。 + public FileSystem(string name, int[] resourceIndexes) + { + if (name == null) + { + throw new GameFrameworkException("Name is invalid."); + } + + m_Name = name; + m_ResourceIndexes = resourceIndexes ?? EmptyIntArray; + } + + /// + /// 获取文件系统名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取文件系统包含的资源索引集合。 + /// + /// 文件系统包含的资源索引集合。 + public int[] GetResourceIndexes() + { + return m_ResourceIndexes; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.FileSystem.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.FileSystem.cs.meta new file mode 100644 index 0000000..9f5eac1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.FileSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 005ba6014d1d6b84a96404980a310779 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.Resource.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.Resource.cs new file mode 100644 index 0000000..e2f7beb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.Resource.cs @@ -0,0 +1,132 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + public partial struct PackageVersionList + { + /// + /// 资源。 + /// + [StructLayout(LayoutKind.Auto)] + public struct Resource + { + private static readonly int[] EmptyIntArray = new int[] { }; + + private readonly string m_Name; + private readonly string m_Variant; + private readonly string m_Extension; + private readonly byte m_LoadType; + private readonly int m_Length; + private readonly int m_HashCode; + private readonly int[] m_AssetIndexes; + + /// + /// 初始化资源的新实例。 + /// + /// 资源名称。 + /// 资源变体名称。 + /// 资源扩展名称。 + /// 资源加载方式。 + /// 资源长度。 + /// 资源哈希值。 + /// 资源包含的资源索引集合。 + public Resource(string name, string variant, string extension, byte loadType, int length, int hashCode, int[] assetIndexes) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + m_Name = name; + m_Variant = variant; + m_Extension = extension; + m_LoadType = loadType; + m_Length = length; + m_HashCode = hashCode; + m_AssetIndexes = assetIndexes ?? EmptyIntArray; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取资源变体名称。 + /// + public string Variant + { + get + { + return m_Variant; + } + } + + /// + /// 获取资源扩展名称。 + /// + public string Extension + { + get + { + return m_Extension; + } + } + + /// + /// 获取资源加载方式。 + /// + public byte LoadType + { + get + { + return m_LoadType; + } + } + + /// + /// 获取资源长度。 + /// + public int Length + { + get + { + return m_Length; + } + } + + /// + /// 获取资源哈希值。 + /// + public int HashCode + { + get + { + return m_HashCode; + } + } + + /// + /// 获取资源包含的资源索引集合。 + /// + /// 资源包含的资源索引集合。 + public int[] GetAssetIndexes() + { + return m_AssetIndexes; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.Resource.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.Resource.cs.meta new file mode 100644 index 0000000..3df6bab --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.Resource.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6f3089363b160d74ea1a59e500eef66a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.ResourceGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.ResourceGroup.cs new file mode 100644 index 0000000..630ba68 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.ResourceGroup.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + public partial struct PackageVersionList + { + /// + /// 资源组。 + /// + [StructLayout(LayoutKind.Auto)] + public struct ResourceGroup + { + private static readonly int[] EmptyIntArray = new int[] { }; + + private readonly string m_Name; + private readonly int[] m_ResourceIndexes; + + /// + /// 初始化资源组的新实例。 + /// + /// 资源组名称。 + /// 资源组包含的资源索引集合。 + public ResourceGroup(string name, int[] resourceIndexes) + { + if (name == null) + { + throw new GameFrameworkException("Name is invalid."); + } + + m_Name = name; + m_ResourceIndexes = resourceIndexes ?? EmptyIntArray; + } + + /// + /// 获取资源组名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取资源组包含的资源索引集合。 + /// + /// 资源组包含的资源索引集合。 + public int[] GetResourceIndexes() + { + return m_ResourceIndexes; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.ResourceGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.ResourceGroup.cs.meta new file mode 100644 index 0000000..27f9e73 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.ResourceGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 231ad5750b30fa340a72cb89f9911e4e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.cs new file mode 100644 index 0000000..cb1fca5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.cs @@ -0,0 +1,150 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + /// + /// 单机模式版本资源列表。 + /// + [StructLayout(LayoutKind.Auto)] + public partial struct PackageVersionList + { + private static readonly Asset[] EmptyAssetArray = new Asset[] { }; + private static readonly Resource[] EmptyResourceArray = new Resource[] { }; + private static readonly FileSystem[] EmptyFileSystemArray = new FileSystem[] { }; + private static readonly ResourceGroup[] EmptyResourceGroupArray = new ResourceGroup[] { }; + + private readonly bool m_IsValid; + private readonly string m_ApplicableGameVersion; + private readonly int m_InternalResourceVersion; + private readonly Asset[] m_Assets; + private readonly Resource[] m_Resources; + private readonly FileSystem[] m_FileSystems; + private readonly ResourceGroup[] m_ResourceGroups; + + /// + /// 初始化单机模式版本资源列表的新实例。 + /// + /// 适配的游戏版本号。 + /// 内部资源版本号。 + /// 包含的资源集合。 + /// 包含的资源集合。 + /// 包含的文件系统集合。 + /// 包含的资源组集合。 + public PackageVersionList(string applicableGameVersion, int internalResourceVersion, Asset[] assets, Resource[] resources, FileSystem[] fileSystems, ResourceGroup[] resourceGroups) + { + m_IsValid = true; + m_ApplicableGameVersion = applicableGameVersion; + m_InternalResourceVersion = internalResourceVersion; + m_Assets = assets ?? EmptyAssetArray; + m_Resources = resources ?? EmptyResourceArray; + m_FileSystems = fileSystems ?? EmptyFileSystemArray; + m_ResourceGroups = resourceGroups ?? EmptyResourceGroupArray; + } + + /// + /// 获取单机模式版本资源列表是否有效。 + /// + public bool IsValid + { + get + { + return m_IsValid; + } + } + + /// + /// 获取适配的游戏版本号。 + /// + public string ApplicableGameVersion + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_ApplicableGameVersion; + } + } + + /// + /// 获取内部资源版本号。 + /// + public int InternalResourceVersion + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_InternalResourceVersion; + } + } + + /// + /// 获取包含的资源集合。 + /// + /// 包含的资源集合。 + public Asset[] GetAssets() + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_Assets; + } + + /// + /// 获取包含的资源集合。 + /// + /// 包含的资源集合。 + public Resource[] GetResources() + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_Resources; + } + + /// + /// 获取包含的文件系统集合。 + /// + /// 包含的文件系统集合。 + public FileSystem[] GetFileSystems() + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_FileSystems; + } + + /// + /// 获取包含的资源组集合。 + /// + /// 包含的资源组集合。 + public ResourceGroup[] GetResourceGroups() + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_ResourceGroups; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.cs.meta new file mode 100644 index 0000000..2bc8e96 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d5e53fcb4372f2d47ae1e6ecc270f6e8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionListSerializer.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionListSerializer.cs new file mode 100644 index 0000000..9038174 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionListSerializer.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 单机模式版本资源列表序列化器。 + /// + public sealed class PackageVersionListSerializer : GameFrameworkSerializer + { + private static readonly byte[] Header = new byte[] { (byte)'G', (byte)'F', (byte)'P' }; + + /// + /// 初始化单机模式版本资源列表序列化器的新实例。 + /// + public PackageVersionListSerializer() + { + } + + /// + /// 获取单机模式版本资源列表头标识。 + /// + /// 单机模式版本资源列表头标识。 + protected override byte[] GetHeader() + { + return Header; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionListSerializer.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionListSerializer.cs.meta new file mode 100644 index 0000000..bbd87fb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/PackageVersionListSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d1b4d29b939c45145b82e040105fa8c8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ReadOnlyVersionListSerializer.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ReadOnlyVersionListSerializer.cs new file mode 100644 index 0000000..6defb90 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ReadOnlyVersionListSerializer.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 本地只读区版本资源列表序列化器。 + /// + public sealed class ReadOnlyVersionListSerializer : GameFrameworkSerializer + { + private static readonly byte[] Header = new byte[] { (byte)'G', (byte)'F', (byte)'R' }; + + /// + /// 初始化本地只读区版本资源列表序列化器的新实例。 + /// + public ReadOnlyVersionListSerializer() + { + } + + /// + /// 获取本地只读区版本资源列表头标识。 + /// + /// 本地只读区版本资源列表头标识。 + protected override byte[] GetHeader() + { + return Header; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ReadOnlyVersionListSerializer.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ReadOnlyVersionListSerializer.cs.meta new file mode 100644 index 0000000..9bd3003 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ReadOnlyVersionListSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e9df2e7fdb235ea41ae67dc1278526b7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ReadWriteVersionListSerializer.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ReadWriteVersionListSerializer.cs new file mode 100644 index 0000000..1c902ed --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ReadWriteVersionListSerializer.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 本地读写区版本资源列表序列化器。 + /// + public sealed class ReadWriteVersionListSerializer : GameFrameworkSerializer + { + private static readonly byte[] Header = new byte[] { (byte)'G', (byte)'F', (byte)'W' }; + + /// + /// 初始化本地读写区版本资源列表序列化器的新实例。 + /// + public ReadWriteVersionListSerializer() + { + } + + /// + /// 获取本地读写区版本资源列表头标识。 + /// + /// 本地读写区版本资源列表头标识。 + protected override byte[] GetHeader() + { + return Header; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ReadWriteVersionListSerializer.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ReadWriteVersionListSerializer.cs.meta new file mode 100644 index 0000000..5b9d641 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ReadWriteVersionListSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d293be354d6aff6429b6418f6918278f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplyFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplyFailureEventArgs.cs new file mode 100644 index 0000000..5ca3bef --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplyFailureEventArgs.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源应用失败事件。 + /// + public sealed class ResourceApplyFailureEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化资源应用失败事件的新实例。 + /// + public ResourceApplyFailureEventArgs() + { + Name = null; + ResourcePackPath = null; + ErrorMessage = null; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取资源包路径。 + /// + public string ResourcePackPath + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 创建资源应用失败事件。 + /// + /// 资源名称。 + /// 资源包路径。 + /// 错误信息。 + /// 创建的资源应用失败事件。 + public static ResourceApplyFailureEventArgs Create(string name, string resourcePackPath, string errorMessage) + { + ResourceApplyFailureEventArgs resourceApplyFailureEventArgs = ReferencePool.Acquire(); + resourceApplyFailureEventArgs.Name = name; + resourceApplyFailureEventArgs.ResourcePackPath = resourcePackPath; + resourceApplyFailureEventArgs.ErrorMessage = errorMessage; + return resourceApplyFailureEventArgs; + } + + /// + /// 清理资源应用失败事件。 + /// + public override void Clear() + { + Name = null; + ResourcePackPath = null; + ErrorMessage = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplyFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplyFailureEventArgs.cs.meta new file mode 100644 index 0000000..cf5c442 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplyFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 20d2dfd031d751f45b076a4947ef2cc0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplyStartEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplyStartEventArgs.cs new file mode 100644 index 0000000..f3876d1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplyStartEventArgs.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源应用开始事件。 + /// + public sealed class ResourceApplyStartEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化资源应用开始事件的新实例。 + /// + public ResourceApplyStartEventArgs() + { + ResourcePackPath = null; + Count = 0; + TotalLength = 0L; + } + + /// + /// 获取资源包路径。 + /// + public string ResourcePackPath + { + get; + private set; + } + + /// + /// 获取要应用资源的数量。 + /// + public int Count + { + get; + private set; + } + + /// + /// 获取要应用资源的总大小。 + /// + public long TotalLength + { + get; + private set; + } + + /// + /// 创建资源应用开始事件。 + /// + /// 资源包路径。 + /// 要应用资源的数量。 + /// 要应用资源的总大小。 + /// 创建的资源应用开始事件。 + public static ResourceApplyStartEventArgs Create(string resourcePackPath, int count, long totalLength) + { + ResourceApplyStartEventArgs resourceApplyStartEventArgs = ReferencePool.Acquire(); + resourceApplyStartEventArgs.ResourcePackPath = resourcePackPath; + resourceApplyStartEventArgs.Count = count; + resourceApplyStartEventArgs.TotalLength = totalLength; + return resourceApplyStartEventArgs; + } + + /// + /// 清理资源应用开始事件。 + /// + public override void Clear() + { + ResourcePackPath = null; + Count = 0; + TotalLength = 0L; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplyStartEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplyStartEventArgs.cs.meta new file mode 100644 index 0000000..803c715 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplyStartEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 768c9181bf35bfd4cb58405d11b7ffcc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplySuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplySuccessEventArgs.cs new file mode 100644 index 0000000..a73a332 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplySuccessEventArgs.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源应用成功事件。 + /// + public sealed class ResourceApplySuccessEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化资源应用成功事件的新实例。 + /// + public ResourceApplySuccessEventArgs() + { + Name = null; + ApplyPath = null; + ResourcePackPath = null; + Length = 0; + CompressedLength = 0; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取资源应用后存放路径。 + /// + public string ApplyPath + { + get; + private set; + } + + /// + /// 获取资源包路径。 + /// + public string ResourcePackPath + { + get; + private set; + } + + /// + /// 获取资源大小。 + /// + public int Length + { + get; + private set; + } + + /// + /// 获取压缩后大小。 + /// + public int CompressedLength + { + get; + private set; + } + + /// + /// 创建资源应用成功事件。 + /// + /// 资源名称。 + /// 资源应用后存放路径。 + /// 资源包路径。 + /// 资源大小。 + /// 压缩后大小。 + /// 创建的资源应用成功事件。 + public static ResourceApplySuccessEventArgs Create(string name, string applyPath, string resourcePackPath, int length, int compressedLength) + { + ResourceApplySuccessEventArgs resourceApplySuccessEventArgs = ReferencePool.Acquire(); + resourceApplySuccessEventArgs.Name = name; + resourceApplySuccessEventArgs.ApplyPath = applyPath; + resourceApplySuccessEventArgs.ResourcePackPath = resourcePackPath; + resourceApplySuccessEventArgs.Length = length; + resourceApplySuccessEventArgs.CompressedLength = compressedLength; + return resourceApplySuccessEventArgs; + } + + /// + /// 清理资源应用成功事件。 + /// + public override void Clear() + { + Name = null; + ApplyPath = null; + ResourcePackPath = null; + Length = 0; + CompressedLength = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplySuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplySuccessEventArgs.cs.meta new file mode 100644 index 0000000..5d589fc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceApplySuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 153f8f2935dc18742bd4781344e46d6f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.AssetInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.AssetInfo.cs new file mode 100644 index 0000000..6785c2e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.AssetInfo.cs @@ -0,0 +1,66 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 资源信息。 + /// + private sealed class AssetInfo + { + private readonly string m_AssetName; + private readonly ResourceName m_ResourceName; + private readonly string[] m_DependencyAssetNames; + + /// + /// 初始化资源信息的新实例。 + /// + /// 资源名称。 + /// 所在资源名称。 + /// 依赖资源名称。 + public AssetInfo(string assetName, ResourceName resourceName, string[] dependencyAssetNames) + { + m_AssetName = assetName; + m_ResourceName = resourceName; + m_DependencyAssetNames = dependencyAssetNames; + } + + /// + /// 获取资源名称。 + /// + public string AssetName + { + get + { + return m_AssetName; + } + } + + /// + /// 获取所在资源名称。 + /// + public ResourceName ResourceName + { + get + { + return m_ResourceName; + } + } + + /// + /// 获取依赖资源名称。 + /// + /// 依赖资源名称。 + public string[] GetDependencyAssetNames() + { + return m_DependencyAssetNames; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.AssetInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.AssetInfo.cs.meta new file mode 100644 index 0000000..a09e055 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.AssetInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1633c7761e28c684ba95f6de18754a11 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.LoadType.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.LoadType.cs new file mode 100644 index 0000000..43825af --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.LoadType.cs @@ -0,0 +1,53 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 资源加载方式类型。 + /// + private enum LoadType : byte + { + /// + /// 使用文件方式加载。 + /// + LoadFromFile = 0, + + /// + /// 使用内存方式加载。 + /// + LoadFromMemory, + + /// + /// 使用内存快速解密方式加载。 + /// + LoadFromMemoryAndQuickDecrypt, + + /// + /// 使用内存解密方式加载。 + /// + LoadFromMemoryAndDecrypt, + + /// + /// 使用二进制方式加载。 + /// + LoadFromBinary, + + /// + /// 使用二进制快速解密方式加载。 + /// + LoadFromBinaryAndQuickDecrypt, + + /// + /// 使用二进制解密方式加载。 + /// + LoadFromBinaryAndDecrypt + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.LoadType.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.LoadType.cs.meta new file mode 100644 index 0000000..f0831cb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.LoadType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f80a78eb134c7b54c9689ef5f576d060 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ReadWriteResourceInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ReadWriteResourceInfo.cs new file mode 100644 index 0000000..d349fb2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ReadWriteResourceInfo.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + [StructLayout(LayoutKind.Auto)] + private struct ReadWriteResourceInfo + { + private readonly string m_FileSystemName; + private readonly LoadType m_LoadType; + private readonly int m_Length; + private readonly int m_HashCode; + + public ReadWriteResourceInfo(string fileSystemName, LoadType loadType, int length, int hashCode) + { + m_FileSystemName = fileSystemName; + m_LoadType = loadType; + m_Length = length; + m_HashCode = hashCode; + } + + public bool UseFileSystem + { + get + { + return !string.IsNullOrEmpty(m_FileSystemName); + } + } + + public string FileSystemName + { + get + { + return m_FileSystemName; + } + } + + public LoadType LoadType + { + get + { + return m_LoadType; + } + } + + public int Length + { + get + { + return m_Length; + } + } + + public int HashCode + { + get + { + return m_HashCode; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ReadWriteResourceInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ReadWriteResourceInfo.cs.meta new file mode 100644 index 0000000..aa1c9d8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ReadWriteResourceInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5df9583e4b16e6a4689994eb8b4274c5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.CheckStatus.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.CheckStatus.cs new file mode 100644 index 0000000..5ab17ee --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.CheckStatus.cs @@ -0,0 +1,54 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceChecker + { + private sealed partial class CheckInfo + { + /// + /// 资源检查状态。 + /// + public enum CheckStatus : byte + { + /// + /// 资源状态未知。 + /// + Unknown = 0, + + /// + /// 资源存在且已存放于只读区中。 + /// + StorageInReadOnly, + + /// + /// 资源存在且已存放于读写区中。 + /// + StorageInReadWrite, + + /// + /// 资源不适用于当前变体。 + /// + Unavailable, + + /// + /// 资源需要更新。 + /// + Update, + + /// + /// 资源已废弃。 + /// + Disuse + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.CheckStatus.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.CheckStatus.cs.meta new file mode 100644 index 0000000..24ace59 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.CheckStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9023ed109aaff4f4597d3f65cd5fe728 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.LocalVersionInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.LocalVersionInfo.cs new file mode 100644 index 0000000..4f22410 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.LocalVersionInfo.cs @@ -0,0 +1,90 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceChecker + { + private sealed partial class CheckInfo + { + /// + /// 本地资源状态信息。 + /// + [StructLayout(LayoutKind.Auto)] + private struct LocalVersionInfo + { + private readonly bool m_Exist; + private readonly string m_FileSystemName; + private readonly LoadType m_LoadType; + private readonly int m_Length; + private readonly int m_HashCode; + + public LocalVersionInfo(string fileSystemName, LoadType loadType, int length, int hashCode) + { + m_Exist = true; + m_FileSystemName = fileSystemName; + m_LoadType = loadType; + m_Length = length; + m_HashCode = hashCode; + } + + public bool Exist + { + get + { + return m_Exist; + } + } + + public bool UseFileSystem + { + get + { + return !string.IsNullOrEmpty(m_FileSystemName); + } + } + + public string FileSystemName + { + get + { + return m_FileSystemName; + } + } + + public LoadType LoadType + { + get + { + return m_LoadType; + } + } + + public int Length + { + get + { + return m_Length; + } + } + + public int HashCode + { + get + { + return m_HashCode; + } + } + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.LocalVersionInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.LocalVersionInfo.cs.meta new file mode 100644 index 0000000..e750697 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.LocalVersionInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ca0996f92a26ed847ae157c9b17d2493 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.RemoteVersionInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.RemoteVersionInfo.cs new file mode 100644 index 0000000..52bb19e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.RemoteVersionInfo.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceChecker + { + private sealed partial class CheckInfo + { + /// + /// 远程资源状态信息。 + /// + [StructLayout(LayoutKind.Auto)] + private struct RemoteVersionInfo + { + private readonly bool m_Exist; + private readonly string m_FileSystemName; + private readonly LoadType m_LoadType; + private readonly int m_Length; + private readonly int m_HashCode; + private readonly int m_CompressedLength; + private readonly int m_CompressedHashCode; + + public RemoteVersionInfo(string fileSystemName, LoadType loadType, int length, int hashCode, int compressedLength, int compressedHashCode) + { + m_Exist = true; + m_FileSystemName = fileSystemName; + m_LoadType = loadType; + m_Length = length; + m_HashCode = hashCode; + m_CompressedLength = compressedLength; + m_CompressedHashCode = compressedHashCode; + } + + public bool Exist + { + get + { + return m_Exist; + } + } + + public bool UseFileSystem + { + get + { + return !string.IsNullOrEmpty(m_FileSystemName); + } + } + + public string FileSystemName + { + get + { + return m_FileSystemName; + } + } + + public LoadType LoadType + { + get + { + return m_LoadType; + } + } + + public int Length + { + get + { + return m_Length; + } + } + + public int HashCode + { + get + { + return m_HashCode; + } + } + + public int CompressedLength + { + get + { + return m_CompressedLength; + } + } + + public int CompressedHashCode + { + get + { + return m_CompressedHashCode; + } + } + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.RemoteVersionInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.RemoteVersionInfo.cs.meta new file mode 100644 index 0000000..0ffe6c0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.RemoteVersionInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: add43398f3488a34889bbaf753a6a4ac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.cs new file mode 100644 index 0000000..683f808 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.cs @@ -0,0 +1,294 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceChecker + { + /// + /// 资源检查信息。 + /// + private sealed partial class CheckInfo + { + private readonly ResourceName m_ResourceName; + private CheckStatus m_Status; + private bool m_NeedRemove; + private bool m_NeedMoveToDisk; + private bool m_NeedMoveToFileSystem; + private RemoteVersionInfo m_VersionInfo; + private LocalVersionInfo m_ReadOnlyInfo; + private LocalVersionInfo m_ReadWriteInfo; + private string m_CachedFileSystemName; + + /// + /// 初始化资源检查信息的新实例。 + /// + /// 资源名称。 + public CheckInfo(ResourceName resourceName) + { + m_ResourceName = resourceName; + m_Status = CheckStatus.Unknown; + m_NeedRemove = false; + m_NeedMoveToDisk = false; + m_NeedMoveToFileSystem = false; + m_VersionInfo = default(RemoteVersionInfo); + m_ReadOnlyInfo = default(LocalVersionInfo); + m_ReadWriteInfo = default(LocalVersionInfo); + m_CachedFileSystemName = null; + } + + /// + /// 获取资源名称。 + /// + public ResourceName ResourceName + { + get + { + return m_ResourceName; + } + } + + /// + /// 获取资源检查状态。 + /// + public CheckStatus Status + { + get + { + return m_Status; + } + } + + /// + /// 获取是否需要移除读写区的资源。 + /// + public bool NeedRemove + { + get + { + return m_NeedRemove; + } + } + + /// + /// 获取是否需要将读写区的资源移动到磁盘。 + /// + public bool NeedMoveToDisk + { + get + { + return m_NeedMoveToDisk; + } + } + + /// + /// 获取是否需要将读写区的资源移动到文件系统。 + /// + public bool NeedMoveToFileSystem + { + get + { + return m_NeedMoveToFileSystem; + } + } + + /// + /// 获取资源所在的文件系统名称。 + /// + public string FileSystemName + { + get + { + return m_VersionInfo.FileSystemName; + } + } + + /// + /// 获取资源是否使用文件系统。 + /// + public bool ReadWriteUseFileSystem + { + get + { + return m_ReadWriteInfo.UseFileSystem; + } + } + + /// + /// 获取读写资源所在的文件系统名称。 + /// + public string ReadWriteFileSystemName + { + get + { + return m_ReadWriteInfo.FileSystemName; + } + } + + /// + /// 获取资源加载方式。 + /// + public LoadType LoadType + { + get + { + return m_VersionInfo.LoadType; + } + } + + /// + /// 获取资源大小。 + /// + public int Length + { + get + { + return m_VersionInfo.Length; + } + } + + /// + /// 获取资源哈希值。 + /// + public int HashCode + { + get + { + return m_VersionInfo.HashCode; + } + } + + /// + /// 获取压缩后大小。 + /// + public int CompressedLength + { + get + { + return m_VersionInfo.CompressedLength; + } + } + + /// + /// 获取压缩后哈希值。 + /// + public int CompressedHashCode + { + get + { + return m_VersionInfo.CompressedHashCode; + } + } + + /// + /// 临时缓存资源所在的文件系统名称。 + /// + /// 资源所在的文件系统名称。 + public void SetCachedFileSystemName(string fileSystemName) + { + m_CachedFileSystemName = fileSystemName; + } + + /// + /// 设置资源在版本中的信息。 + /// + /// 资源加载方式。 + /// 资源大小。 + /// 资源哈希值。 + /// 压缩后大小。 + /// 压缩后哈希值。 + public void SetVersionInfo(LoadType loadType, int length, int hashCode, int compressedLength, int compressedHashCode) + { + if (m_VersionInfo.Exist) + { + throw new GameFrameworkException(Utility.Text.Format("You must set version info of '{0}' only once.", m_ResourceName.FullName)); + } + + m_VersionInfo = new RemoteVersionInfo(m_CachedFileSystemName, loadType, length, hashCode, compressedLength, compressedHashCode); + m_CachedFileSystemName = null; + } + + /// + /// 设置资源在只读区中的信息。 + /// + /// 资源加载方式。 + /// 资源大小。 + /// 资源哈希值。 + public void SetReadOnlyInfo(LoadType loadType, int length, int hashCode) + { + if (m_ReadOnlyInfo.Exist) + { + throw new GameFrameworkException(Utility.Text.Format("You must set read-only info of '{0}' only once.", m_ResourceName.FullName)); + } + + m_ReadOnlyInfo = new LocalVersionInfo(m_CachedFileSystemName, loadType, length, hashCode); + m_CachedFileSystemName = null; + } + + /// + /// 设置资源在读写区中的信息。 + /// + /// 资源加载方式。 + /// 资源大小。 + /// 资源哈希值。 + public void SetReadWriteInfo(LoadType loadType, int length, int hashCode) + { + if (m_ReadWriteInfo.Exist) + { + throw new GameFrameworkException(Utility.Text.Format("You must set read-write info of '{0}' only once.", m_ResourceName.FullName)); + } + + m_ReadWriteInfo = new LocalVersionInfo(m_CachedFileSystemName, loadType, length, hashCode); + m_CachedFileSystemName = null; + } + + /// + /// 刷新资源信息状态。 + /// + /// 当前变体。 + /// 是否忽略处理其它变体的资源,若不忽略则移除。 + public void RefreshStatus(string currentVariant, bool ignoreOtherVariant) + { + if (!m_VersionInfo.Exist) + { + m_Status = CheckStatus.Disuse; + m_NeedRemove = m_ReadWriteInfo.Exist; + return; + } + + if (m_ResourceName.Variant == null || m_ResourceName.Variant == currentVariant) + { + if (m_ReadOnlyInfo.Exist && m_ReadOnlyInfo.FileSystemName == m_VersionInfo.FileSystemName && m_ReadOnlyInfo.LoadType == m_VersionInfo.LoadType && m_ReadOnlyInfo.Length == m_VersionInfo.Length && m_ReadOnlyInfo.HashCode == m_VersionInfo.HashCode) + { + m_Status = CheckStatus.StorageInReadOnly; + m_NeedRemove = m_ReadWriteInfo.Exist; + } + else if (m_ReadWriteInfo.Exist && m_ReadWriteInfo.LoadType == m_VersionInfo.LoadType && m_ReadWriteInfo.Length == m_VersionInfo.Length && m_ReadWriteInfo.HashCode == m_VersionInfo.HashCode) + { + bool differentFileSystem = m_ReadWriteInfo.FileSystemName != m_VersionInfo.FileSystemName; + m_Status = CheckStatus.StorageInReadWrite; + m_NeedMoveToDisk = m_ReadWriteInfo.UseFileSystem && differentFileSystem; + m_NeedMoveToFileSystem = m_VersionInfo.UseFileSystem && differentFileSystem; + } + else + { + m_Status = CheckStatus.Update; + m_NeedRemove = m_ReadWriteInfo.Exist; + } + } + else + { + m_Status = CheckStatus.Unavailable; + m_NeedRemove = !ignoreOtherVariant && m_ReadWriteInfo.Exist; + } + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.cs.meta new file mode 100644 index 0000000..8ceee72 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.CheckInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 988112be151e0834b9167d7c593ede8f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.cs new file mode 100644 index 0000000..e3e9431 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.cs @@ -0,0 +1,505 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.FileSystem; +using System; +using System.Collections.Generic; +using System.IO; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 资源检查器。 + /// + private sealed partial class ResourceChecker + { + private readonly ResourceManager m_ResourceManager; + private readonly Dictionary m_CheckInfos; + private string m_CurrentVariant; + private bool m_IgnoreOtherVariant; + private bool m_UpdatableVersionListReady; + private bool m_ReadOnlyVersionListReady; + private bool m_ReadWriteVersionListReady; + + public GameFrameworkAction ResourceNeedUpdate; + public GameFrameworkAction ResourceCheckComplete; + + /// + /// 初始化资源检查器的新实例。 + /// + /// 资源管理器。 + public ResourceChecker(ResourceManager resourceManager) + { + m_ResourceManager = resourceManager; + m_CheckInfos = new Dictionary(); + m_CurrentVariant = null; + m_IgnoreOtherVariant = false; + m_UpdatableVersionListReady = false; + m_ReadOnlyVersionListReady = false; + m_ReadWriteVersionListReady = false; + + ResourceNeedUpdate = null; + ResourceCheckComplete = null; + } + + /// + /// 关闭并清理资源检查器。 + /// + public void Shutdown() + { + m_CheckInfos.Clear(); + } + + /// + /// 检查资源。 + /// + /// 当前使用的变体。 + /// 是否忽略处理其它变体的资源,若不忽略,将会移除其它变体的资源。 + public void CheckResources(string currentVariant, bool ignoreOtherVariant) + { + if (m_ResourceManager.m_ResourceHelper == null) + { + throw new GameFrameworkException("Resource helper is invalid."); + } + + if (string.IsNullOrEmpty(m_ResourceManager.m_ReadOnlyPath)) + { + throw new GameFrameworkException("Read-only path is invalid."); + } + + if (string.IsNullOrEmpty(m_ResourceManager.m_ReadWritePath)) + { + throw new GameFrameworkException("Read-write path is invalid."); + } + + m_CurrentVariant = currentVariant; + m_IgnoreOtherVariant = ignoreOtherVariant; + m_ResourceManager.m_ResourceHelper.LoadBytes(Utility.Path.GetRemotePath(Path.Combine(m_ResourceManager.m_ReadWritePath, RemoteVersionListFileName)), new LoadBytesCallbacks(OnLoadUpdatableVersionListSuccess, OnLoadUpdatableVersionListFailure), null); + m_ResourceManager.m_ResourceHelper.LoadBytes(Utility.Path.GetRemotePath(Path.Combine(m_ResourceManager.m_ReadOnlyPath, LocalVersionListFileName)), new LoadBytesCallbacks(OnLoadReadOnlyVersionListSuccess, OnLoadReadOnlyVersionListFailure), null); + m_ResourceManager.m_ResourceHelper.LoadBytes(Utility.Path.GetRemotePath(Path.Combine(m_ResourceManager.m_ReadWritePath, LocalVersionListFileName)), new LoadBytesCallbacks(OnLoadReadWriteVersionListSuccess, OnLoadReadWriteVersionListFailure), null); + } + + private void SetCachedFileSystemName(ResourceName resourceName, string fileSystemName) + { + GetOrAddCheckInfo(resourceName).SetCachedFileSystemName(fileSystemName); + } + + private void SetVersionInfo(ResourceName resourceName, LoadType loadType, int length, int hashCode, int compressedLength, int compressedHashCode) + { + GetOrAddCheckInfo(resourceName).SetVersionInfo(loadType, length, hashCode, compressedLength, compressedHashCode); + } + + private void SetReadOnlyInfo(ResourceName resourceName, LoadType loadType, int length, int hashCode) + { + GetOrAddCheckInfo(resourceName).SetReadOnlyInfo(loadType, length, hashCode); + } + + private void SetReadWriteInfo(ResourceName resourceName, LoadType loadType, int length, int hashCode) + { + GetOrAddCheckInfo(resourceName).SetReadWriteInfo(loadType, length, hashCode); + } + + private CheckInfo GetOrAddCheckInfo(ResourceName resourceName) + { + CheckInfo checkInfo = null; + if (m_CheckInfos.TryGetValue(resourceName, out checkInfo)) + { + return checkInfo; + } + + checkInfo = new CheckInfo(resourceName); + m_CheckInfos.Add(checkInfo.ResourceName, checkInfo); + + return checkInfo; + } + + private void RefreshCheckInfoStatus() + { + if (!m_UpdatableVersionListReady || !m_ReadOnlyVersionListReady || !m_ReadWriteVersionListReady) + { + return; + } + + int movedCount = 0; + int removedCount = 0; + int updateCount = 0; + long updateTotalLength = 0L; + long updateTotalCompressedLength = 0L; + foreach (KeyValuePair checkInfo in m_CheckInfos) + { + CheckInfo ci = checkInfo.Value; + ci.RefreshStatus(m_CurrentVariant, m_IgnoreOtherVariant); + if (ci.Status == CheckInfo.CheckStatus.StorageInReadOnly) + { + m_ResourceManager.m_ResourceInfos.Add(ci.ResourceName, new ResourceInfo(ci.ResourceName, ci.FileSystemName, ci.LoadType, ci.Length, ci.HashCode, ci.CompressedLength, true, true)); + } + else if (ci.Status == CheckInfo.CheckStatus.StorageInReadWrite) + { + if (ci.NeedMoveToDisk || ci.NeedMoveToFileSystem) + { + movedCount++; + string resourceFullName = ci.ResourceName.FullName; + string resourcePath = Utility.Path.GetRegularPath(Path.Combine(m_ResourceManager.m_ReadWritePath, resourceFullName)); + if (ci.NeedMoveToDisk) + { + IFileSystem fileSystem = m_ResourceManager.GetFileSystem(ci.ReadWriteFileSystemName, false); + if (!fileSystem.SaveAsFile(resourceFullName, resourcePath)) + { + throw new GameFrameworkException(Utility.Text.Format("Save as file '{0}' to '{1}' from file system '{2}' error.", resourceFullName, resourcePath, fileSystem.FullPath)); + } + + fileSystem.DeleteFile(resourceFullName); + } + + if (ci.NeedMoveToFileSystem) + { + IFileSystem fileSystem = m_ResourceManager.GetFileSystem(ci.FileSystemName, false); + if (!fileSystem.WriteFile(resourceFullName, resourcePath)) + { + throw new GameFrameworkException(Utility.Text.Format("Write resource '{0}' to file system '{1}' error.", resourceFullName, fileSystem.FullPath)); + } + + if (File.Exists(resourcePath)) + { + File.Delete(resourcePath); + } + } + } + + m_ResourceManager.m_ResourceInfos.Add(ci.ResourceName, new ResourceInfo(ci.ResourceName, ci.FileSystemName, ci.LoadType, ci.Length, ci.HashCode, ci.CompressedLength, false, true)); + m_ResourceManager.m_ReadWriteResourceInfos.Add(ci.ResourceName, new ReadWriteResourceInfo(ci.FileSystemName, ci.LoadType, ci.Length, ci.HashCode)); + } + else if (ci.Status == CheckInfo.CheckStatus.Update) + { + m_ResourceManager.m_ResourceInfos.Add(ci.ResourceName, new ResourceInfo(ci.ResourceName, ci.FileSystemName, ci.LoadType, ci.Length, ci.HashCode, ci.CompressedLength, false, false)); + updateCount++; + updateTotalLength += ci.Length; + updateTotalCompressedLength += ci.CompressedLength; + if (ResourceNeedUpdate != null) + { + ResourceNeedUpdate(ci.ResourceName, ci.FileSystemName, ci.LoadType, ci.Length, ci.HashCode, ci.CompressedLength, ci.CompressedHashCode); + } + } + else if (ci.Status == CheckInfo.CheckStatus.Unavailable || ci.Status == CheckInfo.CheckStatus.Disuse) + { + // Do nothing. + } + else + { + throw new GameFrameworkException(Utility.Text.Format("Check resources '{0}' error with unknown status.", ci.ResourceName.FullName)); + } + + if (ci.NeedRemove) + { + removedCount++; + if (ci.ReadWriteUseFileSystem) + { + IFileSystem fileSystem = m_ResourceManager.GetFileSystem(ci.ReadWriteFileSystemName, false); + fileSystem.DeleteFile(ci.ResourceName.FullName); + } + else + { + string resourcePath = Utility.Path.GetRegularPath(Path.Combine(m_ResourceManager.m_ReadWritePath, ci.ResourceName.FullName)); + if (File.Exists(resourcePath)) + { + File.Delete(resourcePath); + } + } + } + } + + if (movedCount > 0 || removedCount > 0) + { + RemoveEmptyFileSystems(); + Utility.Path.RemoveEmptyDirectory(m_ResourceManager.m_ReadWritePath); + } + + if (ResourceCheckComplete != null) + { + ResourceCheckComplete(movedCount, removedCount, updateCount, updateTotalLength, updateTotalCompressedLength); + } + } + + private void RemoveEmptyFileSystems() + { + List removedFileSystemNames = null; + foreach (KeyValuePair fileSystem in m_ResourceManager.m_ReadWriteFileSystems) + { + if (fileSystem.Value.FileCount <= 0) + { + if (removedFileSystemNames == null) + { + removedFileSystemNames = new List(); + } + + m_ResourceManager.m_FileSystemManager.DestroyFileSystem(fileSystem.Value, true); + removedFileSystemNames.Add(fileSystem.Key); + } + } + + if (removedFileSystemNames != null) + { + foreach (string removedFileSystemName in removedFileSystemNames) + { + m_ResourceManager.m_ReadWriteFileSystems.Remove(removedFileSystemName); + } + } + } + + private void OnLoadUpdatableVersionListSuccess(string fileUri, byte[] bytes, float duration, object userData) + { + if (m_UpdatableVersionListReady) + { + throw new GameFrameworkException("Updatable version list has been parsed."); + } + + MemoryStream memoryStream = null; + try + { + memoryStream = new MemoryStream(bytes, false); + UpdatableVersionList versionList = m_ResourceManager.m_UpdatableVersionListSerializer.Deserialize(memoryStream); + if (!versionList.IsValid) + { + throw new GameFrameworkException("Deserialize updatable version list failure."); + } + + UpdatableVersionList.Asset[] assets = versionList.GetAssets(); + UpdatableVersionList.Resource[] resources = versionList.GetResources(); + UpdatableVersionList.FileSystem[] fileSystems = versionList.GetFileSystems(); + UpdatableVersionList.ResourceGroup[] resourceGroups = versionList.GetResourceGroups(); + m_ResourceManager.m_ApplicableGameVersion = versionList.ApplicableGameVersion; + m_ResourceManager.m_InternalResourceVersion = versionList.InternalResourceVersion; + m_ResourceManager.m_AssetInfos = new Dictionary(assets.Length, StringComparer.Ordinal); + m_ResourceManager.m_ResourceInfos = new Dictionary(resources.Length, new ResourceNameComparer()); + m_ResourceManager.m_ReadWriteResourceInfos = new SortedDictionary(new ResourceNameComparer()); + ResourceGroup defaultResourceGroup = m_ResourceManager.GetOrAddResourceGroup(string.Empty); + + foreach (UpdatableVersionList.FileSystem fileSystem in fileSystems) + { + int[] resourceIndexes = fileSystem.GetResourceIndexes(); + foreach (int resourceIndex in resourceIndexes) + { + UpdatableVersionList.Resource resource = resources[resourceIndex]; + if (resource.Variant != null && resource.Variant != m_CurrentVariant) + { + continue; + } + + SetCachedFileSystemName(new ResourceName(resource.Name, resource.Variant, resource.Extension), fileSystem.Name); + } + } + + foreach (UpdatableVersionList.Resource resource in resources) + { + if (resource.Variant != null && resource.Variant != m_CurrentVariant) + { + continue; + } + + ResourceName resourceName = new ResourceName(resource.Name, resource.Variant, resource.Extension); + int[] assetIndexes = resource.GetAssetIndexes(); + foreach (int assetIndex in assetIndexes) + { + UpdatableVersionList.Asset asset = assets[assetIndex]; + int[] dependencyAssetIndexes = asset.GetDependencyAssetIndexes(); + int index = 0; + string[] dependencyAssetNames = new string[dependencyAssetIndexes.Length]; + foreach (int dependencyAssetIndex in dependencyAssetIndexes) + { + dependencyAssetNames[index++] = assets[dependencyAssetIndex].Name; + } + + m_ResourceManager.m_AssetInfos.Add(asset.Name, new AssetInfo(asset.Name, resourceName, dependencyAssetNames)); + } + + SetVersionInfo(resourceName, (LoadType)resource.LoadType, resource.Length, resource.HashCode, resource.CompressedLength, resource.CompressedHashCode); + defaultResourceGroup.AddResource(resourceName, resource.Length, resource.CompressedLength); + } + + foreach (UpdatableVersionList.ResourceGroup resourceGroup in resourceGroups) + { + ResourceGroup group = m_ResourceManager.GetOrAddResourceGroup(resourceGroup.Name); + int[] resourceIndexes = resourceGroup.GetResourceIndexes(); + foreach (int resourceIndex in resourceIndexes) + { + UpdatableVersionList.Resource resource = resources[resourceIndex]; + if (resource.Variant != null && resource.Variant != m_CurrentVariant) + { + continue; + } + + group.AddResource(new ResourceName(resource.Name, resource.Variant, resource.Extension), resource.Length, resource.CompressedLength); + } + } + + m_UpdatableVersionListReady = true; + RefreshCheckInfoStatus(); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Utility.Text.Format("Parse updatable version list exception '{0}'.", exception), exception); + } + finally + { + if (memoryStream != null) + { + memoryStream.Dispose(); + memoryStream = null; + } + } + } + + private void OnLoadUpdatableVersionListFailure(string fileUri, string errorMessage, object userData) + { + throw new GameFrameworkException(Utility.Text.Format("Updatable version list '{0}' is invalid, error message is '{1}'.", fileUri, string.IsNullOrEmpty(errorMessage) ? "" : errorMessage)); + } + + private void OnLoadReadOnlyVersionListSuccess(string fileUri, byte[] bytes, float duration, object userData) + { + if (m_ReadOnlyVersionListReady) + { + throw new GameFrameworkException("Read-only version list has been parsed."); + } + + MemoryStream memoryStream = null; + try + { + memoryStream = new MemoryStream(bytes, false); + LocalVersionList versionList = m_ResourceManager.m_ReadOnlyVersionListSerializer.Deserialize(memoryStream); + if (!versionList.IsValid) + { + throw new GameFrameworkException("Deserialize read-only version list failure."); + } + + LocalVersionList.Resource[] resources = versionList.GetResources(); + LocalVersionList.FileSystem[] fileSystems = versionList.GetFileSystems(); + + foreach (LocalVersionList.FileSystem fileSystem in fileSystems) + { + int[] resourceIndexes = fileSystem.GetResourceIndexes(); + foreach (int resourceIndex in resourceIndexes) + { + LocalVersionList.Resource resource = resources[resourceIndex]; + SetCachedFileSystemName(new ResourceName(resource.Name, resource.Variant, resource.Extension), fileSystem.Name); + } + } + + foreach (LocalVersionList.Resource resource in resources) + { + SetReadOnlyInfo(new ResourceName(resource.Name, resource.Variant, resource.Extension), (LoadType)resource.LoadType, resource.Length, resource.HashCode); + } + + m_ReadOnlyVersionListReady = true; + RefreshCheckInfoStatus(); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Utility.Text.Format("Parse read-only version list exception '{0}'.", exception), exception); + } + finally + { + if (memoryStream != null) + { + memoryStream.Dispose(); + memoryStream = null; + } + } + } + + private void OnLoadReadOnlyVersionListFailure(string fileUri, string errorMessage, object userData) + { + if (m_ReadOnlyVersionListReady) + { + throw new GameFrameworkException("Read-only version list has been parsed."); + } + + m_ReadOnlyVersionListReady = true; + RefreshCheckInfoStatus(); + } + + private void OnLoadReadWriteVersionListSuccess(string fileUri, byte[] bytes, float duration, object userData) + { + if (m_ReadWriteVersionListReady) + { + throw new GameFrameworkException("Read-write version list has been parsed."); + } + + MemoryStream memoryStream = null; + try + { + memoryStream = new MemoryStream(bytes, false); + LocalVersionList versionList = m_ResourceManager.m_ReadWriteVersionListSerializer.Deserialize(memoryStream); + if (!versionList.IsValid) + { + throw new GameFrameworkException("Deserialize read-write version list failure."); + } + + LocalVersionList.Resource[] resources = versionList.GetResources(); + LocalVersionList.FileSystem[] fileSystems = versionList.GetFileSystems(); + + foreach (LocalVersionList.FileSystem fileSystem in fileSystems) + { + int[] resourceIndexes = fileSystem.GetResourceIndexes(); + foreach (int resourceIndex in resourceIndexes) + { + LocalVersionList.Resource resource = resources[resourceIndex]; + SetCachedFileSystemName(new ResourceName(resource.Name, resource.Variant, resource.Extension), fileSystem.Name); + } + } + + foreach (LocalVersionList.Resource resource in resources) + { + SetReadWriteInfo(new ResourceName(resource.Name, resource.Variant, resource.Extension), (LoadType)resource.LoadType, resource.Length, resource.HashCode); + } + + m_ReadWriteVersionListReady = true; + RefreshCheckInfoStatus(); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Utility.Text.Format("Parse read-write version list exception '{0}'.", exception), exception); + } + finally + { + if (memoryStream != null) + { + memoryStream.Dispose(); + memoryStream = null; + } + } + } + + private void OnLoadReadWriteVersionListFailure(string fileUri, string errorMessage, object userData) + { + if (m_ReadWriteVersionListReady) + { + throw new GameFrameworkException("Read-write version list has been parsed."); + } + + m_ReadWriteVersionListReady = true; + RefreshCheckInfoStatus(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.cs.meta new file mode 100644 index 0000000..f1b108c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceChecker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 416fabfbd0fc5c34488eaf29a88c2c92 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceGroup.cs new file mode 100644 index 0000000..a215aad --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceGroup.cs @@ -0,0 +1,268 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 资源组。 + /// + private sealed class ResourceGroup : IResourceGroup + { + private readonly string m_Name; + private readonly Dictionary m_ResourceInfos; + private readonly HashSet m_ResourceNames; + private long m_TotalLength; + private long m_TotalCompressedLength; + + /// + /// 初始化资源组的新实例。 + /// + /// 资源组名称。 + /// 资源信息引用。 + public ResourceGroup(string name, Dictionary resourceInfos) + { + if (name == null) + { + throw new GameFrameworkException("Name is invalid."); + } + + if (resourceInfos == null) + { + throw new GameFrameworkException("Resource infos is invalid."); + } + + m_Name = name; + m_ResourceInfos = resourceInfos; + m_ResourceNames = new HashSet(); + } + + /// + /// 获取资源组名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取资源组是否准备完毕。 + /// + public bool Ready + { + get + { + return ReadyCount >= TotalCount; + } + } + + /// + /// 获取资源组包含资源数量。 + /// + public int TotalCount + { + get + { + return m_ResourceNames.Count; + } + } + + /// + /// 获取资源组中已准备完成资源数量。 + /// + public int ReadyCount + { + get + { + int readyCount = 0; + foreach (ResourceName resourceName in m_ResourceNames) + { + ResourceInfo resourceInfo = null; + if (m_ResourceInfos.TryGetValue(resourceName, out resourceInfo) && resourceInfo.Ready) + { + readyCount++; + } + } + + return readyCount; + } + } + + /// + /// 获取资源组包含资源的总大小。 + /// + public long TotalLength + { + get + { + return m_TotalLength; + } + } + + /// + /// 获取资源组包含资源压缩后的总大小。 + /// + public long TotalCompressedLength + { + get + { + return m_TotalCompressedLength; + } + } + + /// + /// 获取资源组中已准备完成资源的总大小。 + /// + public long ReadyLength + { + get + { + long readyLength = 0L; + foreach (ResourceName resourceName in m_ResourceNames) + { + ResourceInfo resourceInfo = null; + if (m_ResourceInfos.TryGetValue(resourceName, out resourceInfo) && resourceInfo.Ready) + { + readyLength += resourceInfo.Length; + } + } + + return readyLength; + } + } + + /// + /// 获取资源组中已准备完成资源压缩后的总大小。 + /// + public long ReadyCompressedLength + { + get + { + long readyCompressedLength = 0L; + foreach (ResourceName resourceName in m_ResourceNames) + { + ResourceInfo resourceInfo = null; + if (m_ResourceInfos.TryGetValue(resourceName, out resourceInfo) && resourceInfo.Ready) + { + readyCompressedLength += resourceInfo.CompressedLength; + } + } + + return readyCompressedLength; + } + } + + /// + /// 获取资源组的完成进度。 + /// + public float Progress + { + get + { + return m_TotalLength > 0L ? (float)ReadyLength / m_TotalLength : 1f; + } + } + + /// + /// 获取资源组包含的资源名称列表。 + /// + /// 资源组包含的资源名称列表。 + public string[] GetResourceNames() + { + int index = 0; + string[] resourceNames = new string[m_ResourceNames.Count]; + foreach (ResourceName resourceName in m_ResourceNames) + { + resourceNames[index++] = resourceName.FullName; + } + + return resourceNames; + } + + /// + /// 获取资源组包含的资源名称列表。 + /// + /// 资源组包含的资源名称列表。 + public void GetResourceNames(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (ResourceName resourceName in m_ResourceNames) + { + results.Add(resourceName.FullName); + } + } + + /// + /// 获取资源组包含的资源名称列表。 + /// + /// 资源组包含的资源名称列表。 + public ResourceName[] InternalGetResourceNames() + { + int index = 0; + ResourceName[] resourceNames = new ResourceName[m_ResourceNames.Count]; + foreach (ResourceName resourceName in m_ResourceNames) + { + resourceNames[index++] = resourceName; + } + + return resourceNames; + } + + /// + /// 获取资源组包含的资源名称列表。 + /// + /// 资源组包含的资源名称列表。 + public void InternalGetResourceNames(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (ResourceName resourceName in m_ResourceNames) + { + results.Add(resourceName); + } + } + + /// + /// 检查指定资源是否属于资源组。 + /// + /// 要检查的资源的名称。 + /// 指定资源是否属于资源组。 + public bool HasResource(ResourceName resourceName) + { + return m_ResourceNames.Contains(resourceName); + } + + /// + /// 向资源组中增加资源。 + /// + /// 资源名称。 + /// 资源大小。 + /// 资源压缩后的大小。 + public void AddResource(ResourceName resourceName, int length, int compressedLength) + { + m_ResourceNames.Add(resourceName); + m_TotalLength += length; + m_TotalCompressedLength += compressedLength; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceGroup.cs.meta new file mode 100644 index 0000000..aec98d4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef71d0ab4a89c7e43bb7024ab1ba1176 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceGroupCollection.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceGroupCollection.cs new file mode 100644 index 0000000..8439d8b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceGroupCollection.cs @@ -0,0 +1,253 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 资源组集合。 + /// + private sealed class ResourceGroupCollection : IResourceGroupCollection + { + private readonly ResourceGroup[] m_ResourceGroups; + private readonly Dictionary m_ResourceInfos; + private readonly HashSet m_ResourceNames; + private long m_TotalLength; + private long m_TotalCompressedLength; + + /// + /// 初始化资源组集合的新实例。 + /// + /// 资源组集合。 + /// 资源信息引用。 + public ResourceGroupCollection(ResourceGroup[] resourceGroups, Dictionary resourceInfos) + { + if (resourceGroups == null || resourceGroups.Length < 1) + { + throw new GameFrameworkException("Resource groups is invalid."); + } + + if (resourceInfos == null) + { + throw new GameFrameworkException("Resource infos is invalid."); + } + + int lastIndex = resourceGroups.Length - 1; + for (int i = 0; i < lastIndex; i++) + { + if (resourceGroups[i] == null) + { + throw new GameFrameworkException(Utility.Text.Format("Resource group index '{0}' is invalid.", i)); + } + + for (int j = i + 1; j < resourceGroups.Length; j++) + { + if (resourceGroups[i] == resourceGroups[j]) + { + throw new GameFrameworkException(Utility.Text.Format("Resource group '{0}' duplicated.", resourceGroups[i].Name)); + } + } + } + + if (resourceGroups[lastIndex] == null) + { + throw new GameFrameworkException(Utility.Text.Format("Resource group index '{0}' is invalid.", lastIndex)); + } + + m_ResourceGroups = resourceGroups; + m_ResourceInfos = resourceInfos; + m_ResourceNames = new HashSet(); + m_TotalLength = 0L; + m_TotalCompressedLength = 0L; + + List cachedResourceNames = new List(); + foreach (ResourceGroup resourceGroup in m_ResourceGroups) + { + resourceGroup.InternalGetResourceNames(cachedResourceNames); + foreach (ResourceName resourceName in cachedResourceNames) + { + ResourceInfo resourceInfo = null; + if (!m_ResourceInfos.TryGetValue(resourceName, out resourceInfo)) + { + throw new GameFrameworkException(Utility.Text.Format("Resource info '{0}' is invalid.", resourceName.FullName)); + } + + if (m_ResourceNames.Add(resourceName)) + { + m_TotalLength += resourceInfo.Length; + m_TotalCompressedLength += resourceInfo.CompressedLength; + } + } + } + } + + /// + /// 获取资源组集合是否准备完毕。 + /// + public bool Ready + { + get + { + return ReadyCount >= TotalCount; + } + } + + /// + /// 获取资源组集合包含资源数量。 + /// + public int TotalCount + { + get + { + return m_ResourceNames.Count; + } + } + + /// + /// 获取资源组集合中已准备完成资源数量。 + /// + public int ReadyCount + { + get + { + int readyCount = 0; + foreach (ResourceName resourceName in m_ResourceNames) + { + ResourceInfo resourceInfo = null; + if (m_ResourceInfos.TryGetValue(resourceName, out resourceInfo) && resourceInfo.Ready) + { + readyCount++; + } + } + + return readyCount; + } + } + + /// + /// 获取资源组集合包含资源的总大小。 + /// + public long TotalLength + { + get + { + return m_TotalLength; + } + } + + /// + /// 获取资源组集合包含资源压缩后的总大小。 + /// + public long TotalCompressedLength + { + get + { + return m_TotalCompressedLength; + } + } + + /// + /// 获取资源组集合中已准备完成资源的总大小。 + /// + public long ReadyLength + { + get + { + long readyLength = 0L; + foreach (ResourceName resourceName in m_ResourceNames) + { + ResourceInfo resourceInfo = null; + if (m_ResourceInfos.TryGetValue(resourceName, out resourceInfo) && resourceInfo.Ready) + { + readyLength += resourceInfo.Length; + } + } + + return readyLength; + } + } + + /// + /// 获取资源组集合中已准备完成资源压缩后的总大小。 + /// + public long ReadyCompressedLength + { + get + { + long readyCompressedLength = 0L; + foreach (ResourceName resourceName in m_ResourceNames) + { + ResourceInfo resourceInfo = null; + if (m_ResourceInfos.TryGetValue(resourceName, out resourceInfo) && resourceInfo.Ready) + { + readyCompressedLength += resourceInfo.CompressedLength; + } + } + + return readyCompressedLength; + } + } + + /// + /// 获取资源组集合的完成进度。 + /// + public float Progress + { + get + { + return m_TotalLength > 0L ? (float)ReadyLength / m_TotalLength : 1f; + } + } + + /// + /// 获取资源组集合包含的资源组列表。 + /// + /// 资源组包含的资源名称列表。 + public IResourceGroup[] GetResourceGroups() + { + return m_ResourceGroups; + } + + /// + /// 获取资源组集合包含的资源名称列表。 + /// + /// 资源组包含的资源名称列表。 + public string[] GetResourceNames() + { + int index = 0; + string[] resourceNames = new string[m_ResourceNames.Count]; + foreach (ResourceName resourceName in m_ResourceNames) + { + resourceNames[index++] = resourceName.FullName; + } + + return resourceNames; + } + + /// + /// 获取资源组集合包含的资源名称列表。 + /// + /// 资源组包含的资源名称列表。 + public void GetResourceNames(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (ResourceName resourceName in m_ResourceNames) + { + results.Add(resourceName.FullName); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceGroupCollection.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceGroupCollection.cs.meta new file mode 100644 index 0000000..ef570e0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceGroupCollection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c9e85d4a75b6cb64fb90f951a1bdc177 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceInfo.cs new file mode 100644 index 0000000..170d572 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceInfo.cs @@ -0,0 +1,168 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 资源信息。 + /// + private sealed class ResourceInfo + { + private readonly ResourceName m_ResourceName; + private readonly string m_FileSystemName; + private readonly LoadType m_LoadType; + private readonly int m_Length; + private readonly int m_HashCode; + private readonly int m_CompressedLength; + private readonly bool m_StorageInReadOnly; + private bool m_Ready; + + /// + /// 初始化资源信息的新实例。 + /// + /// 资源名称。 + /// 文件系统名称。 + /// 资源加载方式。 + /// 资源大小。 + /// 资源哈希值。 + /// 压缩后资源大小。 + /// 资源是否在只读区。 + /// 资源是否准备完毕。 + public ResourceInfo(ResourceName resourceName, string fileSystemName, LoadType loadType, int length, int hashCode, int compressedLength, bool storageInReadOnly, bool ready) + { + m_ResourceName = resourceName; + m_FileSystemName = fileSystemName; + m_LoadType = loadType; + m_Length = length; + m_HashCode = hashCode; + m_CompressedLength = compressedLength; + m_StorageInReadOnly = storageInReadOnly; + m_Ready = ready; + } + + /// + /// 获取资源名称。 + /// + public ResourceName ResourceName + { + get + { + return m_ResourceName; + } + } + + /// + /// 获取资源是否使用文件系统。 + /// + public bool UseFileSystem + { + get + { + return !string.IsNullOrEmpty(m_FileSystemName); + } + } + + /// + /// 获取文件系统名称。 + /// + public string FileSystemName + { + get + { + return m_FileSystemName; + } + } + + /// + /// 获取资源是否通过二进制方式加载。 + /// + public bool IsLoadFromBinary + { + get + { + return m_LoadType == LoadType.LoadFromBinary || m_LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || m_LoadType == LoadType.LoadFromBinaryAndDecrypt; + } + } + + /// + /// 获取资源加载方式。 + /// + public LoadType LoadType + { + get + { + return m_LoadType; + } + } + + /// + /// 获取资源大小。 + /// + public int Length + { + get + { + return m_Length; + } + } + + /// + /// 获取资源哈希值。 + /// + public int HashCode + { + get + { + return m_HashCode; + } + } + + /// + /// 获取压缩后资源大小。 + /// + public int CompressedLength + { + get + { + return m_CompressedLength; + } + } + + /// + /// 获取资源是否在只读区。 + /// + public bool StorageInReadOnly + { + get + { + return m_StorageInReadOnly; + } + } + + /// + /// 获取资源是否准备完毕。 + /// + public bool Ready + { + get + { + return m_Ready; + } + } + + /// + /// 标记资源准备完毕。 + /// + public void MarkReady() + { + m_Ready = true; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceInfo.cs.meta new file mode 100644 index 0000000..e883907 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1bd3f1447b6bd5549afc881a2c9d3f7d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceIniter.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceIniter.cs new file mode 100644 index 0000000..0a89778 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceIniter.cs @@ -0,0 +1,181 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.IO; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 资源初始化器。 + /// + private sealed class ResourceIniter + { + private readonly ResourceManager m_ResourceManager; + private readonly Dictionary m_CachedFileSystemNames; + private string m_CurrentVariant; + + public GameFrameworkAction ResourceInitComplete; + + /// + /// 初始化资源初始化器的新实例。 + /// + /// 资源管理器。 + public ResourceIniter(ResourceManager resourceManager) + { + m_ResourceManager = resourceManager; + m_CachedFileSystemNames = new Dictionary(); + m_CurrentVariant = null; + + ResourceInitComplete = null; + } + + /// + /// 关闭并清理资源初始化器。 + /// + public void Shutdown() + { + } + + /// + /// 初始化资源。 + /// + public void InitResources(string currentVariant) + { + m_CurrentVariant = currentVariant; + + if (m_ResourceManager.m_ResourceHelper == null) + { + throw new GameFrameworkException("Resource helper is invalid."); + } + + if (string.IsNullOrEmpty(m_ResourceManager.m_ReadOnlyPath)) + { + throw new GameFrameworkException("Read-only path is invalid."); + } + + m_ResourceManager.m_ResourceHelper.LoadBytes(Utility.Path.GetRemotePath(Path.Combine(m_ResourceManager.m_ReadOnlyPath, RemoteVersionListFileName)), new LoadBytesCallbacks(OnLoadPackageVersionListSuccess, OnLoadPackageVersionListFailure), null); + } + + private void OnLoadPackageVersionListSuccess(string fileUri, byte[] bytes, float duration, object userData) + { + MemoryStream memoryStream = null; + try + { + memoryStream = new MemoryStream(bytes, false); + PackageVersionList versionList = m_ResourceManager.m_PackageVersionListSerializer.Deserialize(memoryStream); + if (!versionList.IsValid) + { + throw new GameFrameworkException("Deserialize package version list failure."); + } + + PackageVersionList.Asset[] assets = versionList.GetAssets(); + PackageVersionList.Resource[] resources = versionList.GetResources(); + PackageVersionList.FileSystem[] fileSystems = versionList.GetFileSystems(); + PackageVersionList.ResourceGroup[] resourceGroups = versionList.GetResourceGroups(); + m_ResourceManager.m_ApplicableGameVersion = versionList.ApplicableGameVersion; + m_ResourceManager.m_InternalResourceVersion = versionList.InternalResourceVersion; + m_ResourceManager.m_AssetInfos = new Dictionary(assets.Length, StringComparer.Ordinal); + m_ResourceManager.m_ResourceInfos = new Dictionary(resources.Length, new ResourceNameComparer()); + ResourceGroup defaultResourceGroup = m_ResourceManager.GetOrAddResourceGroup(string.Empty); + + foreach (PackageVersionList.FileSystem fileSystem in fileSystems) + { + int[] resourceIndexes = fileSystem.GetResourceIndexes(); + foreach (int resourceIndex in resourceIndexes) + { + PackageVersionList.Resource resource = resources[resourceIndex]; + if (resource.Variant != null && resource.Variant != m_CurrentVariant) + { + continue; + } + + m_CachedFileSystemNames.Add(new ResourceName(resource.Name, resource.Variant, resource.Extension), fileSystem.Name); + } + } + + foreach (PackageVersionList.Resource resource in resources) + { + if (resource.Variant != null && resource.Variant != m_CurrentVariant) + { + continue; + } + + ResourceName resourceName = new ResourceName(resource.Name, resource.Variant, resource.Extension); + int[] assetIndexes = resource.GetAssetIndexes(); + foreach (int assetIndex in assetIndexes) + { + PackageVersionList.Asset asset = assets[assetIndex]; + int[] dependencyAssetIndexes = asset.GetDependencyAssetIndexes(); + int index = 0; + string[] dependencyAssetNames = new string[dependencyAssetIndexes.Length]; + foreach (int dependencyAssetIndex in dependencyAssetIndexes) + { + dependencyAssetNames[index++] = assets[dependencyAssetIndex].Name; + } + + m_ResourceManager.m_AssetInfos.Add(asset.Name, new AssetInfo(asset.Name, resourceName, dependencyAssetNames)); + } + + string fileSystemName = null; + if (!m_CachedFileSystemNames.TryGetValue(resourceName, out fileSystemName)) + { + fileSystemName = null; + } + + m_ResourceManager.m_ResourceInfos.Add(resourceName, new ResourceInfo(resourceName, fileSystemName, (LoadType)resource.LoadType, resource.Length, resource.HashCode, resource.Length, true, true)); + defaultResourceGroup.AddResource(resourceName, resource.Length, resource.Length); + } + + foreach (PackageVersionList.ResourceGroup resourceGroup in resourceGroups) + { + ResourceGroup group = m_ResourceManager.GetOrAddResourceGroup(resourceGroup.Name); + int[] resourceIndexes = resourceGroup.GetResourceIndexes(); + foreach (int resourceIndex in resourceIndexes) + { + PackageVersionList.Resource resource = resources[resourceIndex]; + if (resource.Variant != null && resource.Variant != m_CurrentVariant) + { + continue; + } + + group.AddResource(new ResourceName(resource.Name, resource.Variant, resource.Extension), resource.Length, resource.Length); + } + } + + ResourceInitComplete(); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Utility.Text.Format("Parse package version list exception '{0}'.", exception), exception); + } + finally + { + m_CachedFileSystemNames.Clear(); + if (memoryStream != null) + { + memoryStream.Dispose(); + memoryStream = null; + } + } + } + + private void OnLoadPackageVersionListFailure(string fileUri, string errorMessage, object userData) + { + throw new GameFrameworkException(Utility.Text.Format("Package version list '{0}' is invalid, error message is '{1}'.", fileUri, string.IsNullOrEmpty(errorMessage) ? "" : errorMessage)); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceIniter.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceIniter.cs.meta new file mode 100644 index 0000000..dd77eac --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceIniter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5fd705b05ce15e24daa1b8c1cdf23f59 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.AssetObject.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.AssetObject.cs new file mode 100644 index 0000000..695779a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.AssetObject.cs @@ -0,0 +1,141 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.ObjectPool; +using System.Collections.Generic; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceLoader + { + /// + /// 资源对象。 + /// + private sealed class AssetObject : ObjectBase + { + private List m_DependencyAssets; + private object m_Resource; + private IResourceHelper m_ResourceHelper; + private ResourceLoader m_ResourceLoader; + + public AssetObject() + { + m_DependencyAssets = new List(); + m_Resource = null; + m_ResourceHelper = null; + m_ResourceLoader = null; + } + + public override bool CustomCanReleaseFlag + { + get + { + int targetReferenceCount = 0; + m_ResourceLoader.m_AssetDependencyCount.TryGetValue(Target, out targetReferenceCount); + return base.CustomCanReleaseFlag && targetReferenceCount <= 0; + } + } + + public static AssetObject Create(string name, object target, List dependencyAssets, object resource, IResourceHelper resourceHelper, ResourceLoader resourceLoader) + { + if (dependencyAssets == null) + { + throw new GameFrameworkException("Dependency assets is invalid."); + } + + if (resource == null) + { + throw new GameFrameworkException("Resource is invalid."); + } + + if (resourceHelper == null) + { + throw new GameFrameworkException("Resource helper is invalid."); + } + + if (resourceLoader == null) + { + throw new GameFrameworkException("Resource loader is invalid."); + } + + AssetObject assetObject = ReferencePool.Acquire(); + assetObject.Initialize(name, target); + assetObject.m_DependencyAssets.AddRange(dependencyAssets); + assetObject.m_Resource = resource; + assetObject.m_ResourceHelper = resourceHelper; + assetObject.m_ResourceLoader = resourceLoader; + + foreach (object dependencyAsset in dependencyAssets) + { + int referenceCount = 0; + if (resourceLoader.m_AssetDependencyCount.TryGetValue(dependencyAsset, out referenceCount)) + { + resourceLoader.m_AssetDependencyCount[dependencyAsset] = referenceCount + 1; + } + else + { + resourceLoader.m_AssetDependencyCount.Add(dependencyAsset, 1); + } + } + + return assetObject; + } + + public override void Clear() + { + base.Clear(); + m_DependencyAssets.Clear(); + m_Resource = null; + m_ResourceHelper = null; + m_ResourceLoader = null; + } + + protected internal override void OnUnspawn() + { + base.OnUnspawn(); + foreach (object dependencyAsset in m_DependencyAssets) + { + m_ResourceLoader.m_AssetPool.Unspawn(dependencyAsset); + } + } + + protected internal override void Release(bool isShutdown) + { + if (!isShutdown) + { + int targetReferenceCount = 0; + if (m_ResourceLoader.m_AssetDependencyCount.TryGetValue(Target, out targetReferenceCount) && targetReferenceCount > 0) + { + throw new GameFrameworkException(Utility.Text.Format("Asset target '{0}' reference count is '{1}' larger than 0.", Name, targetReferenceCount)); + } + + foreach (object dependencyAsset in m_DependencyAssets) + { + int referenceCount = 0; + if (m_ResourceLoader.m_AssetDependencyCount.TryGetValue(dependencyAsset, out referenceCount)) + { + m_ResourceLoader.m_AssetDependencyCount[dependencyAsset] = referenceCount - 1; + } + else + { + throw new GameFrameworkException(Utility.Text.Format("Asset target '{0}' dependency asset reference count is invalid.", Name)); + } + } + + m_ResourceLoader.m_ResourcePool.Unspawn(m_Resource); + } + + m_ResourceLoader.m_AssetDependencyCount.Remove(Target); + m_ResourceLoader.m_AssetToResourceMap.Remove(Target); + m_ResourceHelper.Release(Target); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.AssetObject.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.AssetObject.cs.meta new file mode 100644 index 0000000..2e99e77 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.AssetObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1e0afab98077ac34e8799708dfa2da93 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadAssetTask.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadAssetTask.cs new file mode 100644 index 0000000..ffc66be --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadAssetTask.cs @@ -0,0 +1,88 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceLoader + { + private sealed class LoadAssetTask : LoadResourceTaskBase + { + private LoadAssetCallbacks m_LoadAssetCallbacks; + + public LoadAssetTask() + { + m_LoadAssetCallbacks = null; + } + + public override bool IsScene + { + get + { + return false; + } + } + + public static LoadAssetTask Create(string assetName, Type assetType, int priority, ResourceInfo resourceInfo, string[] dependencyAssetNames, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + LoadAssetTask loadAssetTask = ReferencePool.Acquire(); + loadAssetTask.Initialize(assetName, assetType, priority, resourceInfo, dependencyAssetNames, userData); + loadAssetTask.m_LoadAssetCallbacks = loadAssetCallbacks; + return loadAssetTask; + } + + public override void Clear() + { + base.Clear(); + m_LoadAssetCallbacks = null; + } + + public override void OnLoadAssetSuccess(LoadResourceAgent agent, object asset, float duration) + { + base.OnLoadAssetSuccess(agent, asset, duration); + if (m_LoadAssetCallbacks.LoadAssetSuccessCallback != null) + { + m_LoadAssetCallbacks.LoadAssetSuccessCallback(AssetName, asset, duration, UserData); + } + } + + public override void OnLoadAssetFailure(LoadResourceAgent agent, LoadResourceStatus status, string errorMessage) + { + base.OnLoadAssetFailure(agent, status, errorMessage); + if (m_LoadAssetCallbacks.LoadAssetFailureCallback != null) + { + m_LoadAssetCallbacks.LoadAssetFailureCallback(AssetName, status, errorMessage, UserData); + } + } + + public override void OnLoadAssetUpdate(LoadResourceAgent agent, LoadResourceProgress type, float progress) + { + base.OnLoadAssetUpdate(agent, type, progress); + if (type == LoadResourceProgress.LoadAsset) + { + if (m_LoadAssetCallbacks.LoadAssetUpdateCallback != null) + { + m_LoadAssetCallbacks.LoadAssetUpdateCallback(AssetName, progress, UserData); + } + } + } + + public override void OnLoadDependencyAsset(LoadResourceAgent agent, string dependencyAssetName, object dependencyAsset) + { + base.OnLoadDependencyAsset(agent, dependencyAssetName, dependencyAsset); + if (m_LoadAssetCallbacks.LoadAssetDependencyAssetCallback != null) + { + m_LoadAssetCallbacks.LoadAssetDependencyAssetCallback(AssetName, dependencyAssetName, LoadedDependencyAssetCount, TotalDependencyAssetCount, UserData); + } + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadAssetTask.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadAssetTask.cs.meta new file mode 100644 index 0000000..28f283b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadAssetTask.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 14f7ed0057d8d654d9ef3c9613aa962e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadBinaryInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadBinaryInfo.cs new file mode 100644 index 0000000..45657b0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadBinaryInfo.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceLoader + { + private sealed class LoadBinaryInfo : IReference + { + private string m_BinaryAssetName; + private ResourceInfo m_ResourceInfo; + private LoadBinaryCallbacks m_LoadBinaryCallbacks; + private object m_UserData; + + public LoadBinaryInfo() + { + m_BinaryAssetName = null; + m_ResourceInfo = null; + m_LoadBinaryCallbacks = null; + m_UserData = null; + } + + public string BinaryAssetName + { + get + { + return m_BinaryAssetName; + } + } + + public ResourceInfo ResourceInfo + { + get + { + return m_ResourceInfo; + } + } + + public LoadBinaryCallbacks LoadBinaryCallbacks + { + get + { + return m_LoadBinaryCallbacks; + } + } + + public object UserData + { + get + { + return m_UserData; + } + } + + public static LoadBinaryInfo Create(string binaryAssetName, ResourceInfo resourceInfo, LoadBinaryCallbacks loadBinaryCallbacks, object userData) + { + LoadBinaryInfo loadBinaryInfo = ReferencePool.Acquire(); + loadBinaryInfo.m_BinaryAssetName = binaryAssetName; + loadBinaryInfo.m_ResourceInfo = resourceInfo; + loadBinaryInfo.m_LoadBinaryCallbacks = loadBinaryCallbacks; + loadBinaryInfo.m_UserData = userData; + return loadBinaryInfo; + } + + public void Clear() + { + m_BinaryAssetName = null; + m_ResourceInfo = null; + m_LoadBinaryCallbacks = null; + m_UserData = null; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadBinaryInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadBinaryInfo.cs.meta new file mode 100644 index 0000000..e0e0a8b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadBinaryInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4c9df77cd883d4f49a99773a27b3a32c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadDependencyAssetTask.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadDependencyAssetTask.cs new file mode 100644 index 0000000..6da2e63 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadDependencyAssetTask.cs @@ -0,0 +1,60 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceLoader + { + private sealed class LoadDependencyAssetTask : LoadResourceTaskBase + { + private LoadResourceTaskBase m_MainTask; + + public LoadDependencyAssetTask() + { + m_MainTask = null; + } + + public override bool IsScene + { + get + { + return false; + } + } + + public static LoadDependencyAssetTask Create(string assetName, int priority, ResourceInfo resourceInfo, string[] dependencyAssetNames, LoadResourceTaskBase mainTask, object userData) + { + LoadDependencyAssetTask loadDependencyAssetTask = ReferencePool.Acquire(); + loadDependencyAssetTask.Initialize(assetName, null, priority, resourceInfo, dependencyAssetNames, userData); + loadDependencyAssetTask.m_MainTask = mainTask; + loadDependencyAssetTask.m_MainTask.TotalDependencyAssetCount++; + return loadDependencyAssetTask; + } + + public override void Clear() + { + base.Clear(); + m_MainTask = null; + } + + public override void OnLoadAssetSuccess(LoadResourceAgent agent, object asset, float duration) + { + base.OnLoadAssetSuccess(agent, asset, duration); + m_MainTask.OnLoadDependencyAsset(agent, AssetName, asset); + } + + public override void OnLoadAssetFailure(LoadResourceAgent agent, LoadResourceStatus status, string errorMessage) + { + base.OnLoadAssetFailure(agent, status, errorMessage); + m_MainTask.OnLoadAssetFailure(agent, LoadResourceStatus.DependencyError, Utility.Text.Format("Can not load dependency asset '{0}', internal status '{1}', internal error message '{2}'.", AssetName, status, errorMessage)); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadDependencyAssetTask.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadDependencyAssetTask.cs.meta new file mode 100644 index 0000000..9ff26a8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadDependencyAssetTask.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 41fd3dadaf0c458499d8bf6fb4d88e63 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadResourceAgent.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadResourceAgent.cs new file mode 100644 index 0000000..f7d340f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadResourceAgent.cs @@ -0,0 +1,361 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.FileSystem; +using System; +using System.Collections.Generic; +using System.IO; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceLoader + { + /// + /// 加载资源代理。 + /// + private sealed partial class LoadResourceAgent : ITaskAgent + { + private static readonly Dictionary s_CachedResourceNames = new Dictionary(StringComparer.Ordinal); + private static readonly HashSet s_LoadingAssetNames = new HashSet(StringComparer.Ordinal); + private static readonly HashSet s_LoadingResourceNames = new HashSet(StringComparer.Ordinal); + + private readonly ILoadResourceAgentHelper m_Helper; + private readonly IResourceHelper m_ResourceHelper; + private readonly ResourceLoader m_ResourceLoader; + private readonly string m_ReadOnlyPath; + private readonly string m_ReadWritePath; + private readonly DecryptResourceCallback m_DecryptResourceCallback; + private LoadResourceTaskBase m_Task; + + /// + /// 初始化加载资源代理的新实例。 + /// + /// 加载资源代理辅助器。 + /// 资源辅助器。 + /// 加载资源器。 + /// 资源只读区路径。 + /// 资源读写区路径。 + /// 解密资源回调函数。 + public LoadResourceAgent(ILoadResourceAgentHelper loadResourceAgentHelper, IResourceHelper resourceHelper, ResourceLoader resourceLoader, string readOnlyPath, string readWritePath, DecryptResourceCallback decryptResourceCallback) + { + if (loadResourceAgentHelper == null) + { + throw new GameFrameworkException("Load resource agent helper is invalid."); + } + + if (resourceHelper == null) + { + throw new GameFrameworkException("Resource helper is invalid."); + } + + if (resourceLoader == null) + { + throw new GameFrameworkException("Resource loader is invalid."); + } + + if (decryptResourceCallback == null) + { + throw new GameFrameworkException("Decrypt resource callback is invalid."); + } + + m_Helper = loadResourceAgentHelper; + m_ResourceHelper = resourceHelper; + m_ResourceLoader = resourceLoader; + m_ReadOnlyPath = readOnlyPath; + m_ReadWritePath = readWritePath; + m_DecryptResourceCallback = decryptResourceCallback; + m_Task = null; + } + + public ILoadResourceAgentHelper Helper + { + get + { + return m_Helper; + } + } + + /// + /// 获取加载资源任务。 + /// + public LoadResourceTaskBase Task + { + get + { + return m_Task; + } + } + + /// + /// 初始化加载资源代理。 + /// + public void Initialize() + { + m_Helper.LoadResourceAgentHelperUpdate += OnLoadResourceAgentHelperUpdate; + m_Helper.LoadResourceAgentHelperReadFileComplete += OnLoadResourceAgentHelperReadFileComplete; + m_Helper.LoadResourceAgentHelperReadBytesComplete += OnLoadResourceAgentHelperReadBytesComplete; + m_Helper.LoadResourceAgentHelperParseBytesComplete += OnLoadResourceAgentHelperParseBytesComplete; + m_Helper.LoadResourceAgentHelperLoadComplete += OnLoadResourceAgentHelperLoadComplete; + m_Helper.LoadResourceAgentHelperError += OnLoadResourceAgentHelperError; + } + + /// + /// 加载资源代理轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void Update(float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 关闭并清理加载资源代理。 + /// + public void Shutdown() + { + Reset(); + m_Helper.LoadResourceAgentHelperUpdate -= OnLoadResourceAgentHelperUpdate; + m_Helper.LoadResourceAgentHelperReadFileComplete -= OnLoadResourceAgentHelperReadFileComplete; + m_Helper.LoadResourceAgentHelperReadBytesComplete -= OnLoadResourceAgentHelperReadBytesComplete; + m_Helper.LoadResourceAgentHelperParseBytesComplete -= OnLoadResourceAgentHelperParseBytesComplete; + m_Helper.LoadResourceAgentHelperLoadComplete -= OnLoadResourceAgentHelperLoadComplete; + m_Helper.LoadResourceAgentHelperError -= OnLoadResourceAgentHelperError; + } + + public static void Clear() + { + s_CachedResourceNames.Clear(); + s_LoadingAssetNames.Clear(); + s_LoadingResourceNames.Clear(); + } + + /// + /// 开始处理加载资源任务。 + /// + /// 要处理的加载资源任务。 + /// 开始处理任务的状态。 + public StartTaskStatus Start(LoadResourceTaskBase task) + { + if (task == null) + { + throw new GameFrameworkException("Task is invalid."); + } + + m_Task = task; + m_Task.StartTime = DateTime.UtcNow; + ResourceInfo resourceInfo = m_Task.ResourceInfo; + + if (!resourceInfo.Ready) + { + m_Task.StartTime = default(DateTime); + return StartTaskStatus.HasToWait; + } + + if (IsAssetLoading(m_Task.AssetName)) + { + m_Task.StartTime = default(DateTime); + return StartTaskStatus.HasToWait; + } + + if (!m_Task.IsScene) + { + AssetObject assetObject = m_ResourceLoader.m_AssetPool.Spawn(m_Task.AssetName); + if (assetObject != null) + { + OnAssetObjectReady(assetObject); + return StartTaskStatus.Done; + } + } + + foreach (string dependencyAssetName in m_Task.GetDependencyAssetNames()) + { + if (!m_ResourceLoader.m_AssetPool.CanSpawn(dependencyAssetName)) + { + m_Task.StartTime = default(DateTime); + return StartTaskStatus.HasToWait; + } + } + + string resourceName = resourceInfo.ResourceName.Name; + if (IsResourceLoading(resourceName)) + { + m_Task.StartTime = default(DateTime); + return StartTaskStatus.HasToWait; + } + + s_LoadingAssetNames.Add(m_Task.AssetName); + + ResourceObject resourceObject = m_ResourceLoader.m_ResourcePool.Spawn(resourceName); + if (resourceObject != null) + { + OnResourceObjectReady(resourceObject); + return StartTaskStatus.CanResume; + } + + s_LoadingResourceNames.Add(resourceName); + + string fullPath = null; + if (!s_CachedResourceNames.TryGetValue(resourceName, out fullPath)) + { + fullPath = Utility.Path.GetRegularPath(Path.Combine(resourceInfo.StorageInReadOnly ? m_ReadOnlyPath : m_ReadWritePath, resourceInfo.UseFileSystem ? resourceInfo.FileSystemName : resourceInfo.ResourceName.FullName)); + s_CachedResourceNames.Add(resourceName, fullPath); + } + + if (resourceInfo.LoadType == LoadType.LoadFromFile) + { + if (resourceInfo.UseFileSystem) + { + IFileSystem fileSystem = m_ResourceLoader.m_ResourceManager.GetFileSystem(resourceInfo.FileSystemName, resourceInfo.StorageInReadOnly); + m_Helper.ReadFile(fileSystem, resourceInfo.ResourceName.FullName); + } + else + { + m_Helper.ReadFile(fullPath); + } + } + else if (resourceInfo.LoadType == LoadType.LoadFromMemory || resourceInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || resourceInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt) + { + if (resourceInfo.UseFileSystem) + { + IFileSystem fileSystem = m_ResourceLoader.m_ResourceManager.GetFileSystem(resourceInfo.FileSystemName, resourceInfo.StorageInReadOnly); + m_Helper.ReadBytes(fileSystem, resourceInfo.ResourceName.FullName); + } + else + { + m_Helper.ReadBytes(fullPath); + } + } + else + { + throw new GameFrameworkException(Utility.Text.Format("Resource load type '{0}' is not supported.", resourceInfo.LoadType)); + } + + return StartTaskStatus.CanResume; + } + + /// + /// 重置加载资源代理。 + /// + public void Reset() + { + m_Helper.Reset(); + m_Task = null; + } + + private static bool IsAssetLoading(string assetName) + { + return s_LoadingAssetNames.Contains(assetName); + } + + private static bool IsResourceLoading(string resourceName) + { + return s_LoadingResourceNames.Contains(resourceName); + } + + private void OnAssetObjectReady(AssetObject assetObject) + { + m_Helper.Reset(); + + object asset = assetObject.Target; + if (m_Task.IsScene) + { + m_ResourceLoader.m_SceneToAssetMap.Add(m_Task.AssetName, asset); + } + + m_Task.OnLoadAssetSuccess(this, asset, (float)(DateTime.UtcNow - m_Task.StartTime).TotalSeconds); + m_Task.Done = true; + } + + private void OnResourceObjectReady(ResourceObject resourceObject) + { + m_Task.LoadMain(this, resourceObject); + } + + private void OnError(LoadResourceStatus status, string errorMessage) + { + m_Helper.Reset(); + m_Task.OnLoadAssetFailure(this, status, errorMessage); + s_LoadingAssetNames.Remove(m_Task.AssetName); + s_LoadingResourceNames.Remove(m_Task.ResourceInfo.ResourceName.Name); + m_Task.Done = true; + } + + private void OnLoadResourceAgentHelperUpdate(object sender, LoadResourceAgentHelperUpdateEventArgs e) + { + m_Task.OnLoadAssetUpdate(this, e.Type, e.Progress); + } + + private void OnLoadResourceAgentHelperReadFileComplete(object sender, LoadResourceAgentHelperReadFileCompleteEventArgs e) + { + ResourceObject resourceObject = ResourceObject.Create(m_Task.ResourceInfo.ResourceName.Name, e.Resource, m_ResourceHelper, m_ResourceLoader); + m_ResourceLoader.m_ResourcePool.Register(resourceObject, true); + s_LoadingResourceNames.Remove(m_Task.ResourceInfo.ResourceName.Name); + OnResourceObjectReady(resourceObject); + } + + private void OnLoadResourceAgentHelperReadBytesComplete(object sender, LoadResourceAgentHelperReadBytesCompleteEventArgs e) + { + byte[] bytes = e.GetBytes(); + ResourceInfo resourceInfo = m_Task.ResourceInfo; + if (resourceInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || resourceInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt) + { + m_DecryptResourceCallback(bytes, 0, bytes.Length, resourceInfo.ResourceName.Name, resourceInfo.ResourceName.Variant, resourceInfo.ResourceName.Extension, resourceInfo.StorageInReadOnly, resourceInfo.FileSystemName, (byte)resourceInfo.LoadType, resourceInfo.Length, resourceInfo.HashCode); + } + + m_Helper.ParseBytes(bytes); + } + + private void OnLoadResourceAgentHelperParseBytesComplete(object sender, LoadResourceAgentHelperParseBytesCompleteEventArgs e) + { + ResourceObject resourceObject = ResourceObject.Create(m_Task.ResourceInfo.ResourceName.Name, e.Resource, m_ResourceHelper, m_ResourceLoader); + m_ResourceLoader.m_ResourcePool.Register(resourceObject, true); + s_LoadingResourceNames.Remove(m_Task.ResourceInfo.ResourceName.Name); + OnResourceObjectReady(resourceObject); + } + + private void OnLoadResourceAgentHelperLoadComplete(object sender, LoadResourceAgentHelperLoadCompleteEventArgs e) + { + AssetObject assetObject = null; + if (m_Task.IsScene) + { + assetObject = m_ResourceLoader.m_AssetPool.Spawn(m_Task.AssetName); + } + + if (assetObject == null) + { + List dependencyAssets = m_Task.GetDependencyAssets(); + assetObject = AssetObject.Create(m_Task.AssetName, e.Asset, dependencyAssets, m_Task.ResourceObject.Target, m_ResourceHelper, m_ResourceLoader); + m_ResourceLoader.m_AssetPool.Register(assetObject, true); + m_ResourceLoader.m_AssetToResourceMap.Add(e.Asset, m_Task.ResourceObject.Target); + foreach (object dependencyAsset in dependencyAssets) + { + object dependencyResource = null; + if (m_ResourceLoader.m_AssetToResourceMap.TryGetValue(dependencyAsset, out dependencyResource)) + { + m_Task.ResourceObject.AddDependencyResource(dependencyResource); + } + else + { + throw new GameFrameworkException("Can not find dependency resource."); + } + } + } + + s_LoadingAssetNames.Remove(m_Task.AssetName); + OnAssetObjectReady(assetObject); + } + + private void OnLoadResourceAgentHelperError(object sender, LoadResourceAgentHelperErrorEventArgs e) + { + OnError(e.Status, e.ErrorMessage); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadResourceAgent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadResourceAgent.cs.meta new file mode 100644 index 0000000..e49e493 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadResourceAgent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9ce574a2d7f6ce54d9bf8c542a7c8953 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadResourceTaskBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadResourceTaskBase.cs new file mode 100644 index 0000000..b371f1e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadResourceTaskBase.cs @@ -0,0 +1,176 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceLoader + { + private abstract class LoadResourceTaskBase : TaskBase + { + private static int s_Serial = 0; + + private string m_AssetName; + private Type m_AssetType; + private ResourceInfo m_ResourceInfo; + private string[] m_DependencyAssetNames; + private readonly List m_DependencyAssets; + private ResourceObject m_ResourceObject; + private DateTime m_StartTime; + private int m_TotalDependencyAssetCount; + + public LoadResourceTaskBase() + { + m_AssetName = null; + m_AssetType = null; + m_ResourceInfo = null; + m_DependencyAssetNames = null; + m_DependencyAssets = new List(); + m_ResourceObject = null; + m_StartTime = default(DateTime); + m_TotalDependencyAssetCount = 0; + } + + public string AssetName + { + get + { + return m_AssetName; + } + } + + public Type AssetType + { + get + { + return m_AssetType; + } + } + + public ResourceInfo ResourceInfo + { + get + { + return m_ResourceInfo; + } + } + + public ResourceObject ResourceObject + { + get + { + return m_ResourceObject; + } + } + + public abstract bool IsScene + { + get; + } + + public DateTime StartTime + { + get + { + return m_StartTime; + } + set + { + m_StartTime = value; + } + } + + public int LoadedDependencyAssetCount + { + get + { + return m_DependencyAssets.Count; + } + } + + public int TotalDependencyAssetCount + { + get + { + return m_TotalDependencyAssetCount; + } + set + { + m_TotalDependencyAssetCount = value; + } + } + + public override string Description + { + get + { + return m_AssetName; + } + } + + public override void Clear() + { + base.Clear(); + m_AssetName = null; + m_AssetType = null; + m_ResourceInfo = null; + m_DependencyAssetNames = null; + m_DependencyAssets.Clear(); + m_ResourceObject = null; + m_StartTime = default(DateTime); + m_TotalDependencyAssetCount = 0; + } + + public string[] GetDependencyAssetNames() + { + return m_DependencyAssetNames; + } + + public List GetDependencyAssets() + { + return m_DependencyAssets; + } + + public void LoadMain(LoadResourceAgent agent, ResourceObject resourceObject) + { + m_ResourceObject = resourceObject; + agent.Helper.LoadAsset(resourceObject.Target, AssetName, AssetType, IsScene); + } + + public virtual void OnLoadAssetSuccess(LoadResourceAgent agent, object asset, float duration) + { + } + + public virtual void OnLoadAssetFailure(LoadResourceAgent agent, LoadResourceStatus status, string errorMessage) + { + } + + public virtual void OnLoadAssetUpdate(LoadResourceAgent agent, LoadResourceProgress type, float progress) + { + } + + public virtual void OnLoadDependencyAsset(LoadResourceAgent agent, string dependencyAssetName, object dependencyAsset) + { + m_DependencyAssets.Add(dependencyAsset); + } + + protected void Initialize(string assetName, Type assetType, int priority, ResourceInfo resourceInfo, string[] dependencyAssetNames, object userData) + { + Initialize(++s_Serial, null, priority, userData); + m_AssetName = assetName; + m_AssetType = assetType; + m_ResourceInfo = resourceInfo; + m_DependencyAssetNames = dependencyAssetNames; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadResourceTaskBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadResourceTaskBase.cs.meta new file mode 100644 index 0000000..9e9381e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadResourceTaskBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8306fa8150358e741a9c7e1f177ea2e1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadSceneTask.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadSceneTask.cs new file mode 100644 index 0000000..0ed85f5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadSceneTask.cs @@ -0,0 +1,86 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceLoader + { + private sealed class LoadSceneTask : LoadResourceTaskBase + { + private LoadSceneCallbacks m_LoadSceneCallbacks; + + public LoadSceneTask() + { + m_LoadSceneCallbacks = null; + } + + public override bool IsScene + { + get + { + return true; + } + } + + public static LoadSceneTask Create(string sceneAssetName, int priority, ResourceInfo resourceInfo, string[] dependencyAssetNames, LoadSceneCallbacks loadSceneCallbacks, object userData) + { + LoadSceneTask loadSceneTask = ReferencePool.Acquire(); + loadSceneTask.Initialize(sceneAssetName, null, priority, resourceInfo, dependencyAssetNames, userData); + loadSceneTask.m_LoadSceneCallbacks = loadSceneCallbacks; + return loadSceneTask; + } + + public override void Clear() + { + base.Clear(); + m_LoadSceneCallbacks = null; + } + + public override void OnLoadAssetSuccess(LoadResourceAgent agent, object asset, float duration) + { + base.OnLoadAssetSuccess(agent, asset, duration); + if (m_LoadSceneCallbacks.LoadSceneSuccessCallback != null) + { + m_LoadSceneCallbacks.LoadSceneSuccessCallback(AssetName, duration, UserData); + } + } + + public override void OnLoadAssetFailure(LoadResourceAgent agent, LoadResourceStatus status, string errorMessage) + { + base.OnLoadAssetFailure(agent, status, errorMessage); + if (m_LoadSceneCallbacks.LoadSceneFailureCallback != null) + { + m_LoadSceneCallbacks.LoadSceneFailureCallback(AssetName, status, errorMessage, UserData); + } + } + + public override void OnLoadAssetUpdate(LoadResourceAgent agent, LoadResourceProgress type, float progress) + { + base.OnLoadAssetUpdate(agent, type, progress); + if (type == LoadResourceProgress.LoadScene) + { + if (m_LoadSceneCallbacks.LoadSceneUpdateCallback != null) + { + m_LoadSceneCallbacks.LoadSceneUpdateCallback(AssetName, progress, UserData); + } + } + } + + public override void OnLoadDependencyAsset(LoadResourceAgent agent, string dependencyAssetName, object dependencyAsset) + { + base.OnLoadDependencyAsset(agent, dependencyAssetName, dependencyAsset); + if (m_LoadSceneCallbacks.LoadSceneDependencyAssetCallback != null) + { + m_LoadSceneCallbacks.LoadSceneDependencyAssetCallback(AssetName, dependencyAssetName, LoadedDependencyAssetCount, TotalDependencyAssetCount, UserData); + } + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadSceneTask.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadSceneTask.cs.meta new file mode 100644 index 0000000..ba54c82 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.LoadSceneTask.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3dc9da29e59fb9343907f59377c06f41 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.ResourceObject.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.ResourceObject.cs new file mode 100644 index 0000000..9242566 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.ResourceObject.cs @@ -0,0 +1,125 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.ObjectPool; +using System.Collections.Generic; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceLoader + { + /// + /// 资源对象。 + /// + private sealed class ResourceObject : ObjectBase + { + private List m_DependencyResources; + private IResourceHelper m_ResourceHelper; + private ResourceLoader m_ResourceLoader; + + public ResourceObject() + { + m_DependencyResources = new List(); + m_ResourceHelper = null; + m_ResourceLoader = null; + } + + public override bool CustomCanReleaseFlag + { + get + { + int targetReferenceCount = 0; + m_ResourceLoader.m_ResourceDependencyCount.TryGetValue(Target, out targetReferenceCount); + return base.CustomCanReleaseFlag && targetReferenceCount <= 0; + } + } + + public static ResourceObject Create(string name, object target, IResourceHelper resourceHelper, ResourceLoader resourceLoader) + { + if (resourceHelper == null) + { + throw new GameFrameworkException("Resource helper is invalid."); + } + + if (resourceLoader == null) + { + throw new GameFrameworkException("Resource loader is invalid."); + } + + ResourceObject resourceObject = ReferencePool.Acquire(); + resourceObject.Initialize(name, target); + resourceObject.m_ResourceHelper = resourceHelper; + resourceObject.m_ResourceLoader = resourceLoader; + return resourceObject; + } + + public override void Clear() + { + base.Clear(); + m_DependencyResources.Clear(); + m_ResourceHelper = null; + m_ResourceLoader = null; + } + + public void AddDependencyResource(object dependencyResource) + { + if (Target == dependencyResource) + { + return; + } + + if (m_DependencyResources.Contains(dependencyResource)) + { + return; + } + + m_DependencyResources.Add(dependencyResource); + + int referenceCount = 0; + if (m_ResourceLoader.m_ResourceDependencyCount.TryGetValue(dependencyResource, out referenceCount)) + { + m_ResourceLoader.m_ResourceDependencyCount[dependencyResource] = referenceCount + 1; + } + else + { + m_ResourceLoader.m_ResourceDependencyCount.Add(dependencyResource, 1); + } + } + + protected internal override void Release(bool isShutdown) + { + if (!isShutdown) + { + int targetReferenceCount = 0; + if (m_ResourceLoader.m_ResourceDependencyCount.TryGetValue(Target, out targetReferenceCount) && targetReferenceCount > 0) + { + throw new GameFrameworkException(Utility.Text.Format("Resource target '{0}' reference count is '{1}' larger than 0.", Name, targetReferenceCount)); + } + + foreach (object dependencyResource in m_DependencyResources) + { + int referenceCount = 0; + if (m_ResourceLoader.m_ResourceDependencyCount.TryGetValue(dependencyResource, out referenceCount)) + { + m_ResourceLoader.m_ResourceDependencyCount[dependencyResource] = referenceCount - 1; + } + else + { + throw new GameFrameworkException(Utility.Text.Format("Resource target '{0}' dependency asset reference count is invalid.", Name)); + } + } + } + + m_ResourceLoader.m_ResourceDependencyCount.Remove(Target); + m_ResourceHelper.Release(Target); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.ResourceObject.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.ResourceObject.cs.meta new file mode 100644 index 0000000..32d2856 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.ResourceObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 48616724889f3194daed53813ae1c35b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.cs new file mode 100644 index 0000000..4659931 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.cs @@ -0,0 +1,943 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.FileSystem; +using GameFramework.ObjectPool; +using System; +using System.Collections.Generic; +using System.IO; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 加载资源器。 + /// + private sealed partial class ResourceLoader + { + private const int CachedHashBytesLength = 4; + + private readonly ResourceManager m_ResourceManager; + private readonly TaskPool m_TaskPool; + private readonly Dictionary m_AssetDependencyCount; + private readonly Dictionary m_ResourceDependencyCount; + private readonly Dictionary m_AssetToResourceMap; + private readonly Dictionary m_SceneToAssetMap; + private readonly LoadBytesCallbacks m_LoadBytesCallbacks; + private readonly byte[] m_CachedHashBytes; + private IObjectPool m_AssetPool; + private IObjectPool m_ResourcePool; + + /// + /// 初始化加载资源器的新实例。 + /// + /// 资源管理器。 + public ResourceLoader(ResourceManager resourceManager) + { + m_ResourceManager = resourceManager; + m_TaskPool = new TaskPool(); + m_AssetDependencyCount = new Dictionary(); + m_ResourceDependencyCount = new Dictionary(); + m_AssetToResourceMap = new Dictionary(); + m_SceneToAssetMap = new Dictionary(StringComparer.Ordinal); + m_LoadBytesCallbacks = new LoadBytesCallbacks(OnLoadBinarySuccess, OnLoadBinaryFailure); + m_CachedHashBytes = new byte[CachedHashBytesLength]; + m_AssetPool = null; + m_ResourcePool = null; + } + + /// + /// 获取加载资源代理总数量。 + /// + public int TotalAgentCount + { + get + { + return m_TaskPool.TotalAgentCount; + } + } + + /// + /// 获取可用加载资源代理数量。 + /// + public int FreeAgentCount + { + get + { + return m_TaskPool.FreeAgentCount; + } + } + + /// + /// 获取工作中加载资源代理数量。 + /// + public int WorkingAgentCount + { + get + { + return m_TaskPool.WorkingAgentCount; + } + } + + /// + /// 获取等待加载资源任务数量。 + /// + public int WaitingTaskCount + { + get + { + return m_TaskPool.WaitingTaskCount; + } + } + + /// + /// 获取或设置资源对象池自动释放可释放对象的间隔秒数。 + /// + public float AssetAutoReleaseInterval + { + get + { + return m_AssetPool.AutoReleaseInterval; + } + set + { + m_AssetPool.AutoReleaseInterval = value; + } + } + + /// + /// 获取或设置资源对象池的容量。 + /// + public int AssetCapacity + { + get + { + return m_AssetPool.Capacity; + } + set + { + m_AssetPool.Capacity = value; + } + } + + /// + /// 获取或设置资源对象池对象过期秒数。 + /// + public float AssetExpireTime + { + get + { + return m_AssetPool.ExpireTime; + } + set + { + m_AssetPool.ExpireTime = value; + } + } + + /// + /// 获取或设置资源对象池的优先级。 + /// + public int AssetPriority + { + get + { + return m_AssetPool.Priority; + } + set + { + m_AssetPool.Priority = value; + } + } + + /// + /// 获取或设置资源对象池自动释放可释放对象的间隔秒数。 + /// + public float ResourceAutoReleaseInterval + { + get + { + return m_ResourcePool.AutoReleaseInterval; + } + set + { + m_ResourcePool.AutoReleaseInterval = value; + } + } + + /// + /// 获取或设置资源对象池的容量。 + /// + public int ResourceCapacity + { + get + { + return m_ResourcePool.Capacity; + } + set + { + m_ResourcePool.Capacity = value; + } + } + + /// + /// 获取或设置资源对象池对象过期秒数。 + /// + public float ResourceExpireTime + { + get + { + return m_ResourcePool.ExpireTime; + } + set + { + m_ResourcePool.ExpireTime = value; + } + } + + /// + /// 获取或设置资源对象池的优先级。 + /// + public int ResourcePriority + { + get + { + return m_ResourcePool.Priority; + } + set + { + m_ResourcePool.Priority = value; + } + } + + /// + /// 加载资源器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void Update(float elapseSeconds, float realElapseSeconds) + { + m_TaskPool.Update(elapseSeconds, realElapseSeconds); + } + + /// + /// 关闭并清理加载资源器。 + /// + public void Shutdown() + { + m_TaskPool.Shutdown(); + m_AssetDependencyCount.Clear(); + m_ResourceDependencyCount.Clear(); + m_AssetToResourceMap.Clear(); + m_SceneToAssetMap.Clear(); + LoadResourceAgent.Clear(); + } + + /// + /// 设置对象池管理器。 + /// + /// 对象池管理器。 + public void SetObjectPoolManager(IObjectPoolManager objectPoolManager) + { + m_AssetPool = objectPoolManager.CreateMultiSpawnObjectPool("Asset Pool"); + m_ResourcePool = objectPoolManager.CreateMultiSpawnObjectPool("Resource Pool"); + } + + /// + /// 增加加载资源代理辅助器。 + /// + /// 要增加的加载资源代理辅助器。 + /// 资源辅助器。 + /// 资源只读区路径。 + /// 资源读写区路径。 + /// 要设置的解密资源回调函数。 + public void AddLoadResourceAgentHelper(ILoadResourceAgentHelper loadResourceAgentHelper, IResourceHelper resourceHelper, string readOnlyPath, string readWritePath, DecryptResourceCallback decryptResourceCallback) + { + if (m_AssetPool == null || m_ResourcePool == null) + { + throw new GameFrameworkException("You must set object pool manager first."); + } + + LoadResourceAgent agent = new LoadResourceAgent(loadResourceAgentHelper, resourceHelper, this, readOnlyPath, readWritePath, decryptResourceCallback ?? DefaultDecryptResourceCallback); + m_TaskPool.AddAgent(agent); + } + + /// + /// 检查资源是否存在。 + /// + /// 要检查资源的名称。 + /// 检查资源是否存在的结果。 + public HasAssetResult HasAsset(string assetName) + { + ResourceInfo resourceInfo = GetResourceInfo(assetName); + if (resourceInfo == null) + { + return HasAssetResult.NotExist; + } + + if (!resourceInfo.Ready && m_ResourceManager.m_ResourceMode != ResourceMode.UpdatableWhilePlaying) + { + return HasAssetResult.NotReady; + } + + if (resourceInfo.UseFileSystem) + { + return resourceInfo.IsLoadFromBinary ? HasAssetResult.BinaryOnFileSystem : HasAssetResult.AssetOnFileSystem; + } + else + { + return resourceInfo.IsLoadFromBinary ? HasAssetResult.BinaryOnDisk : HasAssetResult.AssetOnDisk; + } + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, Type assetType, int priority, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + ResourceInfo resourceInfo = null; + string[] dependencyAssetNames = null; + if (!CheckAsset(assetName, out resourceInfo, out dependencyAssetNames)) + { + string errorMessage = Utility.Text.Format("Can not load asset '{0}'.", assetName); + if (loadAssetCallbacks.LoadAssetFailureCallback != null) + { + loadAssetCallbacks.LoadAssetFailureCallback(assetName, resourceInfo != null && !resourceInfo.Ready ? LoadResourceStatus.NotReady : LoadResourceStatus.NotExist, errorMessage, userData); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + if (resourceInfo.IsLoadFromBinary) + { + string errorMessage = Utility.Text.Format("Can not load asset '{0}' which is a binary asset.", assetName); + if (loadAssetCallbacks.LoadAssetFailureCallback != null) + { + loadAssetCallbacks.LoadAssetFailureCallback(assetName, LoadResourceStatus.TypeError, errorMessage, userData); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + LoadAssetTask mainTask = LoadAssetTask.Create(assetName, assetType, priority, resourceInfo, dependencyAssetNames, loadAssetCallbacks, userData); + foreach (string dependencyAssetName in dependencyAssetNames) + { + if (!LoadDependencyAsset(dependencyAssetName, priority, mainTask, userData)) + { + string errorMessage = Utility.Text.Format("Can not load dependency asset '{0}' when load asset '{1}'.", dependencyAssetName, assetName); + if (loadAssetCallbacks.LoadAssetFailureCallback != null) + { + loadAssetCallbacks.LoadAssetFailureCallback(assetName, LoadResourceStatus.DependencyError, errorMessage, userData); + return; + } + + throw new GameFrameworkException(errorMessage); + } + } + + m_TaskPool.AddTask(mainTask); + if (!resourceInfo.Ready) + { + m_ResourceManager.UpdateResource(resourceInfo.ResourceName); + } + } + + /// + /// 卸载资源。 + /// + /// 要卸载的资源。 + public void UnloadAsset(object asset) + { + m_AssetPool.Unspawn(asset); + } + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景资源的优先级。 + /// 加载场景回调函数集。 + /// 用户自定义数据。 + public void LoadScene(string sceneAssetName, int priority, LoadSceneCallbacks loadSceneCallbacks, object userData) + { + ResourceInfo resourceInfo = null; + string[] dependencyAssetNames = null; + if (!CheckAsset(sceneAssetName, out resourceInfo, out dependencyAssetNames)) + { + string errorMessage = Utility.Text.Format("Can not load scene '{0}'.", sceneAssetName); + if (loadSceneCallbacks.LoadSceneFailureCallback != null) + { + loadSceneCallbacks.LoadSceneFailureCallback(sceneAssetName, resourceInfo != null && !resourceInfo.Ready ? LoadResourceStatus.NotReady : LoadResourceStatus.NotExist, errorMessage, userData); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + if (resourceInfo.IsLoadFromBinary) + { + string errorMessage = Utility.Text.Format("Can not load scene asset '{0}' which is a binary asset.", sceneAssetName); + if (loadSceneCallbacks.LoadSceneFailureCallback != null) + { + loadSceneCallbacks.LoadSceneFailureCallback(sceneAssetName, LoadResourceStatus.TypeError, errorMessage, userData); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + LoadSceneTask mainTask = LoadSceneTask.Create(sceneAssetName, priority, resourceInfo, dependencyAssetNames, loadSceneCallbacks, userData); + foreach (string dependencyAssetName in dependencyAssetNames) + { + if (!LoadDependencyAsset(dependencyAssetName, priority, mainTask, userData)) + { + string errorMessage = Utility.Text.Format("Can not load dependency asset '{0}' when load scene '{1}'.", dependencyAssetName, sceneAssetName); + if (loadSceneCallbacks.LoadSceneFailureCallback != null) + { + loadSceneCallbacks.LoadSceneFailureCallback(sceneAssetName, LoadResourceStatus.DependencyError, errorMessage, userData); + return; + } + + throw new GameFrameworkException(errorMessage); + } + } + + m_TaskPool.AddTask(mainTask); + if (!resourceInfo.Ready) + { + m_ResourceManager.UpdateResource(resourceInfo.ResourceName); + } + } + + /// + /// 异步卸载场景。 + /// + /// 要卸载场景资源的名称。 + /// 卸载场景回调函数集。 + /// 用户自定义数据。 + public void UnloadScene(string sceneAssetName, UnloadSceneCallbacks unloadSceneCallbacks, object userData) + { + if (m_ResourceManager.m_ResourceHelper == null) + { + throw new GameFrameworkException("You must set resource helper first."); + } + + object asset = null; + if (m_SceneToAssetMap.TryGetValue(sceneAssetName, out asset)) + { + m_SceneToAssetMap.Remove(sceneAssetName); + m_AssetPool.Unspawn(asset); + m_AssetPool.ReleaseObject(asset); + } + else + { + throw new GameFrameworkException(Utility.Text.Format("Can not find asset of scene '{0}'.", sceneAssetName)); + } + + m_ResourceManager.m_ResourceHelper.UnloadScene(sceneAssetName, unloadSceneCallbacks, userData); + } + + /// + /// 获取二进制资源的实际路径。 + /// + /// 要获取实际路径的二进制资源的名称。 + /// 二进制资源的实际路径。 + /// 此方法仅适用于二进制资源存储在磁盘(而非文件系统)中的情况。若二进制资源存储在文件系统中时,返回值将始终为空。 + public string GetBinaryPath(string binaryAssetName) + { + ResourceInfo resourceInfo = GetResourceInfo(binaryAssetName); + if (resourceInfo == null) + { + return null; + } + + if (!resourceInfo.Ready) + { + return null; + } + + if (!resourceInfo.IsLoadFromBinary) + { + return null; + } + + if (resourceInfo.UseFileSystem) + { + return null; + } + + return Utility.Path.GetRegularPath(Path.Combine(resourceInfo.StorageInReadOnly ? m_ResourceManager.m_ReadOnlyPath : m_ResourceManager.m_ReadWritePath, resourceInfo.ResourceName.FullName)); + } + + /// + /// 获取二进制资源的实际路径。 + /// + /// 要获取实际路径的二进制资源的名称。 + /// 二进制资源是否存储在只读区中。 + /// 二进制资源是否存储在文件系统中。 + /// 二进制资源或存储二进制资源的文件系统,相对于只读区或者读写区的相对路径。 + /// 若二进制资源存储在文件系统中,则指示二进制资源在文件系统中的名称,否则此参数返回空。 + /// 是否获取二进制资源的实际路径成功。 + public bool GetBinaryPath(string binaryAssetName, out bool storageInReadOnly, out bool storageInFileSystem, out string relativePath, out string fileName) + { + storageInReadOnly = false; + storageInFileSystem = false; + relativePath = null; + fileName = null; + + ResourceInfo resourceInfo = GetResourceInfo(binaryAssetName); + if (resourceInfo == null) + { + return false; + } + + if (!resourceInfo.Ready) + { + return false; + } + + if (!resourceInfo.IsLoadFromBinary) + { + return false; + } + + storageInReadOnly = resourceInfo.StorageInReadOnly; + if (resourceInfo.UseFileSystem) + { + storageInFileSystem = true; + relativePath = Utility.Text.Format("{0}.{1}", resourceInfo.FileSystemName, DefaultExtension); + fileName = resourceInfo.ResourceName.FullName; + } + else + { + relativePath = resourceInfo.ResourceName.FullName; + } + + return true; + } + + /// + /// 获取二进制资源的长度。 + /// + /// 要获取长度的二进制资源的名称。 + /// 二进制资源的长度。 + public int GetBinaryLength(string binaryAssetName) + { + ResourceInfo resourceInfo = GetResourceInfo(binaryAssetName); + if (resourceInfo == null) + { + return -1; + } + + if (!resourceInfo.Ready) + { + return -1; + } + + if (!resourceInfo.IsLoadFromBinary) + { + return -1; + } + + return resourceInfo.Length; + } + + /// + /// 异步加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 加载二进制资源回调函数集。 + /// 用户自定义数据。 + public void LoadBinary(string binaryAssetName, LoadBinaryCallbacks loadBinaryCallbacks, object userData) + { + ResourceInfo resourceInfo = GetResourceInfo(binaryAssetName); + if (resourceInfo == null) + { + string errorMessage = Utility.Text.Format("Can not load binary '{0}' which is not exist.", binaryAssetName); + if (loadBinaryCallbacks.LoadBinaryFailureCallback != null) + { + loadBinaryCallbacks.LoadBinaryFailureCallback(binaryAssetName, LoadResourceStatus.NotExist, errorMessage, userData); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + if (!resourceInfo.Ready) + { + string errorMessage = Utility.Text.Format("Can not load binary '{0}' which is not ready.", binaryAssetName); + if (loadBinaryCallbacks.LoadBinaryFailureCallback != null) + { + loadBinaryCallbacks.LoadBinaryFailureCallback(binaryAssetName, LoadResourceStatus.NotReady, errorMessage, userData); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + if (!resourceInfo.IsLoadFromBinary) + { + string errorMessage = Utility.Text.Format("Can not load binary '{0}' which is not a binary asset.", binaryAssetName); + if (loadBinaryCallbacks.LoadBinaryFailureCallback != null) + { + loadBinaryCallbacks.LoadBinaryFailureCallback(binaryAssetName, LoadResourceStatus.TypeError, errorMessage, userData); + return; + } + + throw new GameFrameworkException(errorMessage); + } + + if (resourceInfo.UseFileSystem) + { + loadBinaryCallbacks.LoadBinarySuccessCallback(binaryAssetName, LoadBinaryFromFileSystem(binaryAssetName), 0f, userData); + } + else + { + string path = Utility.Path.GetRemotePath(Path.Combine(resourceInfo.StorageInReadOnly ? m_ResourceManager.m_ReadOnlyPath : m_ResourceManager.m_ReadWritePath, resourceInfo.ResourceName.FullName)); + m_ResourceManager.m_ResourceHelper.LoadBytes(path, m_LoadBytesCallbacks, LoadBinaryInfo.Create(binaryAssetName, resourceInfo, loadBinaryCallbacks, userData)); + } + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + public byte[] LoadBinaryFromFileSystem(string binaryAssetName) + { + ResourceInfo resourceInfo = GetResourceInfo(binaryAssetName); + if (resourceInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not exist.", binaryAssetName)); + } + + if (!resourceInfo.Ready) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not ready.", binaryAssetName)); + } + + if (!resourceInfo.IsLoadFromBinary) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not a binary asset.", binaryAssetName)); + } + + if (!resourceInfo.UseFileSystem) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not use file system.", binaryAssetName)); + } + + IFileSystem fileSystem = m_ResourceManager.GetFileSystem(resourceInfo.FileSystemName, resourceInfo.StorageInReadOnly); + byte[] bytes = fileSystem.ReadFile(resourceInfo.ResourceName.FullName); + if (bytes == null) + { + return null; + } + + if (resourceInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || resourceInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + DecryptResourceCallback decryptResourceCallback = m_ResourceManager.m_DecryptResourceCallback ?? DefaultDecryptResourceCallback; + decryptResourceCallback(bytes, 0, bytes.Length, resourceInfo.ResourceName.Name, resourceInfo.ResourceName.Variant, resourceInfo.ResourceName.Extension, resourceInfo.StorageInReadOnly, resourceInfo.FileSystemName, (byte)resourceInfo.LoadType, resourceInfo.Length, resourceInfo.HashCode); + } + + return bytes; + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 存储加载二进制资源的二进制流的起始位置。 + /// 存储加载二进制资源的二进制流的长度。 + /// 实际加载了多少字节。 + public int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex, int length) + { + ResourceInfo resourceInfo = GetResourceInfo(binaryAssetName); + if (resourceInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not exist.", binaryAssetName)); + } + + if (!resourceInfo.Ready) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not ready.", binaryAssetName)); + } + + if (!resourceInfo.IsLoadFromBinary) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not a binary asset.", binaryAssetName)); + } + + if (!resourceInfo.UseFileSystem) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not use file system.", binaryAssetName)); + } + + IFileSystem fileSystem = m_ResourceManager.GetFileSystem(resourceInfo.FileSystemName, resourceInfo.StorageInReadOnly); + int bytesRead = fileSystem.ReadFile(resourceInfo.ResourceName.FullName, buffer, startIndex, length); + if (resourceInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || resourceInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + DecryptResourceCallback decryptResourceCallback = m_ResourceManager.m_DecryptResourceCallback ?? DefaultDecryptResourceCallback; + decryptResourceCallback(buffer, startIndex, bytesRead, resourceInfo.ResourceName.Name, resourceInfo.ResourceName.Variant, resourceInfo.ResourceName.Extension, resourceInfo.StorageInReadOnly, resourceInfo.FileSystemName, (byte)resourceInfo.LoadType, resourceInfo.Length, resourceInfo.HashCode); + } + + return bytesRead; + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 要加载片段的长度。 + /// 存储加载二进制资源片段内容的二进制流。 + public byte[] LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, int length) + { + ResourceInfo resourceInfo = GetResourceInfo(binaryAssetName); + if (resourceInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not exist.", binaryAssetName)); + } + + if (!resourceInfo.Ready) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not ready.", binaryAssetName)); + } + + if (!resourceInfo.IsLoadFromBinary) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not a binary asset.", binaryAssetName)); + } + + if (!resourceInfo.UseFileSystem) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not use file system.", binaryAssetName)); + } + + IFileSystem fileSystem = m_ResourceManager.GetFileSystem(resourceInfo.FileSystemName, resourceInfo.StorageInReadOnly); + byte[] bytes = fileSystem.ReadFileSegment(resourceInfo.ResourceName.FullName, offset, length); + if (bytes == null) + { + return null; + } + + if (resourceInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || resourceInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + DecryptResourceCallback decryptResourceCallback = m_ResourceManager.m_DecryptResourceCallback ?? DefaultDecryptResourceCallback; + decryptResourceCallback(bytes, 0, bytes.Length, resourceInfo.ResourceName.Name, resourceInfo.ResourceName.Variant, resourceInfo.ResourceName.Extension, resourceInfo.StorageInReadOnly, resourceInfo.FileSystemName, (byte)resourceInfo.LoadType, resourceInfo.Length, resourceInfo.HashCode); + } + + return bytes; + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 存储加载二进制资源片段内容的二进制流的起始位置。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer, int startIndex, int length) + { + ResourceInfo resourceInfo = GetResourceInfo(binaryAssetName); + if (resourceInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not exist.", binaryAssetName)); + } + + if (!resourceInfo.Ready) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not ready.", binaryAssetName)); + } + + if (!resourceInfo.IsLoadFromBinary) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not a binary asset.", binaryAssetName)); + } + + if (!resourceInfo.UseFileSystem) + { + throw new GameFrameworkException(Utility.Text.Format("Can not load binary '{0}' from file system which is not use file system.", binaryAssetName)); + } + + IFileSystem fileSystem = m_ResourceManager.GetFileSystem(resourceInfo.FileSystemName, resourceInfo.StorageInReadOnly); + int bytesRead = fileSystem.ReadFileSegment(resourceInfo.ResourceName.FullName, offset, buffer, startIndex, length); + if (resourceInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || resourceInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + DecryptResourceCallback decryptResourceCallback = m_ResourceManager.m_DecryptResourceCallback ?? DefaultDecryptResourceCallback; + decryptResourceCallback(buffer, startIndex, bytesRead, resourceInfo.ResourceName.Name, resourceInfo.ResourceName.Variant, resourceInfo.ResourceName.Extension, resourceInfo.StorageInReadOnly, resourceInfo.FileSystemName, (byte)resourceInfo.LoadType, resourceInfo.Length, resourceInfo.HashCode); + } + + return bytesRead; + } + + /// + /// 获取所有加载资源任务的信息。 + /// + /// 所有加载资源任务的信息。 + public TaskInfo[] GetAllLoadAssetInfos() + { + return m_TaskPool.GetAllTaskInfos(); + } + + /// + /// 获取所有加载资源任务的信息。 + /// + /// 所有加载资源任务的信息。 + public void GetAllLoadAssetInfos(List results) + { + m_TaskPool.GetAllTaskInfos(results); + } + + private bool LoadDependencyAsset(string assetName, int priority, LoadResourceTaskBase mainTask, object userData) + { + if (mainTask == null) + { + throw new GameFrameworkException("Main task is invalid."); + } + + ResourceInfo resourceInfo = null; + string[] dependencyAssetNames = null; + if (!CheckAsset(assetName, out resourceInfo, out dependencyAssetNames)) + { + return false; + } + + if (resourceInfo.IsLoadFromBinary) + { + return false; + } + + LoadDependencyAssetTask dependencyTask = LoadDependencyAssetTask.Create(assetName, priority, resourceInfo, dependencyAssetNames, mainTask, userData); + foreach (string dependencyAssetName in dependencyAssetNames) + { + if (!LoadDependencyAsset(dependencyAssetName, priority, dependencyTask, userData)) + { + return false; + } + } + + m_TaskPool.AddTask(dependencyTask); + if (!resourceInfo.Ready) + { + m_ResourceManager.UpdateResource(resourceInfo.ResourceName); + } + + return true; + } + + private ResourceInfo GetResourceInfo(string assetName) + { + if (string.IsNullOrEmpty(assetName)) + { + return null; + } + + AssetInfo assetInfo = m_ResourceManager.GetAssetInfo(assetName); + if (assetInfo == null) + { + return null; + } + + return m_ResourceManager.GetResourceInfo(assetInfo.ResourceName); + } + + private bool CheckAsset(string assetName, out ResourceInfo resourceInfo, out string[] dependencyAssetNames) + { + resourceInfo = null; + dependencyAssetNames = null; + + if (string.IsNullOrEmpty(assetName)) + { + return false; + } + + AssetInfo assetInfo = m_ResourceManager.GetAssetInfo(assetName); + if (assetInfo == null) + { + return false; + } + + resourceInfo = m_ResourceManager.GetResourceInfo(assetInfo.ResourceName); + if (resourceInfo == null) + { + return false; + } + + dependencyAssetNames = assetInfo.GetDependencyAssetNames(); + return m_ResourceManager.m_ResourceMode == ResourceMode.UpdatableWhilePlaying ? true : resourceInfo.Ready; + } + + private void DefaultDecryptResourceCallback(byte[] bytes, int startIndex, int count, string name, string variant, string extension, bool storageInReadOnly, string fileSystem, byte loadType, int length, int hashCode) + { + Utility.Converter.GetBytes(hashCode, m_CachedHashBytes); + switch ((LoadType)loadType) + { + case LoadType.LoadFromMemoryAndQuickDecrypt: + case LoadType.LoadFromBinaryAndQuickDecrypt: + Utility.Encryption.GetQuickSelfXorBytes(bytes, m_CachedHashBytes); + break; + + case LoadType.LoadFromMemoryAndDecrypt: + case LoadType.LoadFromBinaryAndDecrypt: + Utility.Encryption.GetSelfXorBytes(bytes, m_CachedHashBytes); + break; + + default: + throw new GameFrameworkException("Not supported load type when decrypt resource."); + } + + Array.Clear(m_CachedHashBytes, 0, CachedHashBytesLength); + } + + private void OnLoadBinarySuccess(string fileUri, byte[] bytes, float duration, object userData) + { + LoadBinaryInfo loadBinaryInfo = (LoadBinaryInfo)userData; + if (loadBinaryInfo == null) + { + throw new GameFrameworkException("Load binary info is invalid."); + } + + ResourceInfo resourceInfo = loadBinaryInfo.ResourceInfo; + if (resourceInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || resourceInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + DecryptResourceCallback decryptResourceCallback = m_ResourceManager.m_DecryptResourceCallback ?? DefaultDecryptResourceCallback; + decryptResourceCallback(bytes, 0, bytes.Length, resourceInfo.ResourceName.Name, resourceInfo.ResourceName.Variant, resourceInfo.ResourceName.Extension, resourceInfo.StorageInReadOnly, resourceInfo.FileSystemName, (byte)resourceInfo.LoadType, resourceInfo.Length, resourceInfo.HashCode); + } + + loadBinaryInfo.LoadBinaryCallbacks.LoadBinarySuccessCallback(loadBinaryInfo.BinaryAssetName, bytes, duration, loadBinaryInfo.UserData); + ReferencePool.Release(loadBinaryInfo); + } + + private void OnLoadBinaryFailure(string fileUri, string errorMessage, object userData) + { + LoadBinaryInfo loadBinaryInfo = (LoadBinaryInfo)userData; + if (loadBinaryInfo == null) + { + throw new GameFrameworkException("Load binary info is invalid."); + } + + if (loadBinaryInfo.LoadBinaryCallbacks.LoadBinaryFailureCallback != null) + { + loadBinaryInfo.LoadBinaryCallbacks.LoadBinaryFailureCallback(loadBinaryInfo.BinaryAssetName, LoadResourceStatus.AssetError, errorMessage, loadBinaryInfo.UserData); + } + + ReferencePool.Release(loadBinaryInfo); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.cs.meta new file mode 100644 index 0000000..4784739 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceLoader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 514dc011c4ef43c4b9e6ede6767dd547 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceName.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceName.cs new file mode 100644 index 0000000..2a077e6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceName.cs @@ -0,0 +1,168 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 资源名称。 + /// + [StructLayout(LayoutKind.Auto)] + private struct ResourceName : IComparable, IComparable, IEquatable + { + private static readonly Dictionary s_ResourceFullNames = new Dictionary(); + + private readonly string m_Name; + private readonly string m_Variant; + private readonly string m_Extension; + + /// + /// 初始化资源名称的新实例。 + /// + /// 资源名称。 + /// 变体名称。 + /// 扩展名称。 + public ResourceName(string name, string variant, string extension) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Resource name is invalid."); + } + + if (string.IsNullOrEmpty(extension)) + { + throw new GameFrameworkException("Resource extension is invalid."); + } + + m_Name = name; + m_Variant = variant; + m_Extension = extension; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取变体名称。 + /// + public string Variant + { + get + { + return m_Variant; + } + } + + /// + /// 获取扩展名称。 + /// + public string Extension + { + get + { + return m_Extension; + } + } + + public string FullName + { + get + { + string fullName = null; + if (s_ResourceFullNames.TryGetValue(this, out fullName)) + { + return fullName; + } + + fullName = m_Variant != null ? Utility.Text.Format("{0}.{1}.{2}", m_Name, m_Variant, m_Extension) : Utility.Text.Format("{0}.{1}", m_Name, m_Extension); + s_ResourceFullNames.Add(this, fullName); + return fullName; + } + } + + public override string ToString() + { + return FullName; + } + + public override int GetHashCode() + { + if (m_Variant == null) + { + return m_Name.GetHashCode() ^ m_Extension.GetHashCode(); + } + + return m_Name.GetHashCode() ^ m_Variant.GetHashCode() ^ m_Extension.GetHashCode(); + } + + public override bool Equals(object obj) + { + return (obj is ResourceName) && Equals((ResourceName)obj); + } + + public bool Equals(ResourceName value) + { + return string.Equals(m_Name, value.m_Name, StringComparison.Ordinal) && string.Equals(m_Variant, value.m_Variant, StringComparison.Ordinal) && string.Equals(m_Extension, value.m_Extension, StringComparison.Ordinal); + } + + public static bool operator ==(ResourceName a, ResourceName b) + { + return a.Equals(b); + } + + public static bool operator !=(ResourceName a, ResourceName b) + { + return !(a == b); + } + + public int CompareTo(object value) + { + if (value == null) + { + return 1; + } + + if (!(value is ResourceName)) + { + throw new GameFrameworkException("Type of value is invalid."); + } + + return CompareTo((ResourceName)value); + } + + public int CompareTo(ResourceName resourceName) + { + int result = string.CompareOrdinal(m_Name, resourceName.m_Name); + if (result != 0) + { + return result; + } + + result = string.CompareOrdinal(m_Variant, resourceName.m_Variant); + if (result != 0) + { + return result; + } + + return string.CompareOrdinal(m_Extension, resourceName.m_Extension); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceName.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceName.cs.meta new file mode 100644 index 0000000..2b00822 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceName.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5dce30cbf11c485499f6bbc77d9cbd10 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceNameComparer.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceNameComparer.cs new file mode 100644 index 0000000..ece5d44 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceNameComparer.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 资源名称比较器。 + /// + private sealed class ResourceNameComparer : IComparer, IEqualityComparer + { + public int Compare(ResourceName x, ResourceName y) + { + return x.CompareTo(y); + } + + public bool Equals(ResourceName x, ResourceName y) + { + return x.Equals(y); + } + + public int GetHashCode(ResourceName obj) + { + return obj.GetHashCode(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceNameComparer.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceNameComparer.cs.meta new file mode 100644 index 0000000..9d83dc5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceNameComparer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 615316025632e374da88b00240172945 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.ApplyInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.ApplyInfo.cs new file mode 100644 index 0000000..6272caf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.ApplyInfo.cs @@ -0,0 +1,169 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceUpdater + { + /// + /// 资源应用信息。 + /// + [StructLayout(LayoutKind.Auto)] + private struct ApplyInfo + { + private readonly ResourceName m_ResourceName; + private readonly string m_FileSystemName; + private readonly LoadType m_LoadType; + private readonly long m_Offset; + private readonly int m_Length; + private readonly int m_HashCode; + private readonly int m_CompressedLength; + private readonly int m_CompressedHashCode; + private readonly string m_ResourcePath; + + /// + /// 初始化资源应用信息的新实例。 + /// + /// 资源名称。 + /// 资源所在的文件系统名称。 + /// 资源加载方式。 + /// 资源偏移。 + /// 资源大小。 + /// 资源哈希值。 + /// 压缩后大小。 + /// 压缩后哈希值。 + /// 资源路径。 + public ApplyInfo(ResourceName resourceName, string fileSystemName, LoadType loadType, long offset, int length, int hashCode, int compressedLength, int compressedHashCode, string resourcePath) + { + m_ResourceName = resourceName; + m_FileSystemName = fileSystemName; + m_LoadType = loadType; + m_Offset = offset; + m_Length = length; + m_HashCode = hashCode; + m_CompressedLength = compressedLength; + m_CompressedHashCode = compressedHashCode; + m_ResourcePath = resourcePath; + } + + /// + /// 获取资源名称。 + /// + public ResourceName ResourceName + { + get + { + return m_ResourceName; + } + } + + /// + /// 获取资源是否使用文件系统。 + /// + public bool UseFileSystem + { + get + { + return !string.IsNullOrEmpty(m_FileSystemName); + } + } + + /// + /// 获取资源所在的文件系统名称。 + /// + public string FileSystemName + { + get + { + return m_FileSystemName; + } + } + + /// + /// 获取资源加载方式。 + /// + public LoadType LoadType + { + get + { + return m_LoadType; + } + } + + /// + /// 获取资源偏移。 + /// + public long Offset + { + get + { + return m_Offset; + } + } + + /// + /// 获取资源大小。 + /// + public int Length + { + get + { + return m_Length; + } + } + + /// + /// 获取资源哈希值。 + /// + public int HashCode + { + get + { + return m_HashCode; + } + } + + /// + /// 获取压缩后大小。 + /// + public int CompressedLength + { + get + { + return m_CompressedLength; + } + } + + /// + /// 获取压缩后哈希值。 + /// + public int CompressedHashCode + { + get + { + return m_CompressedHashCode; + } + } + + /// + /// 获取资源路径。 + /// + public string ResourcePath + { + get + { + return m_ResourcePath; + } + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.ApplyInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.ApplyInfo.cs.meta new file mode 100644 index 0000000..5145119 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.ApplyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: df3407b030c390c47ac9ca916dcb3571 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.UpdateInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.UpdateInfo.cs new file mode 100644 index 0000000..bd4c138 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.UpdateInfo.cs @@ -0,0 +1,186 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceUpdater + { + /// + /// 资源更新信息。 + /// + private sealed class UpdateInfo + { + private readonly ResourceName m_ResourceName; + private readonly string m_FileSystemName; + private readonly LoadType m_LoadType; + private readonly int m_Length; + private readonly int m_HashCode; + private readonly int m_CompressedLength; + private readonly int m_CompressedHashCode; + private readonly string m_ResourcePath; + private bool m_Downloading; + private int m_RetryCount; + + /// + /// 初始化资源更新信息的新实例。 + /// + /// 资源名称。 + /// 资源所在的文件系统名称。 + /// 资源加载方式。 + /// 资源大小。 + /// 资源哈希值。 + /// 压缩后大小。 + /// 压缩后哈希值。 + /// 资源路径。 + public UpdateInfo(ResourceName resourceName, string fileSystemName, LoadType loadType, int length, int hashCode, int compressedLength, int compressedHashCode, string resourcePath) + { + m_ResourceName = resourceName; + m_FileSystemName = fileSystemName; + m_LoadType = loadType; + m_Length = length; + m_HashCode = hashCode; + m_CompressedLength = compressedLength; + m_CompressedHashCode = compressedHashCode; + m_ResourcePath = resourcePath; + m_Downloading = false; + m_RetryCount = 0; + } + + /// + /// 获取资源名称。 + /// + public ResourceName ResourceName + { + get + { + return m_ResourceName; + } + } + + /// + /// 获取资源是否使用文件系统。 + /// + public bool UseFileSystem + { + get + { + return !string.IsNullOrEmpty(m_FileSystemName); + } + } + + /// + /// 获取资源所在的文件系统名称。 + /// + public string FileSystemName + { + get + { + return m_FileSystemName; + } + } + + /// + /// 获取资源加载方式。 + /// + public LoadType LoadType + { + get + { + return m_LoadType; + } + } + + /// + /// 获取资源大小。 + /// + public int Length + { + get + { + return m_Length; + } + } + + /// + /// 获取资源哈希值。 + /// + public int HashCode + { + get + { + return m_HashCode; + } + } + + /// + /// 获取压缩后大小。 + /// + public int CompressedLength + { + get + { + return m_CompressedLength; + } + } + + /// + /// 获取压缩后哈希值。 + /// + public int CompressedHashCode + { + get + { + return m_CompressedHashCode; + } + } + + /// + /// 获取资源路径。 + /// + public string ResourcePath + { + get + { + return m_ResourcePath; + } + } + + /// + /// 获取或设置下载状态。 + /// + public bool Downloading + { + get + { + return m_Downloading; + } + set + { + m_Downloading = value; + } + } + + /// + /// 获取或设置已重试次数。 + /// + public int RetryCount + { + get + { + return m_RetryCount; + } + set + { + m_RetryCount = value; + } + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.UpdateInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.UpdateInfo.cs.meta new file mode 100644 index 0000000..cb90c2e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.UpdateInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7a4d84f0355c75f41931227e4359c8fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.cs new file mode 100644 index 0000000..b81aef0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.cs @@ -0,0 +1,1016 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Download; +using GameFramework.FileSystem; +using System; +using System.Collections.Generic; +using System.IO; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 资源更新器。 + /// + private sealed partial class ResourceUpdater + { + private const int CachedHashBytesLength = 4; + private const int CachedBytesLength = 0x1000; + + private readonly ResourceManager m_ResourceManager; + private readonly Queue m_ApplyWaitingInfo; + private readonly List m_UpdateWaitingInfo; + private readonly HashSet m_UpdateWaitingInfoWhilePlaying; + private readonly Dictionary m_UpdateCandidateInfo; + private readonly SortedDictionary> m_CachedFileSystemsForGenerateReadWriteVersionList; + private readonly List m_CachedResourceNames; + private readonly byte[] m_CachedHashBytes; + private readonly byte[] m_CachedBytes; + private IDownloadManager m_DownloadManager; + private bool m_CheckResourcesComplete; + private string m_ApplyingResourcePackPath; + private FileStream m_ApplyingResourcePackStream; + private ResourceGroup m_UpdatingResourceGroup; + private int m_GenerateReadWriteVersionListLength; + private int m_CurrentGenerateReadWriteVersionListLength; + private int m_UpdateRetryCount; + private bool m_FailureFlag; + private string m_ReadWriteVersionListFileName; + private string m_ReadWriteVersionListTempFileName; + + public GameFrameworkAction ResourceApplyStart; + public GameFrameworkAction ResourceApplySuccess; + public GameFrameworkAction ResourceApplyFailure; + public GameFrameworkAction ResourceApplyComplete; + public GameFrameworkAction ResourceUpdateStart; + public GameFrameworkAction ResourceUpdateChanged; + public GameFrameworkAction ResourceUpdateSuccess; + public GameFrameworkAction ResourceUpdateFailure; + public GameFrameworkAction ResourceUpdateComplete; + public GameFrameworkAction ResourceUpdateAllComplete; + + /// + /// 初始化资源更新器的新实例。 + /// + /// 资源管理器。 + public ResourceUpdater(ResourceManager resourceManager) + { + m_ResourceManager = resourceManager; + m_ApplyWaitingInfo = new Queue(); + m_UpdateWaitingInfo = new List(); + m_UpdateWaitingInfoWhilePlaying = new HashSet(); + m_UpdateCandidateInfo = new Dictionary(); + m_CachedFileSystemsForGenerateReadWriteVersionList = new SortedDictionary>(StringComparer.Ordinal); + m_CachedResourceNames = new List(); + m_CachedHashBytes = new byte[CachedHashBytesLength]; + m_CachedBytes = new byte[CachedBytesLength]; + m_DownloadManager = null; + m_CheckResourcesComplete = false; + m_ApplyingResourcePackPath = null; + m_ApplyingResourcePackStream = null; + m_UpdatingResourceGroup = null; + m_GenerateReadWriteVersionListLength = 0; + m_CurrentGenerateReadWriteVersionListLength = 0; + m_UpdateRetryCount = 3; + m_FailureFlag = false; + m_ReadWriteVersionListFileName = Utility.Path.GetRegularPath(Path.Combine(m_ResourceManager.m_ReadWritePath, LocalVersionListFileName)); + m_ReadWriteVersionListTempFileName = Utility.Text.Format("{0}.{1}", m_ReadWriteVersionListFileName, TempExtension); + + ResourceApplyStart = null; + ResourceApplySuccess = null; + ResourceApplyFailure = null; + ResourceApplyComplete = null; + ResourceUpdateStart = null; + ResourceUpdateChanged = null; + ResourceUpdateSuccess = null; + ResourceUpdateFailure = null; + ResourceUpdateComplete = null; + ResourceUpdateAllComplete = null; + } + + /// + /// 获取或设置每更新多少字节的资源,重新生成一次版本资源列表。 + /// + public int GenerateReadWriteVersionListLength + { + get + { + return m_GenerateReadWriteVersionListLength; + } + set + { + m_GenerateReadWriteVersionListLength = value; + } + } + + /// + /// 获取正在应用的资源包路径。 + /// + public string ApplyingResourcePackPath + { + get + { + return m_ApplyingResourcePackPath; + } + } + + /// + /// 获取等待应用资源数量。 + /// + public int ApplyWaitingCount + { + get + { + return m_ApplyWaitingInfo.Count; + } + } + + /// + /// 获取或设置资源更新重试次数。 + /// + public int UpdateRetryCount + { + get + { + return m_UpdateRetryCount; + } + set + { + m_UpdateRetryCount = value; + } + } + + /// + /// 获取正在更新的资源组。 + /// + public IResourceGroup UpdatingResourceGroup + { + get + { + return m_UpdatingResourceGroup; + } + } + + /// + /// 获取等待更新资源数量。 + /// + public int UpdateWaitingCount + { + get + { + return m_UpdateWaitingInfo.Count; + } + } + + /// + /// 获取使用时下载的等待更新资源数量。 + /// + public int UpdateWaitingWhilePlayingCount + { + get + { + return m_UpdateWaitingInfoWhilePlaying.Count; + } + } + + /// + /// 获取候选更新资源数量。 + /// + public int UpdateCandidateCount + { + get + { + return m_UpdateCandidateInfo.Count; + } + } + + /// + /// 资源更新器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void Update(float elapseSeconds, float realElapseSeconds) + { + if (m_ApplyingResourcePackStream != null) + { + while (m_ApplyWaitingInfo.Count > 0) + { + ApplyInfo applyInfo = m_ApplyWaitingInfo.Dequeue(); + if (ApplyResource(applyInfo)) + { + return; + } + } + + Array.Clear(m_CachedBytes, 0, CachedBytesLength); + string resourcePackPath = m_ApplyingResourcePackPath; + m_ApplyingResourcePackPath = null; + m_ApplyingResourcePackStream.Dispose(); + m_ApplyingResourcePackStream = null; + if (ResourceApplyComplete != null) + { + ResourceApplyComplete(resourcePackPath, !m_FailureFlag); + } + + if (m_UpdateCandidateInfo.Count <= 0 && ResourceUpdateAllComplete != null) + { + ResourceUpdateAllComplete(); + } + + return; + } + + if (m_UpdateWaitingInfo.Count > 0) + { + int freeCount = m_DownloadManager.FreeAgentCount - m_DownloadManager.WaitingTaskCount; + if (freeCount > 0) + { + for (int i = 0, count = 0; i < m_UpdateWaitingInfo.Count && count < freeCount; i++) + { + if (DownloadResource(m_UpdateWaitingInfo[i])) + { + count++; + } + } + } + + return; + } + } + + /// + /// 关闭并清理资源更新器。 + /// + public void Shutdown() + { + if (m_DownloadManager != null) + { + m_DownloadManager.DownloadStart -= OnDownloadStart; + m_DownloadManager.DownloadUpdate -= OnDownloadUpdate; + m_DownloadManager.DownloadSuccess -= OnDownloadSuccess; + m_DownloadManager.DownloadFailure -= OnDownloadFailure; + } + + m_UpdateWaitingInfo.Clear(); + m_UpdateCandidateInfo.Clear(); + m_CachedFileSystemsForGenerateReadWriteVersionList.Clear(); + } + + /// + /// 设置下载管理器。 + /// + /// 下载管理器。 + public void SetDownloadManager(IDownloadManager downloadManager) + { + if (downloadManager == null) + { + throw new GameFrameworkException("Download manager is invalid."); + } + + m_DownloadManager = downloadManager; + m_DownloadManager.DownloadStart += OnDownloadStart; + m_DownloadManager.DownloadUpdate += OnDownloadUpdate; + m_DownloadManager.DownloadSuccess += OnDownloadSuccess; + m_DownloadManager.DownloadFailure += OnDownloadFailure; + } + + /// + /// 增加资源更新。 + /// + /// 资源名称。 + /// 资源所在的文件系统名称。 + /// 资源加载方式。 + /// 资源大小。 + /// 资源哈希值。 + /// 压缩后大小。 + /// 压缩后哈希值。 + /// 资源路径。 + public void AddResourceUpdate(ResourceName resourceName, string fileSystemName, LoadType loadType, int length, int hashCode, int compressedLength, int compressedHashCode, string resourcePath) + { + m_UpdateCandidateInfo.Add(resourceName, new UpdateInfo(resourceName, fileSystemName, loadType, length, hashCode, compressedLength, compressedHashCode, resourcePath)); + } + + /// + /// 检查资源完成。 + /// + /// 是否需要生成读写区版本资源列表。 + public void CheckResourceComplete(bool needGenerateReadWriteVersionList) + { + m_CheckResourcesComplete = true; + if (needGenerateReadWriteVersionList) + { + GenerateReadWriteVersionList(); + } + } + + /// + /// 应用指定资源包的资源。 + /// + /// 要应用的资源包路径。 + public void ApplyResources(string resourcePackPath) + { + if (!m_CheckResourcesComplete) + { + throw new GameFrameworkException("You must check resources complete first."); + } + + if (m_ApplyingResourcePackStream != null) + { + throw new GameFrameworkException(Utility.Text.Format("There is already a resource pack '{0}' being applied.", m_ApplyingResourcePackPath)); + } + + if (m_UpdatingResourceGroup != null) + { + throw new GameFrameworkException(Utility.Text.Format("There is already a resource group '{0}' being updated.", m_UpdatingResourceGroup.Name)); + } + + if (m_UpdateWaitingInfoWhilePlaying.Count > 0) + { + throw new GameFrameworkException("There are already some resources being updated while playing."); + } + + try + { + long length = 0L; + ResourcePackVersionList versionList = default(ResourcePackVersionList); + using (FileStream fileStream = new FileStream(resourcePackPath, FileMode.Open, FileAccess.Read)) + { + length = fileStream.Length; + versionList = m_ResourceManager.m_ResourcePackVersionListSerializer.Deserialize(fileStream); + } + + if (!versionList.IsValid) + { + throw new GameFrameworkException("Deserialize resource pack version list failure."); + } + + if (versionList.Offset + versionList.Length != length) + { + throw new GameFrameworkException("Resource pack length is invalid."); + } + + m_ApplyingResourcePackPath = resourcePackPath; + m_ApplyingResourcePackStream = new FileStream(resourcePackPath, FileMode.Open, FileAccess.Read); + m_ApplyingResourcePackStream.Position = versionList.Offset; + m_FailureFlag = false; + + long totalLength = 0L; + ResourcePackVersionList.Resource[] resources = versionList.GetResources(); + foreach (ResourcePackVersionList.Resource resource in resources) + { + ResourceName resourceName = new ResourceName(resource.Name, resource.Variant, resource.Extension); + UpdateInfo updateInfo = null; + if (!m_UpdateCandidateInfo.TryGetValue(resourceName, out updateInfo)) + { + continue; + } + + if (updateInfo.LoadType == (LoadType)resource.LoadType && updateInfo.Length == resource.Length && updateInfo.HashCode == resource.HashCode) + { + totalLength += resource.Length; + m_ApplyWaitingInfo.Enqueue(new ApplyInfo(resourceName, updateInfo.FileSystemName, (LoadType)resource.LoadType, resource.Offset, resource.Length, resource.HashCode, resource.CompressedLength, resource.CompressedHashCode, updateInfo.ResourcePath)); + } + } + + if (ResourceApplyStart != null) + { + ResourceApplyStart(m_ApplyingResourcePackPath, m_ApplyWaitingInfo.Count, totalLength); + } + } + catch (Exception exception) + { + if (m_ApplyingResourcePackStream != null) + { + m_ApplyingResourcePackStream.Dispose(); + m_ApplyingResourcePackStream = null; + } + + throw new GameFrameworkException(Utility.Text.Format("Apply resources '{0}' with exception '{1}'.", resourcePackPath, exception), exception); + } + } + + /// + /// 更新指定资源组的资源。 + /// + /// 要更新的资源组。 + public void UpdateResources(ResourceGroup resourceGroup) + { + if (m_DownloadManager == null) + { + throw new GameFrameworkException("You must set download manager first."); + } + + if (!m_CheckResourcesComplete) + { + throw new GameFrameworkException("You must check resources complete first."); + } + + if (m_ApplyingResourcePackStream != null) + { + throw new GameFrameworkException(Utility.Text.Format("There is already a resource pack '{0}' being applied.", m_ApplyingResourcePackPath)); + } + + if (m_UpdatingResourceGroup != null) + { + throw new GameFrameworkException(Utility.Text.Format("There is already a resource group '{0}' being updated.", m_UpdatingResourceGroup.Name)); + } + + if (string.IsNullOrEmpty(resourceGroup.Name)) + { + foreach (KeyValuePair updateInfo in m_UpdateCandidateInfo) + { + m_UpdateWaitingInfo.Add(updateInfo.Value); + } + } + else + { + resourceGroup.InternalGetResourceNames(m_CachedResourceNames); + foreach (ResourceName resourceName in m_CachedResourceNames) + { + UpdateInfo updateInfo = null; + if (!m_UpdateCandidateInfo.TryGetValue(resourceName, out updateInfo)) + { + continue; + } + + m_UpdateWaitingInfo.Add(updateInfo); + } + + m_CachedResourceNames.Clear(); + } + + m_UpdatingResourceGroup = resourceGroup; + m_FailureFlag = false; + } + + /// + /// 停止更新资源。 + /// + public void StopUpdateResources() + { + if (m_DownloadManager == null) + { + throw new GameFrameworkException("You must set download manager first."); + } + + if (!m_CheckResourcesComplete) + { + throw new GameFrameworkException("You must check resources complete first."); + } + + if (m_ApplyingResourcePackStream != null) + { + throw new GameFrameworkException(Utility.Text.Format("There is already a resource pack '{0}' being applied.", m_ApplyingResourcePackPath)); + } + + if (m_UpdatingResourceGroup == null) + { + throw new GameFrameworkException("There is no resource group being updated."); + } + + m_UpdateWaitingInfo.Clear(); + m_UpdatingResourceGroup = null; + } + + /// + /// 更新指定资源。 + /// + /// 要更新的资源名称。 + public void UpdateResource(ResourceName resourceName) + { + if (m_DownloadManager == null) + { + throw new GameFrameworkException("You must set download manager first."); + } + + if (!m_CheckResourcesComplete) + { + throw new GameFrameworkException("You must check resources complete first."); + } + + if (m_ApplyingResourcePackStream != null) + { + throw new GameFrameworkException(Utility.Text.Format("There is already a resource pack '{0}' being applied.", m_ApplyingResourcePackPath)); + } + + UpdateInfo updateInfo = null; + if (m_UpdateCandidateInfo.TryGetValue(resourceName, out updateInfo) && m_UpdateWaitingInfoWhilePlaying.Add(updateInfo)) + { + DownloadResource(updateInfo); + } + } + + private bool ApplyResource(ApplyInfo applyInfo) + { + long position = m_ApplyingResourcePackStream.Position; + try + { + bool compressed = applyInfo.Length != applyInfo.CompressedLength || applyInfo.HashCode != applyInfo.CompressedHashCode; + + int bytesRead = 0; + int bytesLeft = applyInfo.CompressedLength; + string directory = Path.GetDirectoryName(applyInfo.ResourcePath); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + m_ApplyingResourcePackStream.Position += applyInfo.Offset; + using (FileStream fileStream = new FileStream(applyInfo.ResourcePath, FileMode.Create, FileAccess.ReadWrite)) + { + while ((bytesRead = m_ApplyingResourcePackStream.Read(m_CachedBytes, 0, bytesLeft < CachedBytesLength ? bytesLeft : CachedBytesLength)) > 0) + { + bytesLeft -= bytesRead; + fileStream.Write(m_CachedBytes, 0, bytesRead); + } + + if (compressed) + { + fileStream.Position = 0L; + int hashCode = Utility.Verifier.GetCrc32(fileStream); + if (hashCode != applyInfo.CompressedHashCode) + { + if (ResourceApplyFailure != null) + { + string errorMessage = Utility.Text.Format("Resource compressed hash code error, need '{0}', applied '{1}'.", applyInfo.CompressedHashCode, hashCode); + ResourceApplyFailure(applyInfo.ResourceName, m_ApplyingResourcePackPath, errorMessage); + } + + m_FailureFlag = true; + return false; + } + + fileStream.Position = 0L; + m_ResourceManager.PrepareCachedStream(); + if (!Utility.Compression.Decompress(fileStream, m_ResourceManager.m_CachedStream)) + { + if (ResourceApplyFailure != null) + { + string errorMessage = Utility.Text.Format("Unable to decompress resource '{0}'.", applyInfo.ResourcePath); + ResourceApplyFailure(applyInfo.ResourceName, m_ApplyingResourcePackPath, errorMessage); + } + + m_FailureFlag = true; + return false; + } + + fileStream.Position = 0L; + fileStream.SetLength(0L); + fileStream.Write(m_ResourceManager.m_CachedStream.GetBuffer(), 0, (int)m_ResourceManager.m_CachedStream.Length); + } + else + { + int hashCode = 0; + fileStream.Position = 0L; + if (applyInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || applyInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt + || applyInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || applyInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + Utility.Converter.GetBytes(applyInfo.HashCode, m_CachedHashBytes); + if (applyInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || applyInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt) + { + hashCode = Utility.Verifier.GetCrc32(fileStream, m_CachedHashBytes, Utility.Encryption.QuickEncryptLength); + } + else if (applyInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt || applyInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + hashCode = Utility.Verifier.GetCrc32(fileStream, m_CachedHashBytes, applyInfo.Length); + } + + Array.Clear(m_CachedHashBytes, 0, CachedHashBytesLength); + } + else + { + hashCode = Utility.Verifier.GetCrc32(fileStream); + } + + if (hashCode != applyInfo.HashCode) + { + if (ResourceApplyFailure != null) + { + string errorMessage = Utility.Text.Format("Resource hash code error, need '{0}', applied '{1}'.", applyInfo.HashCode, hashCode); + ResourceApplyFailure(applyInfo.ResourceName, m_ApplyingResourcePackPath, errorMessage); + } + + m_FailureFlag = true; + return false; + } + } + } + + if (applyInfo.UseFileSystem) + { + IFileSystem fileSystem = m_ResourceManager.GetFileSystem(applyInfo.FileSystemName, false); + bool retVal = fileSystem.WriteFile(applyInfo.ResourceName.FullName, applyInfo.ResourcePath); + if (File.Exists(applyInfo.ResourcePath)) + { + File.Delete(applyInfo.ResourcePath); + } + + if (!retVal) + { + if (ResourceApplyFailure != null) + { + string errorMessage = Utility.Text.Format("Unable to write resource '{0}' to file system '{1}'.", applyInfo.ResourcePath, applyInfo.FileSystemName); + ResourceApplyFailure(applyInfo.ResourceName, m_ApplyingResourcePackPath, errorMessage); + } + + m_FailureFlag = true; + return false; + } + } + + string downloadingResource = Utility.Text.Format("{0}.download", applyInfo.ResourcePath); + if (File.Exists(downloadingResource)) + { + File.Delete(downloadingResource); + } + + m_UpdateCandidateInfo.Remove(applyInfo.ResourceName); + m_ResourceManager.m_ResourceInfos[applyInfo.ResourceName].MarkReady(); + m_ResourceManager.m_ReadWriteResourceInfos.Add(applyInfo.ResourceName, new ReadWriteResourceInfo(applyInfo.FileSystemName, applyInfo.LoadType, applyInfo.Length, applyInfo.HashCode)); + if (ResourceApplySuccess != null) + { + ResourceApplySuccess(applyInfo.ResourceName, applyInfo.ResourcePath, m_ApplyingResourcePackPath, applyInfo.Length, applyInfo.CompressedLength); + } + + m_CurrentGenerateReadWriteVersionListLength += applyInfo.CompressedLength; + if (m_ApplyWaitingInfo.Count <= 0 || m_CurrentGenerateReadWriteVersionListLength >= m_GenerateReadWriteVersionListLength) + { + GenerateReadWriteVersionList(); + return true; + } + + return false; + } + catch (Exception exception) + { + if (ResourceApplyFailure != null) + { + ResourceApplyFailure(applyInfo.ResourceName, m_ApplyingResourcePackPath, exception.ToString()); + } + + m_FailureFlag = true; + return false; + } + finally + { + m_ApplyingResourcePackStream.Position = position; + } + } + + private bool DownloadResource(UpdateInfo updateInfo) + { + if (updateInfo.Downloading) + { + return false; + } + + updateInfo.Downloading = true; + string resourceFullNameWithCrc32 = updateInfo.ResourceName.Variant != null ? Utility.Text.Format("{0}.{1}.{2:x8}.{3}", updateInfo.ResourceName.Name, updateInfo.ResourceName.Variant, updateInfo.HashCode, DefaultExtension) : Utility.Text.Format("{0}.{1:x8}.{2}", updateInfo.ResourceName.Name, updateInfo.HashCode, DefaultExtension); + m_DownloadManager.AddDownload(updateInfo.ResourcePath, Utility.Path.GetRemotePath(Path.Combine(m_ResourceManager.m_UpdatePrefixUri, resourceFullNameWithCrc32)), updateInfo); + return true; + } + + private void GenerateReadWriteVersionList() + { + FileStream fileStream = null; + try + { + fileStream = new FileStream(m_ReadWriteVersionListTempFileName, FileMode.Create, FileAccess.Write); + LocalVersionList.Resource[] resources = m_ResourceManager.m_ReadWriteResourceInfos.Count > 0 ? new LocalVersionList.Resource[m_ResourceManager.m_ReadWriteResourceInfos.Count] : null; + if (resources != null) + { + int index = 0; + foreach (KeyValuePair i in m_ResourceManager.m_ReadWriteResourceInfos) + { + ResourceName resourceName = i.Key; + ReadWriteResourceInfo resourceInfo = i.Value; + resources[index] = new LocalVersionList.Resource(resourceName.Name, resourceName.Variant, resourceName.Extension, (byte)resourceInfo.LoadType, resourceInfo.Length, resourceInfo.HashCode); + if (resourceInfo.UseFileSystem) + { + List resourceIndexes = null; + if (!m_CachedFileSystemsForGenerateReadWriteVersionList.TryGetValue(resourceInfo.FileSystemName, out resourceIndexes)) + { + resourceIndexes = new List(); + m_CachedFileSystemsForGenerateReadWriteVersionList.Add(resourceInfo.FileSystemName, resourceIndexes); + } + + resourceIndexes.Add(index); + } + + index++; + } + } + + LocalVersionList.FileSystem[] fileSystems = m_CachedFileSystemsForGenerateReadWriteVersionList.Count > 0 ? new LocalVersionList.FileSystem[m_CachedFileSystemsForGenerateReadWriteVersionList.Count] : null; + if (fileSystems != null) + { + int index = 0; + foreach (KeyValuePair> i in m_CachedFileSystemsForGenerateReadWriteVersionList) + { + fileSystems[index++] = new LocalVersionList.FileSystem(i.Key, i.Value.ToArray()); + i.Value.Clear(); + } + } + + LocalVersionList versionList = new LocalVersionList(resources, fileSystems); + if (!m_ResourceManager.m_ReadWriteVersionListSerializer.Serialize(fileStream, versionList)) + { + throw new GameFrameworkException("Serialize read-write version list failure."); + } + + if (fileStream != null) + { + fileStream.Dispose(); + fileStream = null; + } + } + catch (Exception exception) + { + if (fileStream != null) + { + fileStream.Dispose(); + fileStream = null; + } + + if (File.Exists(m_ReadWriteVersionListTempFileName)) + { + File.Delete(m_ReadWriteVersionListTempFileName); + } + + throw new GameFrameworkException(Utility.Text.Format("Generate read-write version list exception '{0}'.", exception), exception); + } + + if (File.Exists(m_ReadWriteVersionListFileName)) + { + File.Delete(m_ReadWriteVersionListFileName); + } + + File.Move(m_ReadWriteVersionListTempFileName, m_ReadWriteVersionListFileName); + m_CurrentGenerateReadWriteVersionListLength = 0; + } + + private void OnDownloadStart(object sender, DownloadStartEventArgs e) + { + UpdateInfo updateInfo = e.UserData as UpdateInfo; + if (updateInfo == null) + { + return; + } + + if (m_DownloadManager == null) + { + throw new GameFrameworkException("You must set download manager first."); + } + + if (e.CurrentLength > int.MaxValue) + { + throw new GameFrameworkException(Utility.Text.Format("File '{0}' is too large.", e.DownloadPath)); + } + + if (ResourceUpdateStart != null) + { + ResourceUpdateStart(updateInfo.ResourceName, e.DownloadPath, e.DownloadUri, (int)e.CurrentLength, updateInfo.CompressedLength, updateInfo.RetryCount); + } + } + + private void OnDownloadUpdate(object sender, DownloadUpdateEventArgs e) + { + UpdateInfo updateInfo = e.UserData as UpdateInfo; + if (updateInfo == null) + { + return; + } + + if (m_DownloadManager == null) + { + throw new GameFrameworkException("You must set download manager first."); + } + + if (e.CurrentLength > updateInfo.CompressedLength) + { + m_DownloadManager.RemoveDownload(e.SerialId); + string downloadFile = Utility.Text.Format("{0}.download", e.DownloadPath); + if (File.Exists(downloadFile)) + { + File.Delete(downloadFile); + } + + string errorMessage = Utility.Text.Format("When download update, downloaded length is larger than compressed length, need '{0}', downloaded '{1}'.", updateInfo.CompressedLength, e.CurrentLength); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + return; + } + + if (ResourceUpdateChanged != null) + { + ResourceUpdateChanged(updateInfo.ResourceName, e.DownloadPath, e.DownloadUri, (int)e.CurrentLength, updateInfo.CompressedLength); + } + } + + private void OnDownloadSuccess(object sender, DownloadSuccessEventArgs e) + { + UpdateInfo updateInfo = e.UserData as UpdateInfo; + if (updateInfo == null) + { + return; + } + + try + { + using (FileStream fileStream = new FileStream(e.DownloadPath, FileMode.Open, FileAccess.ReadWrite)) + { + bool compressed = updateInfo.Length != updateInfo.CompressedLength || updateInfo.HashCode != updateInfo.CompressedHashCode; + + int length = (int)fileStream.Length; + if (length != updateInfo.CompressedLength) + { + fileStream.Close(); + string errorMessage = Utility.Text.Format("Resource compressed length error, need '{0}', downloaded '{1}'.", updateInfo.CompressedLength, length); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + return; + } + + if (compressed) + { + fileStream.Position = 0L; + int hashCode = Utility.Verifier.GetCrc32(fileStream); + if (hashCode != updateInfo.CompressedHashCode) + { + fileStream.Close(); + string errorMessage = Utility.Text.Format("Resource compressed hash code error, need '{0}', downloaded '{1}'.", updateInfo.CompressedHashCode, hashCode); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + return; + } + + fileStream.Position = 0L; + m_ResourceManager.PrepareCachedStream(); + if (!Utility.Compression.Decompress(fileStream, m_ResourceManager.m_CachedStream)) + { + fileStream.Close(); + string errorMessage = Utility.Text.Format("Unable to decompress resource '{0}'.", e.DownloadPath); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + return; + } + + int uncompressedLength = (int)m_ResourceManager.m_CachedStream.Length; + if (uncompressedLength != updateInfo.Length) + { + fileStream.Close(); + string errorMessage = Utility.Text.Format("Resource length error, need '{0}', downloaded '{1}'.", updateInfo.Length, uncompressedLength); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + return; + } + + fileStream.Position = 0L; + fileStream.SetLength(0L); + fileStream.Write(m_ResourceManager.m_CachedStream.GetBuffer(), 0, uncompressedLength); + } + else + { + int hashCode = 0; + fileStream.Position = 0L; + if (updateInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || updateInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt + || updateInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || updateInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + Utility.Converter.GetBytes(updateInfo.HashCode, m_CachedHashBytes); + if (updateInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || updateInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt) + { + hashCode = Utility.Verifier.GetCrc32(fileStream, m_CachedHashBytes, Utility.Encryption.QuickEncryptLength); + } + else if (updateInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt || updateInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + hashCode = Utility.Verifier.GetCrc32(fileStream, m_CachedHashBytes, length); + } + + Array.Clear(m_CachedHashBytes, 0, CachedHashBytesLength); + } + else + { + hashCode = Utility.Verifier.GetCrc32(fileStream); + } + + if (hashCode != updateInfo.HashCode) + { + fileStream.Close(); + string errorMessage = Utility.Text.Format("Resource hash code error, need '{0}', downloaded '{1}'.", updateInfo.HashCode, hashCode); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + return; + } + } + } + + if (updateInfo.UseFileSystem) + { + IFileSystem fileSystem = m_ResourceManager.GetFileSystem(updateInfo.FileSystemName, false); + bool retVal = fileSystem.WriteFile(updateInfo.ResourceName.FullName, updateInfo.ResourcePath); + if (File.Exists(updateInfo.ResourcePath)) + { + File.Delete(updateInfo.ResourcePath); + } + + if (!retVal) + { + string errorMessage = Utility.Text.Format("Write resource to file system '{0}' error.", fileSystem.FullPath); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + return; + } + } + + m_UpdateCandidateInfo.Remove(updateInfo.ResourceName); + m_UpdateWaitingInfo.Remove(updateInfo); + m_UpdateWaitingInfoWhilePlaying.Remove(updateInfo); + m_ResourceManager.m_ResourceInfos[updateInfo.ResourceName].MarkReady(); + m_ResourceManager.m_ReadWriteResourceInfos.Add(updateInfo.ResourceName, new ReadWriteResourceInfo(updateInfo.FileSystemName, updateInfo.LoadType, updateInfo.Length, updateInfo.HashCode)); + if (ResourceUpdateSuccess != null) + { + ResourceUpdateSuccess(updateInfo.ResourceName, e.DownloadPath, e.DownloadUri, updateInfo.Length, updateInfo.CompressedLength); + } + + m_CurrentGenerateReadWriteVersionListLength += updateInfo.CompressedLength; + if (m_UpdateCandidateInfo.Count <= 0 || m_UpdateWaitingInfo.Count + m_UpdateWaitingInfoWhilePlaying.Count <= 0 || m_CurrentGenerateReadWriteVersionListLength >= m_GenerateReadWriteVersionListLength) + { + GenerateReadWriteVersionList(); + } + + if (m_UpdatingResourceGroup != null && m_UpdateWaitingInfo.Count <= 0) + { + ResourceGroup updatingResourceGroup = m_UpdatingResourceGroup; + m_UpdatingResourceGroup = null; + if (ResourceUpdateComplete != null) + { + ResourceUpdateComplete(updatingResourceGroup, !m_FailureFlag); + } + } + + if (m_UpdateCandidateInfo.Count <= 0 && ResourceUpdateAllComplete != null) + { + ResourceUpdateAllComplete(); + } + } + catch (Exception exception) + { + string errorMessage = Utility.Text.Format("Update resource '{0}' with error message '{1}'.", e.DownloadPath, exception); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + } + } + + private void OnDownloadFailure(object sender, DownloadFailureEventArgs e) + { + UpdateInfo updateInfo = e.UserData as UpdateInfo; + if (updateInfo == null) + { + return; + } + + if (File.Exists(e.DownloadPath)) + { + File.Delete(e.DownloadPath); + } + + if (ResourceUpdateFailure != null) + { + ResourceUpdateFailure(updateInfo.ResourceName, e.DownloadUri, updateInfo.RetryCount, m_UpdateRetryCount, e.ErrorMessage); + } + + if (updateInfo.RetryCount < m_UpdateRetryCount) + { + updateInfo.Downloading = false; + updateInfo.RetryCount++; + if (m_UpdateWaitingInfoWhilePlaying.Contains(updateInfo)) + { + DownloadResource(updateInfo); + } + } + else + { + m_FailureFlag = true; + updateInfo.Downloading = false; + updateInfo.RetryCount = 0; + m_UpdateWaitingInfo.Remove(updateInfo); + m_UpdateWaitingInfoWhilePlaying.Remove(updateInfo); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.cs.meta new file mode 100644 index 0000000..8de46ce --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceUpdater.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 55c246252956f824181c979527ccc63b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceVerifier.VerifyInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceVerifier.VerifyInfo.cs new file mode 100644 index 0000000..b6d2a6e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceVerifier.VerifyInfo.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private sealed partial class ResourceVerifier + { + /// + /// 资源校验信息。 + /// + private struct VerifyInfo + { + private readonly ResourceName m_ResourceName; + private readonly string m_FileSystemName; + private readonly LoadType m_LoadType; + private readonly int m_Length; + private readonly int m_HashCode; + + /// + /// 初始化资源校验信息的新实例。 + /// + /// 资源名称。 + /// 资源所在的文件系统名称。 + /// 资源加载方式。 + /// 资源大小。 + /// 资源哈希值。 + public VerifyInfo(ResourceName resourceName, string fileSystemName, LoadType loadType, int length, int hashCode) + { + m_ResourceName = resourceName; + m_FileSystemName = fileSystemName; + m_LoadType = loadType; + m_Length = length; + m_HashCode = hashCode; + } + + /// + /// 获取资源名称。 + /// + public ResourceName ResourceName + { + get + { + return m_ResourceName; + } + } + + /// + /// 获取资源是否使用文件系统。 + /// + public bool UseFileSystem + { + get + { + return !string.IsNullOrEmpty(m_FileSystemName); + } + } + + /// + /// 获取资源所在的文件系统名称。 + /// + public string FileSystemName + { + get + { + return m_FileSystemName; + } + } + + /// + /// 获取资源加载方式。 + /// + public LoadType LoadType + { + get + { + return m_LoadType; + } + } + + /// + /// 获取资源大小。 + /// + public int Length + { + get + { + return m_Length; + } + } + + /// + /// 获取资源哈希值。 + /// + public int HashCode + { + get + { + return m_HashCode; + } + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceVerifier.VerifyInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceVerifier.VerifyInfo.cs.meta new file mode 100644 index 0000000..e863eca --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceVerifier.VerifyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 66af4330fb3928944a68c9a34c76a527 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceVerifier.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceVerifier.cs new file mode 100644 index 0000000..ff6aa9b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceVerifier.cs @@ -0,0 +1,389 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.FileSystem; +using System; +using System.Collections.Generic; +using System.IO; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 资源校验器。 + /// + private sealed partial class ResourceVerifier + { + private const int CachedHashBytesLength = 4; + + private readonly ResourceManager m_ResourceManager; + private readonly List m_VerifyInfos; + private readonly byte[] m_CachedHashBytes; + private bool m_LoadReadWriteVersionListComplete; + private int m_VerifyResourceLengthPerFrame; + private int m_VerifyResourceIndex; + private bool m_FailureFlag; + + public GameFrameworkAction ResourceVerifyStart; + public GameFrameworkAction ResourceVerifySuccess; + public GameFrameworkAction ResourceVerifyFailure; + public GameFrameworkAction ResourceVerifyComplete; + + /// + /// 初始化资源校验器的新实例。 + /// + /// 资源管理器。 + public ResourceVerifier(ResourceManager resourceManager) + { + m_ResourceManager = resourceManager; + m_VerifyInfos = new List(); + m_CachedHashBytes = new byte[CachedHashBytesLength]; + m_LoadReadWriteVersionListComplete = false; + m_VerifyResourceLengthPerFrame = 0; + m_VerifyResourceIndex = 0; + m_FailureFlag = false; + + ResourceVerifyStart = null; + ResourceVerifySuccess = null; + ResourceVerifyFailure = null; + ResourceVerifyComplete = null; + } + + /// + /// 资源校验器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void Update(float elapseSeconds, float realElapseSeconds) + { + if (!m_LoadReadWriteVersionListComplete) + { + return; + } + + int length = 0; + while (m_VerifyResourceIndex < m_VerifyInfos.Count) + { + VerifyInfo verifyInfo = m_VerifyInfos[m_VerifyResourceIndex]; + length += verifyInfo.Length; + if (VerifyResource(verifyInfo)) + { + m_VerifyResourceIndex++; + if (ResourceVerifySuccess != null) + { + ResourceVerifySuccess(verifyInfo.ResourceName, verifyInfo.Length); + } + } + else + { + m_FailureFlag = true; + m_VerifyInfos.RemoveAt(m_VerifyResourceIndex); + if (ResourceVerifyFailure != null) + { + ResourceVerifyFailure(verifyInfo.ResourceName); + } + } + + if (length >= m_VerifyResourceLengthPerFrame) + { + return; + } + } + + m_LoadReadWriteVersionListComplete = false; + if (m_FailureFlag) + { + GenerateReadWriteVersionList(); + } + + if (ResourceVerifyComplete != null) + { + ResourceVerifyComplete(!m_FailureFlag); + } + } + + /// + /// 关闭并清理资源校验器。 + /// + public void Shutdown() + { + m_VerifyInfos.Clear(); + m_LoadReadWriteVersionListComplete = false; + m_VerifyResourceLengthPerFrame = 0; + m_VerifyResourceIndex = 0; + m_FailureFlag = false; + } + + /// + /// 校验资源。 + /// + /// 每帧至少校验资源的大小,以字节为单位。 + public void VerifyResources(int verifyResourceLengthPerFrame) + { + if (verifyResourceLengthPerFrame < 0) + { + throw new GameFrameworkException("Verify resource count per frame is invalid."); + } + + if (m_ResourceManager.m_ResourceHelper == null) + { + throw new GameFrameworkException("Resource helper is invalid."); + } + + if (string.IsNullOrEmpty(m_ResourceManager.m_ReadWritePath)) + { + throw new GameFrameworkException("Read-write path is invalid."); + } + + m_VerifyResourceLengthPerFrame = verifyResourceLengthPerFrame; + m_ResourceManager.m_ResourceHelper.LoadBytes(Utility.Path.GetRemotePath(Path.Combine(m_ResourceManager.m_ReadWritePath, LocalVersionListFileName)), new LoadBytesCallbacks(OnLoadReadWriteVersionListSuccess, OnLoadReadWriteVersionListFailure), null); + } + + private bool VerifyResource(VerifyInfo verifyInfo) + { + if (verifyInfo.UseFileSystem) + { + IFileSystem fileSystem = m_ResourceManager.GetFileSystem(verifyInfo.FileSystemName, false); + string fileName = verifyInfo.ResourceName.FullName; + FileSystem.FileInfo fileInfo = fileSystem.GetFileInfo(fileName); + if (!fileInfo.IsValid) + { + return false; + } + + int length = fileInfo.Length; + if (length == verifyInfo.Length) + { + m_ResourceManager.PrepareCachedStream(); + fileSystem.ReadFile(fileName, m_ResourceManager.m_CachedStream); + m_ResourceManager.m_CachedStream.Position = 0L; + int hashCode = 0; + if (verifyInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || verifyInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt + || verifyInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || verifyInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + Utility.Converter.GetBytes(verifyInfo.HashCode, m_CachedHashBytes); + if (verifyInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || verifyInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt) + { + hashCode = Utility.Verifier.GetCrc32(m_ResourceManager.m_CachedStream, m_CachedHashBytes, Utility.Encryption.QuickEncryptLength); + } + else if (verifyInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt || verifyInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + hashCode = Utility.Verifier.GetCrc32(m_ResourceManager.m_CachedStream, m_CachedHashBytes, length); + } + + Array.Clear(m_CachedHashBytes, 0, CachedHashBytesLength); + } + else + { + hashCode = Utility.Verifier.GetCrc32(m_ResourceManager.m_CachedStream); + } + + if (hashCode == verifyInfo.HashCode) + { + return true; + } + } + + fileSystem.DeleteFile(fileName); + return false; + } + else + { + string resourcePath = Utility.Path.GetRegularPath(Path.Combine(m_ResourceManager.ReadWritePath, verifyInfo.ResourceName.FullName)); + if (!File.Exists(resourcePath)) + { + return false; + } + + using (FileStream fileStream = new FileStream(resourcePath, FileMode.Open, FileAccess.Read)) + { + int length = (int)fileStream.Length; + if (length == verifyInfo.Length) + { + int hashCode = 0; + if (verifyInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || verifyInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt + || verifyInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt || verifyInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + Utility.Converter.GetBytes(verifyInfo.HashCode, m_CachedHashBytes); + if (verifyInfo.LoadType == LoadType.LoadFromMemoryAndQuickDecrypt || verifyInfo.LoadType == LoadType.LoadFromBinaryAndQuickDecrypt) + { + hashCode = Utility.Verifier.GetCrc32(fileStream, m_CachedHashBytes, Utility.Encryption.QuickEncryptLength); + } + else if (verifyInfo.LoadType == LoadType.LoadFromMemoryAndDecrypt || verifyInfo.LoadType == LoadType.LoadFromBinaryAndDecrypt) + { + hashCode = Utility.Verifier.GetCrc32(fileStream, m_CachedHashBytes, length); + } + + Array.Clear(m_CachedHashBytes, 0, CachedHashBytesLength); + } + else + { + hashCode = Utility.Verifier.GetCrc32(fileStream); + } + + if (hashCode == verifyInfo.HashCode) + { + return true; + } + } + } + + File.Delete(resourcePath); + return false; + } + } + + private void GenerateReadWriteVersionList() + { + string readWriteVersionListFileName = Utility.Path.GetRegularPath(Path.Combine(m_ResourceManager.m_ReadWritePath, LocalVersionListFileName)); + string readWriteVersionListTempFileName = Utility.Text.Format("{0}.{1}", readWriteVersionListFileName, TempExtension); + SortedDictionary> cachedFileSystemsForGenerateReadWriteVersionList = new SortedDictionary>(StringComparer.Ordinal); + FileStream fileStream = null; + try + { + fileStream = new FileStream(readWriteVersionListTempFileName, FileMode.Create, FileAccess.Write); + LocalVersionList.Resource[] resources = m_VerifyInfos.Count > 0 ? new LocalVersionList.Resource[m_VerifyInfos.Count] : null; + if (resources != null) + { + int index = 0; + foreach (VerifyInfo i in m_VerifyInfos) + { + resources[index] = new LocalVersionList.Resource(i.ResourceName.Name, i.ResourceName.Variant, i.ResourceName.Extension, (byte)i.LoadType, i.Length, i.HashCode); + if (i.UseFileSystem) + { + List resourceIndexes = null; + if (!cachedFileSystemsForGenerateReadWriteVersionList.TryGetValue(i.FileSystemName, out resourceIndexes)) + { + resourceIndexes = new List(); + cachedFileSystemsForGenerateReadWriteVersionList.Add(i.FileSystemName, resourceIndexes); + } + + resourceIndexes.Add(index); + } + + index++; + } + } + + LocalVersionList.FileSystem[] fileSystems = cachedFileSystemsForGenerateReadWriteVersionList.Count > 0 ? new LocalVersionList.FileSystem[cachedFileSystemsForGenerateReadWriteVersionList.Count] : null; + if (fileSystems != null) + { + int index = 0; + foreach (KeyValuePair> i in cachedFileSystemsForGenerateReadWriteVersionList) + { + fileSystems[index++] = new LocalVersionList.FileSystem(i.Key, i.Value.ToArray()); + i.Value.Clear(); + } + } + + LocalVersionList versionList = new LocalVersionList(resources, fileSystems); + if (!m_ResourceManager.m_ReadWriteVersionListSerializer.Serialize(fileStream, versionList)) + { + throw new GameFrameworkException("Serialize read-write version list failure."); + } + + if (fileStream != null) + { + fileStream.Dispose(); + fileStream = null; + } + } + catch (Exception exception) + { + if (fileStream != null) + { + fileStream.Dispose(); + fileStream = null; + } + + if (File.Exists(readWriteVersionListTempFileName)) + { + File.Delete(readWriteVersionListTempFileName); + } + + throw new GameFrameworkException(Utility.Text.Format("Generate read-write version list exception '{0}'.", exception), exception); + } + + if (File.Exists(readWriteVersionListFileName)) + { + File.Delete(readWriteVersionListFileName); + } + + File.Move(readWriteVersionListTempFileName, readWriteVersionListFileName); + } + + private void OnLoadReadWriteVersionListSuccess(string fileUri, byte[] bytes, float duration, object userData) + { + MemoryStream memoryStream = null; + try + { + memoryStream = new MemoryStream(bytes, false); + LocalVersionList versionList = m_ResourceManager.m_ReadWriteVersionListSerializer.Deserialize(memoryStream); + if (!versionList.IsValid) + { + throw new GameFrameworkException("Deserialize read write version list failure."); + } + + LocalVersionList.Resource[] resources = versionList.GetResources(); + LocalVersionList.FileSystem[] fileSystems = versionList.GetFileSystems(); + Dictionary resourceInFileSystemNames = new Dictionary(); + foreach (LocalVersionList.FileSystem fileSystem in fileSystems) + { + int[] resourceIndexes = fileSystem.GetResourceIndexes(); + foreach (int resourceIndex in resourceIndexes) + { + LocalVersionList.Resource resource = resources[resourceIndex]; + resourceInFileSystemNames.Add(new ResourceName(resource.Name, resource.Variant, resource.Extension), fileSystem.Name); + } + } + + long totalLength = 0L; + foreach (LocalVersionList.Resource resource in resources) + { + ResourceName resourceName = new ResourceName(resource.Name, resource.Variant, resource.Extension); + string fileSystemName = null; + resourceInFileSystemNames.TryGetValue(resourceName, out fileSystemName); + totalLength += resource.Length; + m_VerifyInfos.Add(new VerifyInfo(resourceName, fileSystemName, (LoadType)resource.LoadType, resource.Length, resource.HashCode)); + } + + m_LoadReadWriteVersionListComplete = true; + if (ResourceVerifyStart != null) + { + ResourceVerifyStart(m_VerifyInfos.Count, totalLength); + } + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Utility.Text.Format("Parse read-write version list exception '{0}'.", exception), exception); + } + finally + { + if (memoryStream != null) + { + memoryStream.Dispose(); + memoryStream = null; + } + } + } + + private void OnLoadReadWriteVersionListFailure(string fileUri, string errorMessage, object userData) + { + if (ResourceVerifyComplete != null) + { + ResourceVerifyComplete(true); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceVerifier.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceVerifier.cs.meta new file mode 100644 index 0000000..0959144 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.ResourceVerifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 318384a89313df94c902e3d9e8a558d1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.VersionListProcessor.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.VersionListProcessor.cs new file mode 100644 index 0000000..d5caff4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.VersionListProcessor.cs @@ -0,0 +1,249 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Download; +using System; +using System.IO; + +namespace GameFramework.Resource +{ + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + /// + /// 版本资源列表处理器。 + /// + private sealed class VersionListProcessor + { + private readonly ResourceManager m_ResourceManager; + private IDownloadManager m_DownloadManager; + private int m_VersionListLength; + private int m_VersionListHashCode; + private int m_VersionListCompressedLength; + private int m_VersionListCompressedHashCode; + + public GameFrameworkAction VersionListUpdateSuccess; + public GameFrameworkAction VersionListUpdateFailure; + + /// + /// 初始化版本资源列表处理器的新实例。 + /// + /// 资源管理器。 + public VersionListProcessor(ResourceManager resourceManager) + { + m_ResourceManager = resourceManager; + m_DownloadManager = null; + m_VersionListLength = 0; + m_VersionListHashCode = 0; + m_VersionListCompressedLength = 0; + m_VersionListCompressedHashCode = 0; + + VersionListUpdateSuccess = null; + VersionListUpdateFailure = null; + } + + /// + /// 关闭并清理版本资源列表处理器。 + /// + public void Shutdown() + { + if (m_DownloadManager != null) + { + m_DownloadManager.DownloadSuccess -= OnDownloadSuccess; + m_DownloadManager.DownloadFailure -= OnDownloadFailure; + } + } + + /// + /// 设置下载管理器。 + /// + /// 下载管理器。 + public void SetDownloadManager(IDownloadManager downloadManager) + { + if (downloadManager == null) + { + throw new GameFrameworkException("Download manager is invalid."); + } + + m_DownloadManager = downloadManager; + m_DownloadManager.DownloadSuccess += OnDownloadSuccess; + m_DownloadManager.DownloadFailure += OnDownloadFailure; + } + + /// + /// 检查版本资源列表。 + /// + /// 最新的内部资源版本号。 + /// 检查版本资源列表结果。 + public CheckVersionListResult CheckVersionList(int latestInternalResourceVersion) + { + if (string.IsNullOrEmpty(m_ResourceManager.m_ReadWritePath)) + { + throw new GameFrameworkException("Read-write path is invalid."); + } + + string versionListFileName = Utility.Path.GetRegularPath(Path.Combine(m_ResourceManager.m_ReadWritePath, RemoteVersionListFileName)); + if (!File.Exists(versionListFileName)) + { + return CheckVersionListResult.NeedUpdate; + } + + int internalResourceVersion = 0; + FileStream fileStream = null; + try + { + fileStream = new FileStream(versionListFileName, FileMode.Open, FileAccess.Read); + object internalResourceVersionObject = null; + if (!m_ResourceManager.m_UpdatableVersionListSerializer.TryGetValue(fileStream, "InternalResourceVersion", out internalResourceVersionObject)) + { + return CheckVersionListResult.NeedUpdate; + } + + internalResourceVersion = (int)internalResourceVersionObject; + } + catch + { + return CheckVersionListResult.NeedUpdate; + } + finally + { + if (fileStream != null) + { + fileStream.Dispose(); + fileStream = null; + } + } + + if (internalResourceVersion != latestInternalResourceVersion) + { + return CheckVersionListResult.NeedUpdate; + } + + return CheckVersionListResult.Updated; + } + + /// + /// 更新版本资源列表。 + /// + /// 版本资源列表大小。 + /// 版本资源列表哈希值。 + /// 版本资源列表压缩后大小。 + /// 版本资源列表压缩后哈希值。 + public void UpdateVersionList(int versionListLength, int versionListHashCode, int versionListCompressedLength, int versionListCompressedHashCode) + { + if (m_DownloadManager == null) + { + throw new GameFrameworkException("You must set download manager first."); + } + + m_VersionListLength = versionListLength; + m_VersionListHashCode = versionListHashCode; + m_VersionListCompressedLength = versionListCompressedLength; + m_VersionListCompressedHashCode = versionListCompressedHashCode; + string localVersionListFilePath = Utility.Path.GetRegularPath(Path.Combine(m_ResourceManager.m_ReadWritePath, RemoteVersionListFileName)); + int dotPosition = RemoteVersionListFileName.LastIndexOf('.'); + string latestVersionListFullNameWithCrc32 = Utility.Text.Format("{0}.{2:x8}.{1}", RemoteVersionListFileName.Substring(0, dotPosition), RemoteVersionListFileName.Substring(dotPosition + 1), m_VersionListHashCode); + m_DownloadManager.AddDownload(localVersionListFilePath, Utility.Path.GetRemotePath(Path.Combine(m_ResourceManager.m_UpdatePrefixUri, latestVersionListFullNameWithCrc32)), this); + } + + private void OnDownloadSuccess(object sender, DownloadSuccessEventArgs e) + { + VersionListProcessor versionListProcessor = e.UserData as VersionListProcessor; + if (versionListProcessor == null || versionListProcessor != this) + { + return; + } + + try + { + using (FileStream fileStream = new FileStream(e.DownloadPath, FileMode.Open, FileAccess.ReadWrite)) + { + int length = (int)fileStream.Length; + if (length != m_VersionListCompressedLength) + { + fileStream.Close(); + string errorMessage = Utility.Text.Format("Latest version list compressed length error, need '{0}', downloaded '{1}'.", m_VersionListCompressedLength, length); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + return; + } + + fileStream.Position = 0L; + int hashCode = Utility.Verifier.GetCrc32(fileStream); + if (hashCode != m_VersionListCompressedHashCode) + { + fileStream.Close(); + string errorMessage = Utility.Text.Format("Latest version list compressed hash code error, need '{0}', downloaded '{1}'.", m_VersionListCompressedHashCode, hashCode); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + return; + } + + fileStream.Position = 0L; + m_ResourceManager.PrepareCachedStream(); + if (!Utility.Compression.Decompress(fileStream, m_ResourceManager.m_CachedStream)) + { + fileStream.Close(); + string errorMessage = Utility.Text.Format("Unable to decompress latest version list '{0}'.", e.DownloadPath); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + return; + } + + int uncompressedLength = (int)m_ResourceManager.m_CachedStream.Length; + if (uncompressedLength != m_VersionListLength) + { + fileStream.Close(); + string errorMessage = Utility.Text.Format("Latest version list length error, need '{0}', downloaded '{1}'.", m_VersionListLength, uncompressedLength); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + return; + } + + fileStream.Position = 0L; + fileStream.SetLength(0L); + fileStream.Write(m_ResourceManager.m_CachedStream.GetBuffer(), 0, uncompressedLength); + } + + if (VersionListUpdateSuccess != null) + { + VersionListUpdateSuccess(e.DownloadPath, e.DownloadUri); + } + } + catch (Exception exception) + { + string errorMessage = Utility.Text.Format("Update latest version list '{0}' with error message '{1}'.", e.DownloadPath, exception); + DownloadFailureEventArgs downloadFailureEventArgs = DownloadFailureEventArgs.Create(e.SerialId, e.DownloadPath, e.DownloadUri, errorMessage, e.UserData); + OnDownloadFailure(this, downloadFailureEventArgs); + ReferencePool.Release(downloadFailureEventArgs); + } + } + + private void OnDownloadFailure(object sender, DownloadFailureEventArgs e) + { + VersionListProcessor versionListProcessor = e.UserData as VersionListProcessor; + if (versionListProcessor == null || versionListProcessor != this) + { + return; + } + + if (File.Exists(e.DownloadPath)) + { + File.Delete(e.DownloadPath); + } + + if (VersionListUpdateFailure != null) + { + VersionListUpdateFailure(e.DownloadUri, e.ErrorMessage); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.VersionListProcessor.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.VersionListProcessor.cs.meta new file mode 100644 index 0000000..3c58369 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.VersionListProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8e63f681247edbd4782b772c6caaf4ee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.cs new file mode 100644 index 0000000..a6656bb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.cs @@ -0,0 +1,2587 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Download; +using GameFramework.FileSystem; +using GameFramework.ObjectPool; +using System; +using System.Collections.Generic; +using System.IO; + +namespace GameFramework.Resource +{ + /// + /// 资源管理器。 + /// + internal sealed partial class ResourceManager : GameFrameworkModule, IResourceManager + { + private const string RemoteVersionListFileName = "GameFrameworkVersion.dat"; + private const string LocalVersionListFileName = "GameFrameworkList.dat"; + private const string DefaultExtension = "dat"; + private const string TempExtension = "tmp"; + private const int FileSystemMaxFileCount = 1024 * 16; + private const int FileSystemMaxBlockCount = 1024 * 256; + + private Dictionary m_AssetInfos; + private Dictionary m_ResourceInfos; + private SortedDictionary m_ReadWriteResourceInfos; + private readonly Dictionary m_ReadOnlyFileSystems; + private readonly Dictionary m_ReadWriteFileSystems; + private readonly Dictionary m_ResourceGroups; + + private PackageVersionListSerializer m_PackageVersionListSerializer; + private UpdatableVersionListSerializer m_UpdatableVersionListSerializer; + private ReadOnlyVersionListSerializer m_ReadOnlyVersionListSerializer; + private ReadWriteVersionListSerializer m_ReadWriteVersionListSerializer; + private ResourcePackVersionListSerializer m_ResourcePackVersionListSerializer; + + private IFileSystemManager m_FileSystemManager; + private ResourceIniter m_ResourceIniter; + private VersionListProcessor m_VersionListProcessor; + private ResourceVerifier m_ResourceVerifier; + private ResourceChecker m_ResourceChecker; + private ResourceUpdater m_ResourceUpdater; + private ResourceLoader m_ResourceLoader; + private IResourceHelper m_ResourceHelper; + + private string m_ReadOnlyPath; + private string m_ReadWritePath; + private ResourceMode m_ResourceMode; + private bool m_RefuseSetFlag; + private string m_CurrentVariant; + private string m_UpdatePrefixUri; + private string m_ApplicableGameVersion; + private int m_InternalResourceVersion; + private MemoryStream m_CachedStream; + private DecryptResourceCallback m_DecryptResourceCallback; + private InitResourcesCompleteCallback m_InitResourcesCompleteCallback; + private UpdateVersionListCallbacks m_UpdateVersionListCallbacks; + private VerifyResourcesCompleteCallback m_VerifyResourcesCompleteCallback; + private CheckResourcesCompleteCallback m_CheckResourcesCompleteCallback; + private ApplyResourcesCompleteCallback m_ApplyResourcesCompleteCallback; + private UpdateResourcesCompleteCallback m_UpdateResourcesCompleteCallback; + private EventHandler m_ResourceVerifyStartEventHandler; + private EventHandler m_ResourceVerifySuccessEventHandler; + private EventHandler m_ResourceVerifyFailureEventHandler; + private EventHandler m_ResourceApplyStartEventHandler; + private EventHandler m_ResourceApplySuccessEventHandler; + private EventHandler m_ResourceApplyFailureEventHandler; + private EventHandler m_ResourceUpdateStartEventHandler; + private EventHandler m_ResourceUpdateChangedEventHandler; + private EventHandler m_ResourceUpdateSuccessEventHandler; + private EventHandler m_ResourceUpdateFailureEventHandler; + private EventHandler m_ResourceUpdateAllCompleteEventHandler; + + /// + /// 初始化资源管理器的新实例。 + /// + public ResourceManager() + { + m_AssetInfos = null; + m_ResourceInfos = null; + m_ReadWriteResourceInfos = null; + m_ReadOnlyFileSystems = new Dictionary(StringComparer.Ordinal); + m_ReadWriteFileSystems = new Dictionary(StringComparer.Ordinal); + m_ResourceGroups = new Dictionary(StringComparer.Ordinal); + + m_PackageVersionListSerializer = null; + m_UpdatableVersionListSerializer = null; + m_ReadOnlyVersionListSerializer = null; + m_ReadWriteVersionListSerializer = null; + m_ResourcePackVersionListSerializer = null; + + m_ResourceIniter = null; + m_VersionListProcessor = null; + m_ResourceVerifier = null; + m_ResourceChecker = null; + m_ResourceUpdater = null; + m_ResourceLoader = new ResourceLoader(this); + + m_ResourceHelper = null; + m_ReadOnlyPath = null; + m_ReadWritePath = null; + m_ResourceMode = ResourceMode.Unspecified; + m_RefuseSetFlag = false; + m_CurrentVariant = null; + m_UpdatePrefixUri = null; + m_ApplicableGameVersion = null; + m_InternalResourceVersion = 0; + m_CachedStream = null; + m_DecryptResourceCallback = null; + m_InitResourcesCompleteCallback = null; + m_UpdateVersionListCallbacks = null; + m_VerifyResourcesCompleteCallback = null; + m_CheckResourcesCompleteCallback = null; + m_ApplyResourcesCompleteCallback = null; + m_UpdateResourcesCompleteCallback = null; + m_ResourceVerifySuccessEventHandler = null; + m_ResourceVerifyFailureEventHandler = null; + m_ResourceApplySuccessEventHandler = null; + m_ResourceApplyFailureEventHandler = null; + m_ResourceUpdateStartEventHandler = null; + m_ResourceUpdateChangedEventHandler = null; + m_ResourceUpdateSuccessEventHandler = null; + m_ResourceUpdateFailureEventHandler = null; + m_ResourceUpdateAllCompleteEventHandler = null; + } + + /// + /// 获取游戏框架模块优先级。 + /// + /// 优先级较高的模块会优先轮询,并且关闭操作会后进行。 + internal override int Priority + { + get + { + return 3; + } + } + + /// + /// 获取资源只读区路径。 + /// + public string ReadOnlyPath + { + get + { + return m_ReadOnlyPath; + } + } + + /// + /// 获取资源读写区路径。 + /// + public string ReadWritePath + { + get + { + return m_ReadWritePath; + } + } + + /// + /// 获取资源模式。 + /// + public ResourceMode ResourceMode + { + get + { + return m_ResourceMode; + } + } + + /// + /// 获取当前变体。 + /// + public string CurrentVariant + { + get + { + return m_CurrentVariant; + } + } + + /// + /// 获取单机模式版本资源列表序列化器。 + /// + public PackageVersionListSerializer PackageVersionListSerializer + { + get + { + return m_PackageVersionListSerializer; + } + } + + /// + /// 获取可更新模式版本资源列表序列化器。 + /// + public UpdatableVersionListSerializer UpdatableVersionListSerializer + { + get + { + return m_UpdatableVersionListSerializer; + } + } + + /// + /// 获取本地只读区版本资源列表序列化器。 + /// + public ReadOnlyVersionListSerializer ReadOnlyVersionListSerializer + { + get + { + return m_ReadOnlyVersionListSerializer; + } + } + + /// + /// 获取本地读写区版本资源列表序列化器。 + /// + public ReadWriteVersionListSerializer ReadWriteVersionListSerializer + { + get + { + return m_ReadWriteVersionListSerializer; + } + } + + /// + /// 获取资源包版本资源列表序列化器。 + /// + public ResourcePackVersionListSerializer ResourcePackVersionListSerializer + { + get + { + return m_ResourcePackVersionListSerializer; + } + } + + /// + /// 获取当前资源适用的游戏版本号。 + /// + public string ApplicableGameVersion + { + get + { + return m_ApplicableGameVersion; + } + } + + /// + /// 获取当前内部资源版本号。 + /// + public int InternalResourceVersion + { + get + { + return m_InternalResourceVersion; + } + } + + /// + /// 获取资源数量。 + /// + public int AssetCount + { + get + { + return m_AssetInfos != null ? m_AssetInfos.Count : 0; + } + } + + /// + /// 获取资源数量。 + /// + public int ResourceCount + { + get + { + return m_ResourceInfos != null ? m_ResourceInfos.Count : 0; + } + } + + /// + /// 获取资源组数量。 + /// + public int ResourceGroupCount + { + get + { + return m_ResourceGroups.Count; + } + } + + /// + /// 获取或设置资源更新下载地址前缀。 + /// + public string UpdatePrefixUri + { + get + { + return m_UpdatePrefixUri; + } + set + { + m_UpdatePrefixUri = value; + } + } + + /// + /// 获取或设置每更新多少字节的资源,重新生成一次版本资源列表。 + /// + public int GenerateReadWriteVersionListLength + { + get + { + return m_ResourceUpdater != null ? m_ResourceUpdater.GenerateReadWriteVersionListLength : 0; + } + set + { + if (m_ResourceUpdater == null) + { + throw new GameFrameworkException("You can not use GenerateReadWriteVersionListLength at this time."); + } + + m_ResourceUpdater.GenerateReadWriteVersionListLength = value; + } + } + + /// + /// 获取正在应用的资源包路径。 + /// + public string ApplyingResourcePackPath + { + get + { + return m_ResourceUpdater != null ? m_ResourceUpdater.ApplyingResourcePackPath : null; + } + } + + /// + /// 获取等待应用资源数量。 + /// + public int ApplyWaitingCount + { + get + { + return m_ResourceUpdater != null ? m_ResourceUpdater.ApplyWaitingCount : 0; + } + } + + /// + /// 获取或设置资源更新重试次数。 + /// + public int UpdateRetryCount + { + get + { + return m_ResourceUpdater != null ? m_ResourceUpdater.UpdateRetryCount : 0; + } + set + { + if (m_ResourceUpdater == null) + { + throw new GameFrameworkException("You can not use UpdateRetryCount at this time."); + } + + m_ResourceUpdater.UpdateRetryCount = value; + } + } + + /// + /// 获取正在更新的资源组。 + /// + public IResourceGroup UpdatingResourceGroup + { + get + { + return m_ResourceUpdater != null ? m_ResourceUpdater.UpdatingResourceGroup : null; + } + } + + /// + /// 获取等待更新资源数量。 + /// + public int UpdateWaitingCount + { + get + { + return m_ResourceUpdater != null ? m_ResourceUpdater.UpdateWaitingCount : 0; + } + } + + /// + /// 获取使用时下载的等待更新资源数量。 + /// + public int UpdateWaitingWhilePlayingCount + { + get + { + return m_ResourceUpdater != null ? m_ResourceUpdater.UpdateWaitingWhilePlayingCount : 0; + } + } + + /// + /// 获取候选更新资源数量。 + /// + public int UpdateCandidateCount + { + get + { + return m_ResourceUpdater != null ? m_ResourceUpdater.UpdateCandidateCount : 0; + } + } + + /// + /// 获取加载资源代理总数量。 + /// + public int LoadTotalAgentCount + { + get + { + return m_ResourceLoader.TotalAgentCount; + } + } + + /// + /// 获取可用加载资源代理数量。 + /// + public int LoadFreeAgentCount + { + get + { + return m_ResourceLoader.FreeAgentCount; + } + } + + /// + /// 获取工作中加载资源代理数量。 + /// + public int LoadWorkingAgentCount + { + get + { + return m_ResourceLoader.WorkingAgentCount; + } + } + + /// + /// 获取等待加载资源任务数量。 + /// + public int LoadWaitingTaskCount + { + get + { + return m_ResourceLoader.WaitingTaskCount; + } + } + + /// + /// 获取或设置资源对象池自动释放可释放对象的间隔秒数。 + /// + public float AssetAutoReleaseInterval + { + get + { + return m_ResourceLoader.AssetAutoReleaseInterval; + } + set + { + m_ResourceLoader.AssetAutoReleaseInterval = value; + } + } + + /// + /// 获取或设置资源对象池的容量。 + /// + public int AssetCapacity + { + get + { + return m_ResourceLoader.AssetCapacity; + } + set + { + m_ResourceLoader.AssetCapacity = value; + } + } + + /// + /// 获取或设置资源对象池对象过期秒数。 + /// + public float AssetExpireTime + { + get + { + return m_ResourceLoader.AssetExpireTime; + } + set + { + m_ResourceLoader.AssetExpireTime = value; + } + } + + /// + /// 获取或设置资源对象池的优先级。 + /// + public int AssetPriority + { + get + { + return m_ResourceLoader.AssetPriority; + } + set + { + m_ResourceLoader.AssetPriority = value; + } + } + + /// + /// 获取或设置资源对象池自动释放可释放对象的间隔秒数。 + /// + public float ResourceAutoReleaseInterval + { + get + { + return m_ResourceLoader.ResourceAutoReleaseInterval; + } + set + { + m_ResourceLoader.ResourceAutoReleaseInterval = value; + } + } + + /// + /// 获取或设置资源对象池的容量。 + /// + public int ResourceCapacity + { + get + { + return m_ResourceLoader.ResourceCapacity; + } + set + { + m_ResourceLoader.ResourceCapacity = value; + } + } + + /// + /// 获取或设置资源对象池对象过期秒数。 + /// + public float ResourceExpireTime + { + get + { + return m_ResourceLoader.ResourceExpireTime; + } + set + { + m_ResourceLoader.ResourceExpireTime = value; + } + } + + /// + /// 获取或设置资源对象池的优先级。 + /// + public int ResourcePriority + { + get + { + return m_ResourceLoader.ResourcePriority; + } + set + { + m_ResourceLoader.ResourcePriority = value; + } + } + + /// + /// 资源校验开始事件。 + /// + public event EventHandler ResourceVerifyStart + { + add + { + m_ResourceVerifyStartEventHandler += value; + } + remove + { + m_ResourceVerifyStartEventHandler -= value; + } + } + + /// + /// 资源校验成功事件。 + /// + public event EventHandler ResourceVerifySuccess + { + add + { + m_ResourceVerifySuccessEventHandler += value; + } + remove + { + m_ResourceVerifySuccessEventHandler -= value; + } + } + + /// + /// 资源校验失败事件。 + /// + public event EventHandler ResourceVerifyFailure + { + add + { + m_ResourceVerifyFailureEventHandler += value; + } + remove + { + m_ResourceVerifyFailureEventHandler -= value; + } + } + + /// + /// 资源应用开始事件。 + /// + public event EventHandler ResourceApplyStart + { + add + { + m_ResourceApplyStartEventHandler += value; + } + remove + { + m_ResourceApplyStartEventHandler -= value; + } + } + + /// + /// 资源应用成功事件。 + /// + public event EventHandler ResourceApplySuccess + { + add + { + m_ResourceApplySuccessEventHandler += value; + } + remove + { + m_ResourceApplySuccessEventHandler -= value; + } + } + + /// + /// 资源应用失败事件。 + /// + public event EventHandler ResourceApplyFailure + { + add + { + m_ResourceApplyFailureEventHandler += value; + } + remove + { + m_ResourceApplyFailureEventHandler -= value; + } + } + + /// + /// 资源更新开始事件。 + /// + public event EventHandler ResourceUpdateStart + { + add + { + m_ResourceUpdateStartEventHandler += value; + } + remove + { + m_ResourceUpdateStartEventHandler -= value; + } + } + + /// + /// 资源更新改变事件。 + /// + public event EventHandler ResourceUpdateChanged + { + add + { + m_ResourceUpdateChangedEventHandler += value; + } + remove + { + m_ResourceUpdateChangedEventHandler -= value; + } + } + + /// + /// 资源更新成功事件。 + /// + public event EventHandler ResourceUpdateSuccess + { + add + { + m_ResourceUpdateSuccessEventHandler += value; + } + remove + { + m_ResourceUpdateSuccessEventHandler -= value; + } + } + + /// + /// 资源更新失败事件。 + /// + public event EventHandler ResourceUpdateFailure + { + add + { + m_ResourceUpdateFailureEventHandler += value; + } + remove + { + m_ResourceUpdateFailureEventHandler -= value; + } + } + + /// + /// 资源更新全部完成事件。 + /// + public event EventHandler ResourceUpdateAllComplete + { + add + { + m_ResourceUpdateAllCompleteEventHandler += value; + } + remove + { + m_ResourceUpdateAllCompleteEventHandler -= value; + } + } + + /// + /// 资源管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + if (m_ResourceVerifier != null) + { + m_ResourceVerifier.Update(elapseSeconds, realElapseSeconds); + return; + } + + if (m_ResourceUpdater != null) + { + m_ResourceUpdater.Update(elapseSeconds, realElapseSeconds); + } + + m_ResourceLoader.Update(elapseSeconds, realElapseSeconds); + } + + /// + /// 关闭并清理资源管理器。 + /// + internal override void Shutdown() + { + if (m_ResourceIniter != null) + { + m_ResourceIniter.Shutdown(); + m_ResourceIniter = null; + } + + if (m_VersionListProcessor != null) + { + m_VersionListProcessor.VersionListUpdateSuccess -= OnVersionListProcessorUpdateSuccess; + m_VersionListProcessor.VersionListUpdateFailure -= OnVersionListProcessorUpdateFailure; + m_VersionListProcessor.Shutdown(); + m_VersionListProcessor = null; + } + + if (m_ResourceVerifier != null) + { + m_ResourceVerifier.ResourceVerifyStart -= OnVerifierResourceVerifyStart; + m_ResourceVerifier.ResourceVerifySuccess -= OnVerifierResourceVerifySuccess; + m_ResourceVerifier.ResourceVerifyFailure -= OnVerifierResourceVerifyFailure; + m_ResourceVerifier.ResourceVerifyComplete -= OnVerifierResourceVerifyComplete; + m_ResourceVerifier.Shutdown(); + m_ResourceVerifier = null; + } + + if (m_ResourceChecker != null) + { + m_ResourceChecker.ResourceNeedUpdate -= OnCheckerResourceNeedUpdate; + m_ResourceChecker.ResourceCheckComplete -= OnCheckerResourceCheckComplete; + m_ResourceChecker.Shutdown(); + m_ResourceChecker = null; + } + + if (m_ResourceUpdater != null) + { + m_ResourceUpdater.ResourceApplyStart -= OnUpdaterResourceApplyStart; + m_ResourceUpdater.ResourceApplySuccess -= OnUpdaterResourceApplySuccess; + m_ResourceUpdater.ResourceApplyFailure -= OnUpdaterResourceApplyFailure; + m_ResourceUpdater.ResourceApplyComplete -= OnUpdaterResourceApplyComplete; + m_ResourceUpdater.ResourceUpdateStart -= OnUpdaterResourceUpdateStart; + m_ResourceUpdater.ResourceUpdateChanged -= OnUpdaterResourceUpdateChanged; + m_ResourceUpdater.ResourceUpdateSuccess -= OnUpdaterResourceUpdateSuccess; + m_ResourceUpdater.ResourceUpdateFailure -= OnUpdaterResourceUpdateFailure; + m_ResourceUpdater.ResourceUpdateComplete -= OnUpdaterResourceUpdateComplete; + m_ResourceUpdater.ResourceUpdateAllComplete -= OnUpdaterResourceUpdateAllComplete; + m_ResourceUpdater.Shutdown(); + m_ResourceUpdater = null; + + if (m_ReadWriteResourceInfos != null) + { + m_ReadWriteResourceInfos.Clear(); + m_ReadWriteResourceInfos = null; + } + + FreeCachedStream(); + } + + if (m_ResourceLoader != null) + { + m_ResourceLoader.Shutdown(); + m_ResourceLoader = null; + } + + if (m_AssetInfos != null) + { + m_AssetInfos.Clear(); + m_AssetInfos = null; + } + + if (m_ResourceInfos != null) + { + m_ResourceInfos.Clear(); + m_ResourceInfos = null; + } + + m_ReadOnlyFileSystems.Clear(); + m_ReadWriteFileSystems.Clear(); + m_ResourceGroups.Clear(); + } + + /// + /// 设置资源只读区路径。 + /// + /// 资源只读区路径。 + public void SetReadOnlyPath(string readOnlyPath) + { + if (string.IsNullOrEmpty(readOnlyPath)) + { + throw new GameFrameworkException("Read-only path is invalid."); + } + + if (m_RefuseSetFlag) + { + throw new GameFrameworkException("You can not set read-only path at this time."); + } + + if (m_ResourceLoader.TotalAgentCount > 0) + { + throw new GameFrameworkException("You must set read-only path before add load resource agent helper."); + } + + m_ReadOnlyPath = readOnlyPath; + } + + /// + /// 设置资源读写区路径。 + /// + /// 资源读写区路径。 + public void SetReadWritePath(string readWritePath) + { + if (string.IsNullOrEmpty(readWritePath)) + { + throw new GameFrameworkException("Read-write path is invalid."); + } + + if (m_RefuseSetFlag) + { + throw new GameFrameworkException("You can not set read-write path at this time."); + } + + if (m_ResourceLoader.TotalAgentCount > 0) + { + throw new GameFrameworkException("You must set read-write path before add load resource agent helper."); + } + + m_ReadWritePath = readWritePath; + } + + /// + /// 设置资源模式。 + /// + /// 资源模式。 + public void SetResourceMode(ResourceMode resourceMode) + { + if (resourceMode == ResourceMode.Unspecified) + { + throw new GameFrameworkException("Resource mode is invalid."); + } + + if (m_RefuseSetFlag) + { + throw new GameFrameworkException("You can not set resource mode at this time."); + } + + if (m_ResourceMode == ResourceMode.Unspecified) + { + m_ResourceMode = resourceMode; + + if (m_ResourceMode == ResourceMode.Package) + { + m_PackageVersionListSerializer = new PackageVersionListSerializer(); + + m_ResourceIniter = new ResourceIniter(this); + m_ResourceIniter.ResourceInitComplete += OnIniterResourceInitComplete; + } + else if (m_ResourceMode == ResourceMode.Updatable || m_ResourceMode == ResourceMode.UpdatableWhilePlaying) + { + m_UpdatableVersionListSerializer = new UpdatableVersionListSerializer(); + m_ReadOnlyVersionListSerializer = new ReadOnlyVersionListSerializer(); + m_ReadWriteVersionListSerializer = new ReadWriteVersionListSerializer(); + m_ResourcePackVersionListSerializer = new ResourcePackVersionListSerializer(); + + m_VersionListProcessor = new VersionListProcessor(this); + m_VersionListProcessor.VersionListUpdateSuccess += OnVersionListProcessorUpdateSuccess; + m_VersionListProcessor.VersionListUpdateFailure += OnVersionListProcessorUpdateFailure; + + m_ResourceChecker = new ResourceChecker(this); + m_ResourceChecker.ResourceNeedUpdate += OnCheckerResourceNeedUpdate; + m_ResourceChecker.ResourceCheckComplete += OnCheckerResourceCheckComplete; + + m_ResourceUpdater = new ResourceUpdater(this); + m_ResourceUpdater.ResourceApplyStart += OnUpdaterResourceApplyStart; + m_ResourceUpdater.ResourceApplySuccess += OnUpdaterResourceApplySuccess; + m_ResourceUpdater.ResourceApplyFailure += OnUpdaterResourceApplyFailure; + m_ResourceUpdater.ResourceApplyComplete += OnUpdaterResourceApplyComplete; + m_ResourceUpdater.ResourceUpdateStart += OnUpdaterResourceUpdateStart; + m_ResourceUpdater.ResourceUpdateChanged += OnUpdaterResourceUpdateChanged; + m_ResourceUpdater.ResourceUpdateSuccess += OnUpdaterResourceUpdateSuccess; + m_ResourceUpdater.ResourceUpdateFailure += OnUpdaterResourceUpdateFailure; + m_ResourceUpdater.ResourceUpdateComplete += OnUpdaterResourceUpdateComplete; + m_ResourceUpdater.ResourceUpdateAllComplete += OnUpdaterResourceUpdateAllComplete; + } + } + else if (m_ResourceMode != resourceMode) + { + throw new GameFrameworkException("You can not change resource mode at this time."); + } + } + + /// + /// 设置当前变体。 + /// + /// 当前变体。 + public void SetCurrentVariant(string currentVariant) + { + if (m_RefuseSetFlag) + { + throw new GameFrameworkException("You can not set current variant at this time."); + } + + m_CurrentVariant = currentVariant; + } + + /// + /// 设置对象池管理器。 + /// + /// 对象池管理器。 + public void SetObjectPoolManager(IObjectPoolManager objectPoolManager) + { + if (objectPoolManager == null) + { + throw new GameFrameworkException("Object pool manager is invalid."); + } + + m_ResourceLoader.SetObjectPoolManager(objectPoolManager); + } + + /// + /// 设置文件系统管理器。 + /// + /// 文件系统管理器。 + public void SetFileSystemManager(IFileSystemManager fileSystemManager) + { + if (fileSystemManager == null) + { + throw new GameFrameworkException("File system manager is invalid."); + } + + m_FileSystemManager = fileSystemManager; + } + + /// + /// 设置下载管理器。 + /// + /// 下载管理器。 + public void SetDownloadManager(IDownloadManager downloadManager) + { + if (downloadManager == null) + { + throw new GameFrameworkException("Download manager is invalid."); + } + + if (m_VersionListProcessor != null) + { + m_VersionListProcessor.SetDownloadManager(downloadManager); + } + + if (m_ResourceUpdater != null) + { + m_ResourceUpdater.SetDownloadManager(downloadManager); + } + } + + /// + /// 设置解密资源回调函数。 + /// + /// 要设置的解密资源回调函数。 + /// 如果不设置,将使用默认的解密资源回调函数。 + public void SetDecryptResourceCallback(DecryptResourceCallback decryptResourceCallback) + { + if (m_ResourceLoader.TotalAgentCount > 0) + { + throw new GameFrameworkException("You must set decrypt resource callback before add load resource agent helper."); + } + + m_DecryptResourceCallback = decryptResourceCallback; + } + + /// + /// 设置资源辅助器。 + /// + /// 资源辅助器。 + public void SetResourceHelper(IResourceHelper resourceHelper) + { + if (resourceHelper == null) + { + throw new GameFrameworkException("Resource helper is invalid."); + } + + if (m_ResourceLoader.TotalAgentCount > 0) + { + throw new GameFrameworkException("You must set resource helper before add load resource agent helper."); + } + + m_ResourceHelper = resourceHelper; + } + + /// + /// 增加加载资源代理辅助器。 + /// + /// 要增加的加载资源代理辅助器。 + public void AddLoadResourceAgentHelper(ILoadResourceAgentHelper loadResourceAgentHelper) + { + if (m_ResourceHelper == null) + { + throw new GameFrameworkException("Resource helper is invalid."); + } + + if (string.IsNullOrEmpty(m_ReadOnlyPath)) + { + throw new GameFrameworkException("Read-only path is invalid."); + } + + if (string.IsNullOrEmpty(m_ReadWritePath)) + { + throw new GameFrameworkException("Read-write path is invalid."); + } + + m_ResourceLoader.AddLoadResourceAgentHelper(loadResourceAgentHelper, m_ResourceHelper, m_ReadOnlyPath, m_ReadWritePath, m_DecryptResourceCallback); + } + + /// + /// 使用单机模式并初始化资源。 + /// + /// 使用单机模式并初始化资源完成时的回调函数。 + public void InitResources(InitResourcesCompleteCallback initResourcesCompleteCallback) + { + if (initResourcesCompleteCallback == null) + { + throw new GameFrameworkException("Init resources complete callback is invalid."); + } + + if (m_ResourceMode == ResourceMode.Unspecified) + { + throw new GameFrameworkException("You must set resource mode first."); + } + + if (m_ResourceMode != ResourceMode.Package) + { + throw new GameFrameworkException("You can not use InitResources without package resource mode."); + } + + if (m_ResourceIniter == null) + { + throw new GameFrameworkException("You can not use InitResources at this time."); + } + + m_RefuseSetFlag = true; + m_InitResourcesCompleteCallback = initResourcesCompleteCallback; + m_ResourceIniter.InitResources(m_CurrentVariant); + } + + /// + /// 使用可更新模式并检查版本资源列表。 + /// + /// 最新的内部资源版本号。 + /// 检查版本资源列表结果。 + public CheckVersionListResult CheckVersionList(int latestInternalResourceVersion) + { + if (m_ResourceMode == ResourceMode.Unspecified) + { + throw new GameFrameworkException("You must set resource mode first."); + } + + if (m_ResourceMode != ResourceMode.Updatable && m_ResourceMode != ResourceMode.UpdatableWhilePlaying) + { + throw new GameFrameworkException("You can not use CheckVersionList without updatable resource mode."); + } + + if (m_VersionListProcessor == null) + { + throw new GameFrameworkException("You can not use CheckVersionList at this time."); + } + + return m_VersionListProcessor.CheckVersionList(latestInternalResourceVersion); + } + + /// + /// 使用可更新模式并更新版本资源列表。 + /// + /// 版本资源列表大小。 + /// 版本资源列表哈希值。 + /// 版本资源列表压缩后大小。 + /// 版本资源列表压缩后哈希值。 + /// 版本资源列表更新回调函数集。 + public void UpdateVersionList(int versionListLength, int versionListHashCode, int versionListCompressedLength, int versionListCompressedHashCode, UpdateVersionListCallbacks updateVersionListCallbacks) + { + if (updateVersionListCallbacks == null) + { + throw new GameFrameworkException("Update version list callbacks is invalid."); + } + + if (m_ResourceMode == ResourceMode.Unspecified) + { + throw new GameFrameworkException("You must set resource mode first."); + } + + if (m_ResourceMode != ResourceMode.Updatable && m_ResourceMode != ResourceMode.UpdatableWhilePlaying) + { + throw new GameFrameworkException("You can not use UpdateVersionList without updatable resource mode."); + } + + if (m_VersionListProcessor == null) + { + throw new GameFrameworkException("You can not use UpdateVersionList at this time."); + } + + m_UpdateVersionListCallbacks = updateVersionListCallbacks; + m_VersionListProcessor.UpdateVersionList(versionListLength, versionListHashCode, versionListCompressedLength, versionListCompressedHashCode); + } + + /// + /// 使用可更新模式并校验资源。 + /// + /// 每帧至少校验资源的大小,以字节为单位。 + /// 使用可更新模式并校验资源完成时的回调函数。 + public void VerifyResources(int verifyResourceLengthPerFrame, VerifyResourcesCompleteCallback verifyResourcesCompleteCallback) + { + if (verifyResourcesCompleteCallback == null) + { + throw new GameFrameworkException("Verify resources complete callback is invalid."); + } + + if (m_ResourceMode == ResourceMode.Unspecified) + { + throw new GameFrameworkException("You must set resource mode first."); + } + + if (m_ResourceMode != ResourceMode.Updatable && m_ResourceMode != ResourceMode.UpdatableWhilePlaying) + { + throw new GameFrameworkException("You can not use VerifyResources without updatable resource mode."); + } + + if (m_RefuseSetFlag) + { + throw new GameFrameworkException("You can not verify resources at this time."); + } + + m_ResourceVerifier = new ResourceVerifier(this); + m_ResourceVerifier.ResourceVerifyStart += OnVerifierResourceVerifyStart; + m_ResourceVerifier.ResourceVerifySuccess += OnVerifierResourceVerifySuccess; + m_ResourceVerifier.ResourceVerifyFailure += OnVerifierResourceVerifyFailure; + m_ResourceVerifier.ResourceVerifyComplete += OnVerifierResourceVerifyComplete; + m_VerifyResourcesCompleteCallback = verifyResourcesCompleteCallback; + m_ResourceVerifier.VerifyResources(verifyResourceLengthPerFrame); + } + + /// + /// 使用可更新模式并检查资源。 + /// + /// 是否忽略处理其它变体的资源,若不忽略,将会移除其它变体的资源。 + /// 使用可更新模式并检查资源完成时的回调函数。 + public void CheckResources(bool ignoreOtherVariant, CheckResourcesCompleteCallback checkResourcesCompleteCallback) + { + if (checkResourcesCompleteCallback == null) + { + throw new GameFrameworkException("Check resources complete callback is invalid."); + } + + if (m_ResourceMode == ResourceMode.Unspecified) + { + throw new GameFrameworkException("You must set resource mode first."); + } + + if (m_ResourceMode != ResourceMode.Updatable && m_ResourceMode != ResourceMode.UpdatableWhilePlaying) + { + throw new GameFrameworkException("You can not use CheckResources without updatable resource mode."); + } + + if (m_ResourceChecker == null) + { + throw new GameFrameworkException("You can not use CheckResources at this time."); + } + + m_RefuseSetFlag = true; + m_CheckResourcesCompleteCallback = checkResourcesCompleteCallback; + m_ResourceChecker.CheckResources(m_CurrentVariant, ignoreOtherVariant); + } + + /// + /// 使用可更新模式并应用资源包资源。 + /// + /// 要应用的资源包路径。 + /// 使用可更新模式并应用资源包资源完成时的回调函数。 + public void ApplyResources(string resourcePackPath, ApplyResourcesCompleteCallback applyResourcesCompleteCallback) + { + if (string.IsNullOrEmpty(resourcePackPath)) + { + throw new GameFrameworkException("Resource pack path is invalid."); + } + + if (!File.Exists(resourcePackPath)) + { + throw new GameFrameworkException(Utility.Text.Format("Resource pack '{0}' is not exist.", resourcePackPath)); + } + + if (applyResourcesCompleteCallback == null) + { + throw new GameFrameworkException("Apply resources complete callback is invalid."); + } + + if (m_ResourceMode == ResourceMode.Unspecified) + { + throw new GameFrameworkException("You must set resource mode first."); + } + + if (m_ResourceMode != ResourceMode.Updatable && m_ResourceMode != ResourceMode.UpdatableWhilePlaying) + { + throw new GameFrameworkException("You can not use ApplyResources without updatable resource mode."); + } + + if (m_ResourceUpdater == null) + { + throw new GameFrameworkException("You can not use ApplyResources at this time."); + } + + m_ApplyResourcesCompleteCallback = applyResourcesCompleteCallback; + m_ResourceUpdater.ApplyResources(resourcePackPath); + } + + /// + /// 使用可更新模式并更新所有资源。 + /// + /// 使用可更新模式并更新默认资源组完成时的回调函数。 + public void UpdateResources(UpdateResourcesCompleteCallback updateResourcesCompleteCallback) + { + UpdateResources(string.Empty, updateResourcesCompleteCallback); + } + + /// + /// 使用可更新模式并更新指定资源组的资源。 + /// + /// 要更新的资源组名称。 + /// 使用可更新模式并更新指定资源组完成时的回调函数。 + public void UpdateResources(string resourceGroupName, UpdateResourcesCompleteCallback updateResourcesCompleteCallback) + { + if (updateResourcesCompleteCallback == null) + { + throw new GameFrameworkException("Update resources complete callback is invalid."); + } + + if (m_ResourceMode == ResourceMode.Unspecified) + { + throw new GameFrameworkException("You must set resource mode first."); + } + + if (m_ResourceMode != ResourceMode.Updatable && m_ResourceMode != ResourceMode.UpdatableWhilePlaying) + { + throw new GameFrameworkException("You can not use UpdateResources without updatable resource mode."); + } + + if (m_ResourceUpdater == null) + { + throw new GameFrameworkException("You can not use UpdateResources at this time."); + } + + ResourceGroup resourceGroup = (ResourceGroup)GetResourceGroup(resourceGroupName); + if (resourceGroup == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find resource group '{0}'.", resourceGroupName)); + } + + m_UpdateResourcesCompleteCallback = updateResourcesCompleteCallback; + m_ResourceUpdater.UpdateResources(resourceGroup); + } + + /// + /// 停止更新资源。 + /// + public void StopUpdateResources() + { + if (m_ResourceMode == ResourceMode.Unspecified) + { + throw new GameFrameworkException("You must set resource mode first."); + } + + if (m_ResourceMode != ResourceMode.Updatable && m_ResourceMode != ResourceMode.UpdatableWhilePlaying) + { + throw new GameFrameworkException("You can not use StopUpdateResources without updatable resource mode."); + } + + if (m_ResourceUpdater == null) + { + throw new GameFrameworkException("You can not use StopUpdateResources at this time."); + } + + m_ResourceUpdater.StopUpdateResources(); + m_UpdateResourcesCompleteCallback = null; + } + + /// + /// 校验资源包。 + /// + /// 要校验的资源包路径。 + /// 是否校验资源包成功。 + public bool VerifyResourcePack(string resourcePackPath) + { + if (string.IsNullOrEmpty(resourcePackPath)) + { + throw new GameFrameworkException("Resource pack path is invalid."); + } + + if (!File.Exists(resourcePackPath)) + { + throw new GameFrameworkException(Utility.Text.Format("Resource pack '{0}' is not exist.", resourcePackPath)); + } + + if (m_ResourceMode == ResourceMode.Unspecified) + { + throw new GameFrameworkException("You must set resource mode first."); + } + + if (m_ResourceMode != ResourceMode.Updatable && m_ResourceMode != ResourceMode.UpdatableWhilePlaying) + { + throw new GameFrameworkException("You can not use VerifyResourcePack without updatable resource mode."); + } + + if (m_ResourcePackVersionListSerializer == null) + { + throw new GameFrameworkException("You can not use VerifyResourcePack at this time."); + } + + try + { + long length = 0L; + ResourcePackVersionList versionList = default(ResourcePackVersionList); + using (FileStream fileStream = new FileStream(resourcePackPath, FileMode.Open, FileAccess.Read)) + { + length = fileStream.Length; + versionList = m_ResourcePackVersionListSerializer.Deserialize(fileStream); + } + + if (!versionList.IsValid) + { + return false; + } + + if (versionList.Offset + versionList.Length != length) + { + return false; + } + + int hashCode = 0; + using (FileStream fileStream = new FileStream(resourcePackPath, FileMode.Open, FileAccess.Read)) + { + fileStream.Position = versionList.Offset; + hashCode = Utility.Verifier.GetCrc32(fileStream); + } + + if (versionList.HashCode != hashCode) + { + return false; + } + + return true; + } + catch + { + return false; + } + } + + /// + /// 获取所有加载资源任务的信息。 + /// + /// 所有加载资源任务的信息。 + public TaskInfo[] GetAllLoadAssetInfos() + { + return m_ResourceLoader.GetAllLoadAssetInfos(); + } + + /// + /// 获取所有加载资源任务的信息。 + /// + /// 所有加载资源任务的信息。 + public void GetAllLoadAssetInfos(List results) + { + m_ResourceLoader.GetAllLoadAssetInfos(results); + } + + /// + /// 检查资源是否存在。 + /// + /// 要检查资源的名称。 + /// 检查资源是否存在的结果。 + public HasAssetResult HasAsset(string assetName) + { + if (string.IsNullOrEmpty(assetName)) + { + throw new GameFrameworkException("Asset name is invalid."); + } + + return m_ResourceLoader.HasAsset(assetName); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源回调函数集。 + public void LoadAsset(string assetName, LoadAssetCallbacks loadAssetCallbacks) + { + if (string.IsNullOrEmpty(assetName)) + { + throw new GameFrameworkException("Asset name is invalid."); + } + + if (loadAssetCallbacks == null) + { + throw new GameFrameworkException("Load asset callbacks is invalid."); + } + + m_ResourceLoader.LoadAsset(assetName, null, Constant.DefaultPriority, loadAssetCallbacks, null); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源回调函数集。 + public void LoadAsset(string assetName, Type assetType, LoadAssetCallbacks loadAssetCallbacks) + { + if (string.IsNullOrEmpty(assetName)) + { + throw new GameFrameworkException("Asset name is invalid."); + } + + if (loadAssetCallbacks == null) + { + throw new GameFrameworkException("Load asset callbacks is invalid."); + } + + m_ResourceLoader.LoadAsset(assetName, assetType, Constant.DefaultPriority, loadAssetCallbacks, null); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + public void LoadAsset(string assetName, int priority, LoadAssetCallbacks loadAssetCallbacks) + { + if (string.IsNullOrEmpty(assetName)) + { + throw new GameFrameworkException("Asset name is invalid."); + } + + if (loadAssetCallbacks == null) + { + throw new GameFrameworkException("Load asset callbacks is invalid."); + } + + m_ResourceLoader.LoadAsset(assetName, null, priority, loadAssetCallbacks, null); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + if (string.IsNullOrEmpty(assetName)) + { + throw new GameFrameworkException("Asset name is invalid."); + } + + if (loadAssetCallbacks == null) + { + throw new GameFrameworkException("Load asset callbacks is invalid."); + } + + m_ResourceLoader.LoadAsset(assetName, null, Constant.DefaultPriority, loadAssetCallbacks, userData); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + public void LoadAsset(string assetName, Type assetType, int priority, LoadAssetCallbacks loadAssetCallbacks) + { + if (string.IsNullOrEmpty(assetName)) + { + throw new GameFrameworkException("Asset name is invalid."); + } + + if (loadAssetCallbacks == null) + { + throw new GameFrameworkException("Load asset callbacks is invalid."); + } + + m_ResourceLoader.LoadAsset(assetName, assetType, priority, loadAssetCallbacks, null); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, Type assetType, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + if (string.IsNullOrEmpty(assetName)) + { + throw new GameFrameworkException("Asset name is invalid."); + } + + if (loadAssetCallbacks == null) + { + throw new GameFrameworkException("Load asset callbacks is invalid."); + } + + m_ResourceLoader.LoadAsset(assetName, assetType, Constant.DefaultPriority, loadAssetCallbacks, userData); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, int priority, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + if (string.IsNullOrEmpty(assetName)) + { + throw new GameFrameworkException("Asset name is invalid."); + } + + if (loadAssetCallbacks == null) + { + throw new GameFrameworkException("Load asset callbacks is invalid."); + } + + m_ResourceLoader.LoadAsset(assetName, null, priority, loadAssetCallbacks, userData); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, Type assetType, int priority, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + if (string.IsNullOrEmpty(assetName)) + { + throw new GameFrameworkException("Asset name is invalid."); + } + + if (loadAssetCallbacks == null) + { + throw new GameFrameworkException("Load asset callbacks is invalid."); + } + + m_ResourceLoader.LoadAsset(assetName, assetType, priority, loadAssetCallbacks, userData); + } + + /// + /// 卸载资源。 + /// + /// 要卸载的资源。 + public void UnloadAsset(object asset) + { + if (asset == null) + { + throw new GameFrameworkException("Asset is invalid."); + } + + if (m_ResourceLoader == null) + { + return; + } + + m_ResourceLoader.UnloadAsset(asset); + } + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景回调函数集。 + public void LoadScene(string sceneAssetName, LoadSceneCallbacks loadSceneCallbacks) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + throw new GameFrameworkException("Scene asset name is invalid."); + } + + if (loadSceneCallbacks == null) + { + throw new GameFrameworkException("Load scene callbacks is invalid."); + } + + m_ResourceLoader.LoadScene(sceneAssetName, Constant.DefaultPriority, loadSceneCallbacks, null); + } + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景资源的优先级。 + /// 加载场景回调函数集。 + public void LoadScene(string sceneAssetName, int priority, LoadSceneCallbacks loadSceneCallbacks) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + throw new GameFrameworkException("Scene asset name is invalid."); + } + + if (loadSceneCallbacks == null) + { + throw new GameFrameworkException("Load scene callbacks is invalid."); + } + + m_ResourceLoader.LoadScene(sceneAssetName, priority, loadSceneCallbacks, null); + } + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景回调函数集。 + /// 用户自定义数据。 + public void LoadScene(string sceneAssetName, LoadSceneCallbacks loadSceneCallbacks, object userData) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + throw new GameFrameworkException("Scene asset name is invalid."); + } + + if (loadSceneCallbacks == null) + { + throw new GameFrameworkException("Load scene callbacks is invalid."); + } + + m_ResourceLoader.LoadScene(sceneAssetName, Constant.DefaultPriority, loadSceneCallbacks, userData); + } + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景资源的优先级。 + /// 加载场景回调函数集。 + /// 用户自定义数据。 + public void LoadScene(string sceneAssetName, int priority, LoadSceneCallbacks loadSceneCallbacks, object userData) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + throw new GameFrameworkException("Scene asset name is invalid."); + } + + if (loadSceneCallbacks == null) + { + throw new GameFrameworkException("Load scene callbacks is invalid."); + } + + m_ResourceLoader.LoadScene(sceneAssetName, priority, loadSceneCallbacks, userData); + } + + /// + /// 异步卸载场景。 + /// + /// 要卸载场景资源的名称。 + /// 卸载场景回调函数集。 + public void UnloadScene(string sceneAssetName, UnloadSceneCallbacks unloadSceneCallbacks) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + throw new GameFrameworkException("Scene asset name is invalid."); + } + + if (unloadSceneCallbacks == null) + { + throw new GameFrameworkException("Unload scene callbacks is invalid."); + } + + m_ResourceLoader.UnloadScene(sceneAssetName, unloadSceneCallbacks, null); + } + + /// + /// 异步卸载场景。 + /// + /// 要卸载场景资源的名称。 + /// 卸载场景回调函数集。 + /// 用户自定义数据。 + public void UnloadScene(string sceneAssetName, UnloadSceneCallbacks unloadSceneCallbacks, object userData) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + throw new GameFrameworkException("Scene asset name is invalid."); + } + + if (unloadSceneCallbacks == null) + { + throw new GameFrameworkException("Unload scene callbacks is invalid."); + } + + m_ResourceLoader.UnloadScene(sceneAssetName, unloadSceneCallbacks, userData); + } + + /// + /// 获取二进制资源的实际路径。 + /// + /// 要获取实际路径的二进制资源的名称。 + /// 二进制资源的实际路径。 + /// 此方法仅适用于二进制资源存储在磁盘(而非文件系统)中的情况。若二进制资源存储在文件系统中时,返回值将始终为空。 + public string GetBinaryPath(string binaryAssetName) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + return m_ResourceLoader.GetBinaryPath(binaryAssetName); + } + + /// + /// 获取二进制资源的实际路径。 + /// + /// 要获取实际路径的二进制资源的名称。 + /// 二进制资源是否存储在只读区中。 + /// 二进制资源是否存储在文件系统中。 + /// 二进制资源或存储二进制资源的文件系统,相对于只读区或者读写区的相对路径。 + /// 若二进制资源存储在文件系统中,则指示二进制资源在文件系统中的名称,否则此参数返回空。 + /// 是否获取二进制资源的实际路径成功。 + public bool GetBinaryPath(string binaryAssetName, out bool storageInReadOnly, out bool storageInFileSystem, out string relativePath, out string fileName) + { + return m_ResourceLoader.GetBinaryPath(binaryAssetName, out storageInReadOnly, out storageInFileSystem, out relativePath, out fileName); + } + + /// + /// 获取二进制资源的长度。 + /// + /// 要获取长度的二进制资源的名称。 + /// 二进制资源的长度。 + public int GetBinaryLength(string binaryAssetName) + { + return m_ResourceLoader.GetBinaryLength(binaryAssetName); + } + + /// + /// 异步加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 加载二进制资源回调函数集。 + public void LoadBinary(string binaryAssetName, LoadBinaryCallbacks loadBinaryCallbacks) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + if (loadBinaryCallbacks == null) + { + throw new GameFrameworkException("Load binary callbacks is invalid."); + } + + m_ResourceLoader.LoadBinary(binaryAssetName, loadBinaryCallbacks, null); + } + + /// + /// 异步加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 加载二进制资源回调函数集。 + /// 用户自定义数据。 + public void LoadBinary(string binaryAssetName, LoadBinaryCallbacks loadBinaryCallbacks, object userData) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + if (loadBinaryCallbacks == null) + { + throw new GameFrameworkException("Load binary callbacks is invalid."); + } + + m_ResourceLoader.LoadBinary(binaryAssetName, loadBinaryCallbacks, userData); + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + public byte[] LoadBinaryFromFileSystem(string binaryAssetName) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + return m_ResourceLoader.LoadBinaryFromFileSystem(binaryAssetName); + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 实际加载了多少字节。 + public int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return m_ResourceLoader.LoadBinaryFromFileSystem(binaryAssetName, buffer, 0, buffer.Length); + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 存储加载二进制资源的二进制流的起始位置。 + /// 实际加载了多少字节。 + public int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return m_ResourceLoader.LoadBinaryFromFileSystem(binaryAssetName, buffer, startIndex, buffer.Length - startIndex); + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 存储加载二进制资源的二进制流的起始位置。 + /// 存储加载二进制资源的二进制流的长度。 + /// 实际加载了多少字节。 + public int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex, int length) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return m_ResourceLoader.LoadBinaryFromFileSystem(binaryAssetName, buffer, startIndex, length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的长度。 + /// 存储加载二进制资源片段内容的二进制流。 + public byte[] LoadBinarySegmentFromFileSystem(string binaryAssetName, int length) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + return m_ResourceLoader.LoadBinarySegmentFromFileSystem(binaryAssetName, 0, length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 要加载片段的长度。 + /// 存储加载二进制资源片段内容的二进制流。 + public byte[] LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, int length) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + return m_ResourceLoader.LoadBinarySegmentFromFileSystem(binaryAssetName, offset, length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, byte[] buffer) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return m_ResourceLoader.LoadBinarySegmentFromFileSystem(binaryAssetName, 0, buffer, 0, buffer.Length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, byte[] buffer, int length) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return m_ResourceLoader.LoadBinarySegmentFromFileSystem(binaryAssetName, 0, buffer, 0, length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 存储加载二进制资源片段内容的二进制流的起始位置。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex, int length) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return m_ResourceLoader.LoadBinarySegmentFromFileSystem(binaryAssetName, 0, buffer, startIndex, length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return m_ResourceLoader.LoadBinarySegmentFromFileSystem(binaryAssetName, offset, buffer, 0, buffer.Length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer, int length) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return m_ResourceLoader.LoadBinarySegmentFromFileSystem(binaryAssetName, offset, buffer, 0, length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 存储加载二进制资源片段内容的二进制流的起始位置。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer, int startIndex, int length) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + throw new GameFrameworkException("Binary asset name is invalid."); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + return m_ResourceLoader.LoadBinarySegmentFromFileSystem(binaryAssetName, offset, buffer, startIndex, length); + } + + /// + /// 检查资源组是否存在。 + /// + /// 要检查资源组的名称。 + /// 资源组是否存在。 + public bool HasResourceGroup(string resourceGroupName) + { + return m_ResourceGroups.ContainsKey(resourceGroupName ?? string.Empty); + } + + /// + /// 获取默认资源组。 + /// + /// 默认资源组。 + public IResourceGroup GetResourceGroup() + { + return GetResourceGroup(string.Empty); + } + + /// + /// 获取资源组。 + /// + /// 要获取的资源组名称。 + /// 要获取的资源组。 + public IResourceGroup GetResourceGroup(string resourceGroupName) + { + ResourceGroup resourceGroup = null; + if (m_ResourceGroups.TryGetValue(resourceGroupName ?? string.Empty, out resourceGroup)) + { + return resourceGroup; + } + + return null; + } + + /// + /// 获取所有资源组。 + /// + /// 所有资源组。 + public IResourceGroup[] GetAllResourceGroups() + { + int index = 0; + IResourceGroup[] results = new IResourceGroup[m_ResourceGroups.Count]; + foreach (KeyValuePair resourceGroup in m_ResourceGroups) + { + results[index++] = resourceGroup.Value; + } + + return results; + } + + /// + /// 获取所有资源组。 + /// + /// 所有资源组。 + public void GetAllResourceGroups(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair resourceGroup in m_ResourceGroups) + { + results.Add(resourceGroup.Value); + } + } + + /// + /// 获取资源组集合。 + /// + /// 要获取的资源组名称的集合。 + /// 要获取的资源组集合。 + public IResourceGroupCollection GetResourceGroupCollection(params string[] resourceGroupNames) + { + if (resourceGroupNames == null || resourceGroupNames.Length < 1) + { + throw new GameFrameworkException("Resource group names is invalid."); + } + + ResourceGroup[] resourceGroups = new ResourceGroup[resourceGroupNames.Length]; + for (int i = 0; i < resourceGroupNames.Length; i++) + { + if (string.IsNullOrEmpty(resourceGroupNames[i])) + { + throw new GameFrameworkException("Resource group name is invalid."); + } + + resourceGroups[i] = (ResourceGroup)GetResourceGroup(resourceGroupNames[i]); + if (resourceGroups[i] == null) + { + throw new GameFrameworkException(Utility.Text.Format("Resource group '{0}' is not exist.", resourceGroupNames[i])); + } + } + + return new ResourceGroupCollection(resourceGroups, m_ResourceInfos); + } + + /// + /// 获取资源组集合。 + /// + /// 要获取的资源组名称的集合。 + /// 要获取的资源组集合。 + public IResourceGroupCollection GetResourceGroupCollection(List resourceGroupNames) + { + if (resourceGroupNames == null || resourceGroupNames.Count < 1) + { + throw new GameFrameworkException("Resource group names is invalid."); + } + + ResourceGroup[] resourceGroups = new ResourceGroup[resourceGroupNames.Count]; + for (int i = 0; i < resourceGroupNames.Count; i++) + { + if (string.IsNullOrEmpty(resourceGroupNames[i])) + { + throw new GameFrameworkException("Resource group name is invalid."); + } + + resourceGroups[i] = (ResourceGroup)GetResourceGroup(resourceGroupNames[i]); + if (resourceGroups[i] == null) + { + throw new GameFrameworkException(Utility.Text.Format("Resource group '{0}' is not exist.", resourceGroupNames[i])); + } + } + + return new ResourceGroupCollection(resourceGroups, m_ResourceInfos); + } + + private void UpdateResource(ResourceName resourceName) + { + m_ResourceUpdater.UpdateResource(resourceName); + } + + private ResourceGroup GetOrAddResourceGroup(string resourceGroupName) + { + if (resourceGroupName == null) + { + resourceGroupName = string.Empty; + } + + ResourceGroup resourceGroup = null; + if (!m_ResourceGroups.TryGetValue(resourceGroupName, out resourceGroup)) + { + resourceGroup = new ResourceGroup(resourceGroupName, m_ResourceInfos); + m_ResourceGroups.Add(resourceGroupName, resourceGroup); + } + + return resourceGroup; + } + + private AssetInfo GetAssetInfo(string assetName) + { + if (string.IsNullOrEmpty(assetName)) + { + throw new GameFrameworkException("Asset name is invalid."); + } + + if (m_AssetInfos == null) + { + return null; + } + + AssetInfo assetInfo = null; + if (m_AssetInfos.TryGetValue(assetName, out assetInfo)) + { + return assetInfo; + } + + return null; + } + + private ResourceInfo GetResourceInfo(ResourceName resourceName) + { + if (m_ResourceInfos == null) + { + return null; + } + + ResourceInfo resourceInfo = null; + if (m_ResourceInfos.TryGetValue(resourceName, out resourceInfo)) + { + return resourceInfo; + } + + return null; + } + + private IFileSystem GetFileSystem(string fileSystemName, bool storageInReadOnly) + { + if (string.IsNullOrEmpty(fileSystemName)) + { + throw new GameFrameworkException("File system name is invalid."); + } + + IFileSystem fileSystem = null; + if (storageInReadOnly) + { + if (!m_ReadOnlyFileSystems.TryGetValue(fileSystemName, out fileSystem)) + { + string fullPath = Utility.Path.GetRegularPath(Path.Combine(m_ReadOnlyPath, Utility.Text.Format("{0}.{1}", fileSystemName, DefaultExtension))); + fileSystem = m_FileSystemManager.GetFileSystem(fullPath); + if (fileSystem == null) + { + fileSystem = m_FileSystemManager.LoadFileSystem(fullPath, FileSystemAccess.Read); + m_ReadOnlyFileSystems.Add(fileSystemName, fileSystem); + } + } + } + else + { + if (!m_ReadWriteFileSystems.TryGetValue(fileSystemName, out fileSystem)) + { + string fullPath = Utility.Path.GetRegularPath(Path.Combine(m_ReadWritePath, Utility.Text.Format("{0}.{1}", fileSystemName, DefaultExtension))); + fileSystem = m_FileSystemManager.GetFileSystem(fullPath); + if (fileSystem == null) + { + if (File.Exists(fullPath)) + { + fileSystem = m_FileSystemManager.LoadFileSystem(fullPath, FileSystemAccess.ReadWrite); + } + else + { + string directory = Path.GetDirectoryName(fullPath); + if (!Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + fileSystem = m_FileSystemManager.CreateFileSystem(fullPath, FileSystemAccess.ReadWrite, FileSystemMaxFileCount, FileSystemMaxBlockCount); + } + + m_ReadWriteFileSystems.Add(fileSystemName, fileSystem); + } + } + } + + return fileSystem; + } + + private void PrepareCachedStream() + { + if (m_CachedStream == null) + { + m_CachedStream = new MemoryStream(); + } + + m_CachedStream.Position = 0L; + m_CachedStream.SetLength(0L); + } + + private void FreeCachedStream() + { + if (m_CachedStream != null) + { + m_CachedStream.Dispose(); + m_CachedStream = null; + } + } + + private void OnIniterResourceInitComplete() + { + m_ResourceIniter.ResourceInitComplete -= OnIniterResourceInitComplete; + m_ResourceIniter.Shutdown(); + m_ResourceIniter = null; + + m_InitResourcesCompleteCallback(); + m_InitResourcesCompleteCallback = null; + } + + private void OnVersionListProcessorUpdateSuccess(string downloadPath, string downloadUri) + { + m_UpdateVersionListCallbacks.UpdateVersionListSuccessCallback(downloadPath, downloadUri); + } + + private void OnVersionListProcessorUpdateFailure(string downloadUri, string errorMessage) + { + if (m_UpdateVersionListCallbacks.UpdateVersionListFailureCallback != null) + { + m_UpdateVersionListCallbacks.UpdateVersionListFailureCallback(downloadUri, errorMessage); + } + } + + private void OnVerifierResourceVerifyStart(int count, long totalLength) + { + if (m_ResourceVerifyStartEventHandler != null) + { + ResourceVerifyStartEventArgs resourceVerifyStartEventArgs = ResourceVerifyStartEventArgs.Create(count, totalLength); + m_ResourceVerifyStartEventHandler(this, resourceVerifyStartEventArgs); + ReferencePool.Release(resourceVerifyStartEventArgs); + } + } + + private void OnVerifierResourceVerifySuccess(ResourceName resourceName, int length) + { + if (m_ResourceVerifySuccessEventHandler != null) + { + ResourceVerifySuccessEventArgs resourceVerifySuccessEventArgs = ResourceVerifySuccessEventArgs.Create(resourceName.FullName, length); + m_ResourceVerifySuccessEventHandler(this, resourceVerifySuccessEventArgs); + ReferencePool.Release(resourceVerifySuccessEventArgs); + } + } + + private void OnVerifierResourceVerifyFailure(ResourceName resourceName) + { + if (m_ResourceVerifyFailureEventHandler != null) + { + ResourceVerifyFailureEventArgs resourceVerifyFailureEventArgs = ResourceVerifyFailureEventArgs.Create(resourceName.FullName); + m_ResourceVerifyFailureEventHandler(this, resourceVerifyFailureEventArgs); + ReferencePool.Release(resourceVerifyFailureEventArgs); + } + } + + private void OnVerifierResourceVerifyComplete(bool result) + { + m_VerifyResourcesCompleteCallback(result); + m_ResourceVerifier.ResourceVerifyStart -= OnVerifierResourceVerifyStart; + m_ResourceVerifier.ResourceVerifySuccess -= OnVerifierResourceVerifySuccess; + m_ResourceVerifier.ResourceVerifyFailure -= OnVerifierResourceVerifyFailure; + m_ResourceVerifier.ResourceVerifyComplete -= OnVerifierResourceVerifyComplete; + m_ResourceVerifier.Shutdown(); + m_ResourceVerifier = null; + } + + private void OnCheckerResourceNeedUpdate(ResourceName resourceName, string fileSystemName, LoadType loadType, int length, int hashCode, int compressedLength, int compressedHashCode) + { + m_ResourceUpdater.AddResourceUpdate(resourceName, fileSystemName, loadType, length, hashCode, compressedLength, compressedHashCode, Utility.Path.GetRegularPath(Path.Combine(m_ReadWritePath, resourceName.FullName))); + } + + private void OnCheckerResourceCheckComplete(int movedCount, int removedCount, int updateCount, long updateTotalLength, long updateTotalCompressedLength) + { + m_VersionListProcessor.VersionListUpdateSuccess -= OnVersionListProcessorUpdateSuccess; + m_VersionListProcessor.VersionListUpdateFailure -= OnVersionListProcessorUpdateFailure; + m_VersionListProcessor.Shutdown(); + m_VersionListProcessor = null; + m_UpdateVersionListCallbacks = null; + + m_ResourceChecker.ResourceNeedUpdate -= OnCheckerResourceNeedUpdate; + m_ResourceChecker.ResourceCheckComplete -= OnCheckerResourceCheckComplete; + m_ResourceChecker.Shutdown(); + m_ResourceChecker = null; + + m_ResourceUpdater.CheckResourceComplete(movedCount > 0 || removedCount > 0); + + if (updateCount <= 0) + { + m_ResourceUpdater.ResourceApplyStart -= OnUpdaterResourceApplyStart; + m_ResourceUpdater.ResourceApplySuccess -= OnUpdaterResourceApplySuccess; + m_ResourceUpdater.ResourceApplyFailure -= OnUpdaterResourceApplyFailure; + m_ResourceUpdater.ResourceApplyComplete -= OnUpdaterResourceApplyComplete; + m_ResourceUpdater.ResourceUpdateStart -= OnUpdaterResourceUpdateStart; + m_ResourceUpdater.ResourceUpdateChanged -= OnUpdaterResourceUpdateChanged; + m_ResourceUpdater.ResourceUpdateSuccess -= OnUpdaterResourceUpdateSuccess; + m_ResourceUpdater.ResourceUpdateFailure -= OnUpdaterResourceUpdateFailure; + m_ResourceUpdater.ResourceUpdateComplete -= OnUpdaterResourceUpdateComplete; + m_ResourceUpdater.ResourceUpdateAllComplete -= OnUpdaterResourceUpdateAllComplete; + m_ResourceUpdater.Shutdown(); + m_ResourceUpdater = null; + + m_ReadWriteResourceInfos.Clear(); + m_ReadWriteResourceInfos = null; + + FreeCachedStream(); + } + + m_CheckResourcesCompleteCallback(movedCount, removedCount, updateCount, updateTotalLength, updateTotalCompressedLength); + m_CheckResourcesCompleteCallback = null; + } + + private void OnUpdaterResourceApplyStart(string resourcePackPath, int count, long totalLength) + { + if (m_ResourceApplyStartEventHandler != null) + { + ResourceApplyStartEventArgs resourceApplyStartEventArgs = ResourceApplyStartEventArgs.Create(resourcePackPath, count, totalLength); + m_ResourceApplyStartEventHandler(this, resourceApplyStartEventArgs); + ReferencePool.Release(resourceApplyStartEventArgs); + } + } + + private void OnUpdaterResourceApplySuccess(ResourceName resourceName, string applyPath, string resourcePackPath, int length, int compressedLength) + { + if (m_ResourceApplySuccessEventHandler != null) + { + ResourceApplySuccessEventArgs resourceApplySuccessEventArgs = ResourceApplySuccessEventArgs.Create(resourceName.FullName, applyPath, resourcePackPath, length, compressedLength); + m_ResourceApplySuccessEventHandler(this, resourceApplySuccessEventArgs); + ReferencePool.Release(resourceApplySuccessEventArgs); + } + } + + private void OnUpdaterResourceApplyFailure(ResourceName resourceName, string resourcePackPath, string errorMessage) + { + if (m_ResourceApplyFailureEventHandler != null) + { + ResourceApplyFailureEventArgs resourceApplyFailureEventArgs = ResourceApplyFailureEventArgs.Create(resourceName.FullName, resourcePackPath, errorMessage); + m_ResourceApplyFailureEventHandler(this, resourceApplyFailureEventArgs); + ReferencePool.Release(resourceApplyFailureEventArgs); + } + } + + private void OnUpdaterResourceApplyComplete(string resourcePackPath, bool result) + { + ApplyResourcesCompleteCallback applyResourcesCompleteCallback = m_ApplyResourcesCompleteCallback; + m_ApplyResourcesCompleteCallback = null; + applyResourcesCompleteCallback(resourcePackPath, result); + } + + private void OnUpdaterResourceUpdateStart(ResourceName resourceName, string downloadPath, string downloadUri, int currentLength, int compressedLength, int retryCount) + { + if (m_ResourceUpdateStartEventHandler != null) + { + ResourceUpdateStartEventArgs resourceUpdateStartEventArgs = ResourceUpdateStartEventArgs.Create(resourceName.FullName, downloadPath, downloadUri, currentLength, compressedLength, retryCount); + m_ResourceUpdateStartEventHandler(this, resourceUpdateStartEventArgs); + ReferencePool.Release(resourceUpdateStartEventArgs); + } + } + + private void OnUpdaterResourceUpdateChanged(ResourceName resourceName, string downloadPath, string downloadUri, int currentLength, int compressedLength) + { + if (m_ResourceUpdateChangedEventHandler != null) + { + ResourceUpdateChangedEventArgs resourceUpdateChangedEventArgs = ResourceUpdateChangedEventArgs.Create(resourceName.FullName, downloadPath, downloadUri, currentLength, compressedLength); + m_ResourceUpdateChangedEventHandler(this, resourceUpdateChangedEventArgs); + ReferencePool.Release(resourceUpdateChangedEventArgs); + } + } + + private void OnUpdaterResourceUpdateSuccess(ResourceName resourceName, string downloadPath, string downloadUri, int length, int compressedLength) + { + if (m_ResourceUpdateSuccessEventHandler != null) + { + ResourceUpdateSuccessEventArgs resourceUpdateSuccessEventArgs = ResourceUpdateSuccessEventArgs.Create(resourceName.FullName, downloadPath, downloadUri, length, compressedLength); + m_ResourceUpdateSuccessEventHandler(this, resourceUpdateSuccessEventArgs); + ReferencePool.Release(resourceUpdateSuccessEventArgs); + } + } + + private void OnUpdaterResourceUpdateFailure(ResourceName resourceName, string downloadUri, int retryCount, int totalRetryCount, string errorMessage) + { + if (m_ResourceUpdateFailureEventHandler != null) + { + ResourceUpdateFailureEventArgs resourceUpdateFailureEventArgs = ResourceUpdateFailureEventArgs.Create(resourceName.FullName, downloadUri, retryCount, totalRetryCount, errorMessage); + m_ResourceUpdateFailureEventHandler(this, resourceUpdateFailureEventArgs); + ReferencePool.Release(resourceUpdateFailureEventArgs); + } + } + + private void OnUpdaterResourceUpdateComplete(ResourceGroup resourceGroup, bool result) + { + Utility.Path.RemoveEmptyDirectory(m_ReadWritePath); + UpdateResourcesCompleteCallback updateResourcesCompleteCallback = m_UpdateResourcesCompleteCallback; + m_UpdateResourcesCompleteCallback = null; + updateResourcesCompleteCallback(resourceGroup, result); + } + + private void OnUpdaterResourceUpdateAllComplete() + { + m_ResourceUpdater.ResourceApplyStart -= OnUpdaterResourceApplyStart; + m_ResourceUpdater.ResourceApplySuccess -= OnUpdaterResourceApplySuccess; + m_ResourceUpdater.ResourceApplyFailure -= OnUpdaterResourceApplyFailure; + m_ResourceUpdater.ResourceApplyComplete -= OnUpdaterResourceApplyComplete; + m_ResourceUpdater.ResourceUpdateStart -= OnUpdaterResourceUpdateStart; + m_ResourceUpdater.ResourceUpdateChanged -= OnUpdaterResourceUpdateChanged; + m_ResourceUpdater.ResourceUpdateSuccess -= OnUpdaterResourceUpdateSuccess; + m_ResourceUpdater.ResourceUpdateFailure -= OnUpdaterResourceUpdateFailure; + m_ResourceUpdater.ResourceUpdateComplete -= OnUpdaterResourceUpdateComplete; + m_ResourceUpdater.ResourceUpdateAllComplete -= OnUpdaterResourceUpdateAllComplete; + m_ResourceUpdater.Shutdown(); + m_ResourceUpdater = null; + + m_ReadWriteResourceInfos.Clear(); + m_ReadWriteResourceInfos = null; + + FreeCachedStream(); + Utility.Path.RemoveEmptyDirectory(m_ReadWritePath); + + if (m_ResourceUpdateAllCompleteEventHandler != null) + { + ResourceUpdateAllCompleteEventArgs resourceUpdateAllCompleteEventArgs = ResourceUpdateAllCompleteEventArgs.Create(); + m_ResourceUpdateAllCompleteEventHandler(this, resourceUpdateAllCompleteEventArgs); + ReferencePool.Release(resourceUpdateAllCompleteEventArgs); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.cs.meta new file mode 100644 index 0000000..87431e3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9a6bdb3e805060d4fa081fbb5f510adb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceMode.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceMode.cs new file mode 100644 index 0000000..5499382 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceMode.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源模式。 + /// + public enum ResourceMode : byte + { + /// + /// 未指定。 + /// + Unspecified = 0, + + /// + /// 单机模式。 + /// + Package, + + /// + /// 预下载的可更新模式。 + /// + Updatable, + + /// + /// 使用时下载的可更新模式。 + /// + UpdatableWhilePlaying + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceMode.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceMode.cs.meta new file mode 100644 index 0000000..c73155f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 302553b9c2d30284f80ab533caa2354f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionList.Resource.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionList.Resource.cs new file mode 100644 index 0000000..ca09125 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionList.Resource.cs @@ -0,0 +1,160 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + public partial struct ResourcePackVersionList + { + /// + /// 资源。 + /// + [StructLayout(LayoutKind.Auto)] + public struct Resource + { + private readonly string m_Name; + private readonly string m_Variant; + private readonly string m_Extension; + private readonly byte m_LoadType; + private readonly long m_Offset; + private readonly int m_Length; + private readonly int m_HashCode; + private readonly int m_CompressedLength; + private readonly int m_CompressedHashCode; + + /// + /// 初始化资源的新实例。 + /// + /// 资源名称。 + /// 资源变体名称。 + /// 资源扩展名称。 + /// 资源加载方式。 + /// 资源偏移。 + /// 资源长度。 + /// 资源哈希值。 + /// 资源压缩后长度。 + /// 资源压缩后哈希值。 + public Resource(string name, string variant, string extension, byte loadType, long offset, int length, int hashCode, int compressedLength, int compressedHashCode) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + m_Name = name; + m_Variant = variant; + m_Extension = extension; + m_LoadType = loadType; + m_Offset = offset; + m_Length = length; + m_HashCode = hashCode; + m_CompressedLength = compressedLength; + m_CompressedHashCode = compressedHashCode; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取资源变体名称。 + /// + public string Variant + { + get + { + return m_Variant; + } + } + + /// + /// 获取资源扩展名称。 + /// + public string Extension + { + get + { + return m_Extension; + } + } + + /// + /// 获取资源加载方式。 + /// + public byte LoadType + { + get + { + return m_LoadType; + } + } + + /// + /// 获取资源偏移。 + /// + public long Offset + { + get + { + return m_Offset; + } + } + + /// + /// 获取资源长度。 + /// + public int Length + { + get + { + return m_Length; + } + } + + /// + /// 获取资源哈希值。 + /// + public int HashCode + { + get + { + return m_HashCode; + } + } + + /// + /// 获取资源压缩后长度。 + /// + public int CompressedLength + { + get + { + return m_CompressedLength; + } + } + + /// + /// 获取资源压缩后哈希值。 + /// + public int CompressedHashCode + { + get + { + return m_CompressedHashCode; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionList.Resource.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionList.Resource.cs.meta new file mode 100644 index 0000000..8b5915e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionList.Resource.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b540dcc246e54364ca91c734bb3e3eed +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionList.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionList.cs new file mode 100644 index 0000000..ef89148 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionList.cs @@ -0,0 +1,115 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + /// + /// 资源包版本资源列表。 + /// + [StructLayout(LayoutKind.Auto)] + public partial struct ResourcePackVersionList + { + private static readonly Resource[] EmptyResourceArray = new Resource[] { }; + + private readonly bool m_IsValid; + private readonly int m_Offset; + private readonly long m_Length; + private readonly int m_HashCode; + private readonly Resource[] m_Resources; + + /// + /// 初始化资源包版本资源列表的新实例。 + /// + /// 资源数据偏移。 + /// 资源数据长度。 + /// 资源数据哈希值。 + /// 包含的资源集合。 + public ResourcePackVersionList(int offset, long length, int hashCode, Resource[] resources) + { + m_IsValid = true; + m_Offset = offset; + m_Length = length; + m_HashCode = hashCode; + m_Resources = resources ?? EmptyResourceArray; + } + + /// + /// 获取资源包版本资源列表是否有效。 + /// + public bool IsValid + { + get + { + return m_IsValid; + } + } + + /// + /// 获取资源数据偏移。 + /// + public int Offset + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_Offset; + } + } + + /// + /// 获取资源数据长度。 + /// + public long Length + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_Length; + } + } + + /// + /// 获取资源数据哈希值。 + /// + public int HashCode + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_HashCode; + } + } + + /// + /// 获取包含的资源集合。 + /// + /// 包含的资源集合。 + public Resource[] GetResources() + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_Resources; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionList.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionList.cs.meta new file mode 100644 index 0000000..332a0ad --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f5f11c3d85778c24ca7f095f197c804a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionListSerializer.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionListSerializer.cs new file mode 100644 index 0000000..539b8d7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionListSerializer.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源包版本资源列表序列化器。 + /// + public sealed class ResourcePackVersionListSerializer : GameFrameworkSerializer + { + private static readonly byte[] Header = new byte[] { (byte)'G', (byte)'F', (byte)'K' }; + + /// + /// 初始化资源包版本资源列表序列化器的新实例。 + /// + public ResourcePackVersionListSerializer() + { + } + + /// + /// 获取资源包版本资源列表头标识。 + /// + /// 资源包版本资源列表头标识。 + protected override byte[] GetHeader() + { + return Header; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionListSerializer.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionListSerializer.cs.meta new file mode 100644 index 0000000..9e749e4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourcePackVersionListSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cbe6806a0d53dd34a956efa339af1931 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateAllCompleteEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateAllCompleteEventArgs.cs new file mode 100644 index 0000000..1be8522 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateAllCompleteEventArgs.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源更新全部完成事件。 + /// + public sealed class ResourceUpdateAllCompleteEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化资源更新全部完成事件的新实例。 + /// + public ResourceUpdateAllCompleteEventArgs() + { + } + + /// + /// 创建资源更新全部完成事件。 + /// + /// 创建的资源更新全部完成事件。 + public static ResourceUpdateAllCompleteEventArgs Create() + { + return ReferencePool.Acquire(); + } + + /// + /// 清理资源更新全部完成事件。 + /// + public override void Clear() + { + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateAllCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateAllCompleteEventArgs.cs.meta new file mode 100644 index 0000000..ad52bff --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateAllCompleteEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a2cca8bba99d79a4e994a852a63e48b0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateChangedEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateChangedEventArgs.cs new file mode 100644 index 0000000..4c99008 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateChangedEventArgs.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源更新改变事件。 + /// + public sealed class ResourceUpdateChangedEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化资源更新改变事件的新实例。 + /// + public ResourceUpdateChangedEventArgs() + { + Name = null; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0; + CompressedLength = 0; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取资源下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取当前下载大小。 + /// + public int CurrentLength + { + get; + private set; + } + + /// + /// 获取压缩后大小。 + /// + public int CompressedLength + { + get; + private set; + } + + /// + /// 创建资源更新改变事件。 + /// + /// 资源名称。 + /// 资源下载后存放路径。 + /// 资源下载地址。 + /// 当前下载大小。 + /// 压缩后大小。 + /// 创建的资源更新改变事件。 + public static ResourceUpdateChangedEventArgs Create(string name, string downloadPath, string downloadUri, int currentLength, int compressedLength) + { + ResourceUpdateChangedEventArgs resourceUpdateChangedEventArgs = ReferencePool.Acquire(); + resourceUpdateChangedEventArgs.Name = name; + resourceUpdateChangedEventArgs.DownloadPath = downloadPath; + resourceUpdateChangedEventArgs.DownloadUri = downloadUri; + resourceUpdateChangedEventArgs.CurrentLength = currentLength; + resourceUpdateChangedEventArgs.CompressedLength = compressedLength; + return resourceUpdateChangedEventArgs; + } + + /// + /// 清理资源更新改变事件。 + /// + public override void Clear() + { + Name = null; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0; + CompressedLength = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateChangedEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateChangedEventArgs.cs.meta new file mode 100644 index 0000000..621bb33 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateChangedEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3069a06720a3f464e90175c56c912adc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateFailureEventArgs.cs new file mode 100644 index 0000000..544e884 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateFailureEventArgs.cs @@ -0,0 +1,105 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源更新失败事件。 + /// + public sealed class ResourceUpdateFailureEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化资源更新失败事件的新实例。 + /// + public ResourceUpdateFailureEventArgs() + { + Name = null; + DownloadUri = null; + RetryCount = 0; + TotalRetryCount = 0; + ErrorMessage = null; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取已重试次数。 + /// + public int RetryCount + { + get; + private set; + } + + /// + /// 获取设定的重试次数。 + /// + public int TotalRetryCount + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 创建资源更新失败事件。 + /// + /// 资源名称。 + /// 下载地址。 + /// 已重试次数。 + /// 设定的重试次数。 + /// 错误信息。 + /// 创建的资源更新失败事件。 + /// 当已重试次数达到设定的重试次数时,将不再重试。 + public static ResourceUpdateFailureEventArgs Create(string name, string downloadUri, int retryCount, int totalRetryCount, string errorMessage) + { + ResourceUpdateFailureEventArgs resourceUpdateFailureEventArgs = ReferencePool.Acquire(); + resourceUpdateFailureEventArgs.Name = name; + resourceUpdateFailureEventArgs.DownloadUri = downloadUri; + resourceUpdateFailureEventArgs.RetryCount = retryCount; + resourceUpdateFailureEventArgs.TotalRetryCount = totalRetryCount; + resourceUpdateFailureEventArgs.ErrorMessage = errorMessage; + return resourceUpdateFailureEventArgs; + } + + /// + /// 清理资源更新失败事件。 + /// + public override void Clear() + { + Name = null; + DownloadUri = null; + RetryCount = 0; + TotalRetryCount = 0; + ErrorMessage = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateFailureEventArgs.cs.meta new file mode 100644 index 0000000..20a94fd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d748e11461c165340ba74d170e41b35e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateStartEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateStartEventArgs.cs new file mode 100644 index 0000000..0f4d9ae --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateStartEventArgs.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源更新开始事件。 + /// + public sealed class ResourceUpdateStartEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化资源更新开始事件的新实例。 + /// + public ResourceUpdateStartEventArgs() + { + Name = null; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0; + CompressedLength = 0; + RetryCount = 0; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取资源下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取当前下载大小。 + /// + public int CurrentLength + { + get; + private set; + } + + /// + /// 获取压缩后大小。 + /// + public int CompressedLength + { + get; + private set; + } + + /// + /// 获取已重试下载次数。 + /// + public int RetryCount + { + get; + private set; + } + + /// + /// 创建资源更新开始事件。 + /// + /// 资源名称。 + /// 资源下载后存放路径。 + /// 资源下载地址。 + /// 当前下载大小。 + /// 压缩后大小。 + /// 已重试下载次数。 + /// 创建的资源更新开始事件。 + public static ResourceUpdateStartEventArgs Create(string name, string downloadPath, string downloadUri, int currentLength, int compressedLength, int retryCount) + { + ResourceUpdateStartEventArgs resourceUpdateStartEventArgs = ReferencePool.Acquire(); + resourceUpdateStartEventArgs.Name = name; + resourceUpdateStartEventArgs.DownloadPath = downloadPath; + resourceUpdateStartEventArgs.DownloadUri = downloadUri; + resourceUpdateStartEventArgs.CurrentLength = currentLength; + resourceUpdateStartEventArgs.CompressedLength = compressedLength; + resourceUpdateStartEventArgs.RetryCount = retryCount; + return resourceUpdateStartEventArgs; + } + + /// + /// 清理资源更新开始事件。 + /// + public override void Clear() + { + Name = null; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0; + CompressedLength = 0; + RetryCount = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateStartEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateStartEventArgs.cs.meta new file mode 100644 index 0000000..25c38e3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateStartEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3f2893c8378bc574c838de164dcdaab8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateSuccessEventArgs.cs new file mode 100644 index 0000000..3894a5c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateSuccessEventArgs.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源更新成功事件。 + /// + public sealed class ResourceUpdateSuccessEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化资源更新成功事件的新实例。 + /// + public ResourceUpdateSuccessEventArgs() + { + Name = null; + DownloadPath = null; + DownloadUri = null; + Length = 0; + CompressedLength = 0; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取资源下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取资源大小。 + /// + public int Length + { + get; + private set; + } + + /// + /// 获取压缩后大小。 + /// + public int CompressedLength + { + get; + private set; + } + + /// + /// 创建资源更新成功事件。 + /// + /// 资源名称。 + /// 资源下载后存放路径。 + /// 资源下载地址。 + /// 资源大小。 + /// 压缩后大小。 + /// 创建的资源更新成功事件。 + public static ResourceUpdateSuccessEventArgs Create(string name, string downloadPath, string downloadUri, int length, int compressedLength) + { + ResourceUpdateSuccessEventArgs resourceUpdateSuccessEventArgs = ReferencePool.Acquire(); + resourceUpdateSuccessEventArgs.Name = name; + resourceUpdateSuccessEventArgs.DownloadPath = downloadPath; + resourceUpdateSuccessEventArgs.DownloadUri = downloadUri; + resourceUpdateSuccessEventArgs.Length = length; + resourceUpdateSuccessEventArgs.CompressedLength = compressedLength; + return resourceUpdateSuccessEventArgs; + } + + /// + /// 清理资源更新成功事件。 + /// + public override void Clear() + { + Name = null; + DownloadPath = null; + DownloadUri = null; + Length = 0; + CompressedLength = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateSuccessEventArgs.cs.meta new file mode 100644 index 0000000..dbdc29d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceUpdateSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 83709c18daf7de44ebd1791eaa780eaf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifyFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifyFailureEventArgs.cs new file mode 100644 index 0000000..efaaef1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifyFailureEventArgs.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源校验失败事件。 + /// + public sealed class ResourceVerifyFailureEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化资源校验失败事件的新实例。 + /// + public ResourceVerifyFailureEventArgs() + { + Name = null; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 创建资源校验失败事件。 + /// + /// 资源名称。 + /// 创建的资源校验失败事件。 + public static ResourceVerifyFailureEventArgs Create(string name) + { + ResourceVerifyFailureEventArgs resourceVerifyFailureEventArgs = ReferencePool.Acquire(); + resourceVerifyFailureEventArgs.Name = name; + return resourceVerifyFailureEventArgs; + } + + /// + /// 清理资源校验失败事件。 + /// + public override void Clear() + { + Name = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifyFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifyFailureEventArgs.cs.meta new file mode 100644 index 0000000..249b6ba --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifyFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3595033b3cc1ffc49bf98d42fba4fdf8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifyStartEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifyStartEventArgs.cs new file mode 100644 index 0000000..9c3e3bd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifyStartEventArgs.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源校验开始事件。 + /// + public sealed class ResourceVerifyStartEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化资源校验开始事件的新实例。 + /// + public ResourceVerifyStartEventArgs() + { + Count = 0; + TotalLength = 0L; + } + + /// + /// 获取要校验资源的数量。 + /// + public int Count + { + get; + private set; + } + + /// + /// 获取要校验资源的总大小。 + /// + public long TotalLength + { + get; + private set; + } + + /// + /// 创建资源校验开始事件。 + /// + /// 要校验资源的数量。 + /// 要校验资源的总大小。 + /// 创建的资源校验开始事件。 + public static ResourceVerifyStartEventArgs Create(int count, long totalLength) + { + ResourceVerifyStartEventArgs resourceVerifyStartEventArgs = ReferencePool.Acquire(); + resourceVerifyStartEventArgs.Count = count; + resourceVerifyStartEventArgs.TotalLength = totalLength; + return resourceVerifyStartEventArgs; + } + + /// + /// 清理资源校验开始事件。 + /// + public override void Clear() + { + Count = 0; + TotalLength = 0L; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifyStartEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifyStartEventArgs.cs.meta new file mode 100644 index 0000000..f6b3361 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifyStartEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eec34bb9d218a354cbe2d80e913775c4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifySuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifySuccessEventArgs.cs new file mode 100644 index 0000000..4557f8a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifySuccessEventArgs.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 资源校验成功事件。 + /// + public sealed class ResourceVerifySuccessEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化资源校验成功事件的新实例。 + /// + public ResourceVerifySuccessEventArgs() + { + Name = null; + Length = 0; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取资源大小。 + /// + public int Length + { + get; + private set; + } + + /// + /// 创建资源校验成功事件。 + /// + /// 资源名称。 + /// 资源大小。 + /// 创建的资源校验成功事件。 + public static ResourceVerifySuccessEventArgs Create(string name, int length) + { + ResourceVerifySuccessEventArgs resourceVerifySuccessEventArgs = ReferencePool.Acquire(); + resourceVerifySuccessEventArgs.Name = name; + resourceVerifySuccessEventArgs.Length = length; + return resourceVerifySuccessEventArgs; + } + + /// + /// 清理资源校验成功事件。 + /// + public override void Clear() + { + Name = null; + Length = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifySuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifySuccessEventArgs.cs.meta new file mode 100644 index 0000000..5c07f10 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/ResourceVerifySuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e7d1c4ad05456f0428c3918407bee429 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneCallbacks.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneCallbacks.cs new file mode 100644 index 0000000..24bc510 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneCallbacks.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 卸载场景回调函数集。 + /// + public sealed class UnloadSceneCallbacks + { + private readonly UnloadSceneSuccessCallback m_UnloadSceneSuccessCallback; + private readonly UnloadSceneFailureCallback m_UnloadSceneFailureCallback; + + /// + /// 初始化卸载场景回调函数集的新实例。 + /// + /// 卸载场景成功回调函数。 + public UnloadSceneCallbacks(UnloadSceneSuccessCallback unloadSceneSuccessCallback) + : this(unloadSceneSuccessCallback, null) + { + } + + /// + /// 初始化卸载场景回调函数集的新实例。 + /// + /// 卸载场景成功回调函数。 + /// 卸载场景失败回调函数。 + public UnloadSceneCallbacks(UnloadSceneSuccessCallback unloadSceneSuccessCallback, UnloadSceneFailureCallback unloadSceneFailureCallback) + { + if (unloadSceneSuccessCallback == null) + { + throw new GameFrameworkException("Unload scene success callback is invalid."); + } + + m_UnloadSceneSuccessCallback = unloadSceneSuccessCallback; + m_UnloadSceneFailureCallback = unloadSceneFailureCallback; + } + + /// + /// 获取卸载场景成功回调函数。 + /// + public UnloadSceneSuccessCallback UnloadSceneSuccessCallback + { + get + { + return m_UnloadSceneSuccessCallback; + } + } + + /// + /// 获取卸载场景失败回调函数。 + /// + public UnloadSceneFailureCallback UnloadSceneFailureCallback + { + get + { + return m_UnloadSceneFailureCallback; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneCallbacks.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneCallbacks.cs.meta new file mode 100644 index 0000000..fe3cefd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneCallbacks.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 16eebecd11e81764082559a656aabd21 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneFailureCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneFailureCallback.cs new file mode 100644 index 0000000..5c62a76 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneFailureCallback.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 卸载场景失败回调函数。 + /// + /// 要卸载的场景资源名称。 + /// 用户自定义数据。 + public delegate void UnloadSceneFailureCallback(string sceneAssetName, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneFailureCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneFailureCallback.cs.meta new file mode 100644 index 0000000..c6ead2d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneFailureCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d8fff37bd72a4844198601d893648cbd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneSuccessCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneSuccessCallback.cs new file mode 100644 index 0000000..4337db1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneSuccessCallback.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 卸载场景成功回调函数。 + /// + /// 要卸载的场景资源名称。 + /// 用户自定义数据。 + public delegate void UnloadSceneSuccessCallback(string sceneAssetName, object userData); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneSuccessCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneSuccessCallback.cs.meta new file mode 100644 index 0000000..7452ee1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UnloadSceneSuccessCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 91f99543ee266b84f939b476fefa52ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.Asset.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.Asset.cs new file mode 100644 index 0000000..89b976e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.Asset.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + public partial struct UpdatableVersionList + { + /// + /// 资源。 + /// + [StructLayout(LayoutKind.Auto)] + public struct Asset + { + private static readonly int[] EmptyIntArray = new int[] { }; + + private readonly string m_Name; + private readonly int[] m_DependencyAssetIndexes; + + /// + /// 初始化资源的新实例。 + /// + /// 资源名称。 + /// 资源包含的依赖资源索引集合。 + public Asset(string name, int[] dependencyAssetIndexes) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + m_Name = name; + m_DependencyAssetIndexes = dependencyAssetIndexes ?? EmptyIntArray; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取资源包含的依赖资源索引集合。 + /// + /// 资源包含的依赖资源索引集合。 + public int[] GetDependencyAssetIndexes() + { + return m_DependencyAssetIndexes; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.Asset.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.Asset.cs.meta new file mode 100644 index 0000000..fbcf37f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.Asset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0d8ff3eef3791174e8451f2bdd3bf5d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.FileSystem.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.FileSystem.cs new file mode 100644 index 0000000..bd28196 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.FileSystem.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + public partial struct UpdatableVersionList + { + /// + /// 文件系统。 + /// + [StructLayout(LayoutKind.Auto)] + public struct FileSystem + { + private static readonly int[] EmptyIntArray = new int[] { }; + + private readonly string m_Name; + private readonly int[] m_ResourceIndexes; + + /// + /// 初始化文件系统的新实例。 + /// + /// 文件系统名称。 + /// 文件系统包含的资源索引集合。 + public FileSystem(string name, int[] resourceIndexes) + { + if (name == null) + { + throw new GameFrameworkException("Name is invalid."); + } + + m_Name = name; + m_ResourceIndexes = resourceIndexes ?? EmptyIntArray; + } + + /// + /// 获取文件系统名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取文件系统包含的资源索引集合。 + /// + /// 文件系统包含的资源索引集合。 + public int[] GetResourceIndexes() + { + return m_ResourceIndexes; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.FileSystem.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.FileSystem.cs.meta new file mode 100644 index 0000000..1556cd9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.FileSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4ddd9d123080534cb096b037df42620 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.Resource.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.Resource.cs new file mode 100644 index 0000000..b4eceaf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.Resource.cs @@ -0,0 +1,160 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + public partial struct UpdatableVersionList + { + /// + /// 资源。 + /// + [StructLayout(LayoutKind.Auto)] + public struct Resource + { + private static readonly int[] EmptyIntArray = new int[] { }; + + private readonly string m_Name; + private readonly string m_Variant; + private readonly string m_Extension; + private readonly byte m_LoadType; + private readonly int m_Length; + private readonly int m_HashCode; + private readonly int m_CompressedLength; + private readonly int m_CompressedHashCode; + private readonly int[] m_AssetIndexes; + + /// + /// 初始化资源的新实例。 + /// + /// 资源名称。 + /// 资源变体名称。 + /// 资源扩展名称。 + /// 资源加载方式。 + /// 资源长度。 + /// 资源哈希值。 + /// 资源压缩后长度。 + /// 资源压缩后哈希值。 + /// 资源包含的资源索引集合。 + public Resource(string name, string variant, string extension, byte loadType, int length, int hashCode, int compressedLength, int compressedHashCode, int[] assetIndexes) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Name is invalid."); + } + + m_Name = name; + m_Variant = variant; + m_Extension = extension; + m_LoadType = loadType; + m_Length = length; + m_HashCode = hashCode; + m_CompressedLength = compressedLength; + m_CompressedHashCode = compressedHashCode; + m_AssetIndexes = assetIndexes ?? EmptyIntArray; + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取资源变体名称。 + /// + public string Variant + { + get + { + return m_Variant; + } + } + + /// + /// 获取资源扩展名称。 + /// + public string Extension + { + get + { + return m_Extension; + } + } + + /// + /// 获取资源加载方式。 + /// + public byte LoadType + { + get + { + return m_LoadType; + } + } + + /// + /// 获取资源长度。 + /// + public int Length + { + get + { + return m_Length; + } + } + + /// + /// 获取资源哈希值。 + /// + public int HashCode + { + get + { + return m_HashCode; + } + } + + /// + /// 获取资源压缩后长度。 + /// + public int CompressedLength + { + get + { + return m_CompressedLength; + } + } + + /// + /// 获取资源压缩后哈希值。 + /// + public int CompressedHashCode + { + get + { + return m_CompressedHashCode; + } + } + + /// + /// 获取资源包含的资源索引集合。 + /// + /// 资源包含的资源索引集合。 + public int[] GetAssetIndexes() + { + return m_AssetIndexes; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.Resource.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.Resource.cs.meta new file mode 100644 index 0000000..84f3ba3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.Resource.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 56fd3ce6bf410be409ab3d0593a134e6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.ResourceGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.ResourceGroup.cs new file mode 100644 index 0000000..b0df9f8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.ResourceGroup.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + public partial struct UpdatableVersionList + { + /// + /// 资源组。 + /// + [StructLayout(LayoutKind.Auto)] + public struct ResourceGroup + { + private static readonly int[] EmptyIntArray = new int[] { }; + + private readonly string m_Name; + private readonly int[] m_ResourceIndexes; + + /// + /// 初始化资源组的新实例。 + /// + /// 资源组名称。 + /// 资源组包含的资源索引集合。 + public ResourceGroup(string name, int[] resourceIndexes) + { + if (name == null) + { + throw new GameFrameworkException("Name is invalid."); + } + + m_Name = name; + m_ResourceIndexes = resourceIndexes ?? EmptyIntArray; + } + + /// + /// 获取资源组名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取资源组包含的资源索引集合。 + /// + /// 资源组包含的资源索引集合。 + public int[] GetResourceIndexes() + { + return m_ResourceIndexes; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.ResourceGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.ResourceGroup.cs.meta new file mode 100644 index 0000000..71ef3c2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.ResourceGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a244462a671085b48bd704e016c286d1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.cs new file mode 100644 index 0000000..e8f908d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.cs @@ -0,0 +1,150 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Runtime.InteropServices; + +namespace GameFramework.Resource +{ + /// + /// 可更新模式版本资源列表。 + /// + [StructLayout(LayoutKind.Auto)] + public partial struct UpdatableVersionList + { + private static readonly Asset[] EmptyAssetArray = new Asset[] { }; + private static readonly Resource[] EmptyResourceArray = new Resource[] { }; + private static readonly FileSystem[] EmptyFileSystemArray = new FileSystem[] { }; + private static readonly ResourceGroup[] EmptyResourceGroupArray = new ResourceGroup[] { }; + + private readonly bool m_IsValid; + private readonly string m_ApplicableGameVersion; + private readonly int m_InternalResourceVersion; + private readonly Asset[] m_Assets; + private readonly Resource[] m_Resources; + private readonly FileSystem[] m_FileSystems; + private readonly ResourceGroup[] m_ResourceGroups; + + /// + /// 初始化可更新模式版本资源列表的新实例。 + /// + /// 适配的游戏版本号。 + /// 内部资源版本号。 + /// 包含的资源集合。 + /// 包含的资源集合。 + /// 包含的文件系统集合。 + /// 包含的资源组集合。 + public UpdatableVersionList(string applicableGameVersion, int internalResourceVersion, Asset[] assets, Resource[] resources, FileSystem[] fileSystems, ResourceGroup[] resourceGroups) + { + m_IsValid = true; + m_ApplicableGameVersion = applicableGameVersion; + m_InternalResourceVersion = internalResourceVersion; + m_Assets = assets ?? EmptyAssetArray; + m_Resources = resources ?? EmptyResourceArray; + m_FileSystems = fileSystems ?? EmptyFileSystemArray; + m_ResourceGroups = resourceGroups ?? EmptyResourceGroupArray; + } + + /// + /// 获取可更新模式版本资源列表是否有效。 + /// + public bool IsValid + { + get + { + return m_IsValid; + } + } + + /// + /// 获取适配的游戏版本号。 + /// + public string ApplicableGameVersion + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_ApplicableGameVersion; + } + } + + /// + /// 获取内部资源版本号。 + /// + public int InternalResourceVersion + { + get + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_InternalResourceVersion; + } + } + + /// + /// 获取包含的资源集合。 + /// + /// 包含的资源集合。 + public Asset[] GetAssets() + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_Assets; + } + + /// + /// 获取包含的资源集合。 + /// + /// 包含的资源集合。 + public Resource[] GetResources() + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_Resources; + } + + /// + /// 获取包含的文件系统集合。 + /// + /// 包含的文件系统集合。 + public FileSystem[] GetFileSystems() + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_FileSystems; + } + + /// + /// 获取包含的资源组集合。 + /// + /// 包含的资源组集合。 + public ResourceGroup[] GetResourceGroups() + { + if (!m_IsValid) + { + throw new GameFrameworkException("Data is invalid."); + } + + return m_ResourceGroups; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.cs.meta new file mode 100644 index 0000000..09140fb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6a1727e5e57f9b24e8b6fee68216484e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionListSerializer.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionListSerializer.cs new file mode 100644 index 0000000..2ea4bbc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionListSerializer.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 可更新模式版本资源列表序列化器。 + /// + public sealed class UpdatableVersionListSerializer : GameFrameworkSerializer + { + private static readonly byte[] Header = new byte[] { (byte)'G', (byte)'F', (byte)'U' }; + + /// + /// 初始化可更新模式版本资源列表序列化器的新实例。 + /// + public UpdatableVersionListSerializer() + { + } + + /// + /// 获取可更新模式版本资源列表头标识。 + /// + /// 可更新模式版本资源列表头标识。 + protected override byte[] GetHeader() + { + return Header; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionListSerializer.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionListSerializer.cs.meta new file mode 100644 index 0000000..ca15d71 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdatableVersionListSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3a4e3f11bb04fb94b8cec16d5b44877a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateResourcesCompleteCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateResourcesCompleteCallback.cs new file mode 100644 index 0000000..5c26ce5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateResourcesCompleteCallback.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 使用可更新模式并更新指定资源组完成时的回调函数。 + /// + /// 更新的资源组。 + /// 更新资源结果,全部成功为 true,否则为 false。 + public delegate void UpdateResourcesCompleteCallback(IResourceGroup resourceGroup, bool result); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateResourcesCompleteCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateResourcesCompleteCallback.cs.meta new file mode 100644 index 0000000..c8b730c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateResourcesCompleteCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d417741194db8cc489d40e0600f8f7b7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListCallbacks.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListCallbacks.cs new file mode 100644 index 0000000..89d9f5e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListCallbacks.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 版本资源列表更新回调函数集。 + /// + public sealed class UpdateVersionListCallbacks + { + private readonly UpdateVersionListSuccessCallback m_UpdateVersionListSuccessCallback; + private readonly UpdateVersionListFailureCallback m_UpdateVersionListFailureCallback; + + /// + /// 初始化版本资源列表更新回调函数集的新实例。 + /// + /// 版本资源列表更新成功回调函数。 + public UpdateVersionListCallbacks(UpdateVersionListSuccessCallback updateVersionListSuccessCallback) + : this(updateVersionListSuccessCallback, null) + { + } + + /// + /// 初始化版本资源列表更新回调函数集的新实例。 + /// + /// 版本资源列表更新成功回调函数。 + /// 版本资源列表更新失败回调函数。 + public UpdateVersionListCallbacks(UpdateVersionListSuccessCallback updateVersionListSuccessCallback, UpdateVersionListFailureCallback updateVersionListFailureCallback) + { + if (updateVersionListSuccessCallback == null) + { + throw new GameFrameworkException("Update version list success callback is invalid."); + } + + m_UpdateVersionListSuccessCallback = updateVersionListSuccessCallback; + m_UpdateVersionListFailureCallback = updateVersionListFailureCallback; + } + + /// + /// 获取版本资源列表更新成功回调函数。 + /// + public UpdateVersionListSuccessCallback UpdateVersionListSuccessCallback + { + get + { + return m_UpdateVersionListSuccessCallback; + } + } + + /// + /// 获取版本资源列表更新失败回调函数。 + /// + public UpdateVersionListFailureCallback UpdateVersionListFailureCallback + { + get + { + return m_UpdateVersionListFailureCallback; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListCallbacks.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListCallbacks.cs.meta new file mode 100644 index 0000000..4619be7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListCallbacks.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b0e27d2f388225246b155dff1a9c4252 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListFailureCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListFailureCallback.cs new file mode 100644 index 0000000..e2f32ba --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListFailureCallback.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 版本资源列表更新失败回调函数。 + /// + /// 版本资源列表更新地址。 + /// 错误信息。 + public delegate void UpdateVersionListFailureCallback(string downloadUri, string errorMessage); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListFailureCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListFailureCallback.cs.meta new file mode 100644 index 0000000..0f08aba --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListFailureCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: df6ea73c9ca77ea4b8fc195998d48a80 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListSuccessCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListSuccessCallback.cs new file mode 100644 index 0000000..01cc3ff --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListSuccessCallback.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 版本资源列表更新成功回调函数。 + /// + /// 版本资源列表更新后存放路径。 + /// 版本资源列表更新地址。 + public delegate void UpdateVersionListSuccessCallback(string downloadPath, string downloadUri); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListSuccessCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListSuccessCallback.cs.meta new file mode 100644 index 0000000..12a5a50 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/UpdateVersionListSuccessCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f8be8c99f5a36d74187802bd68a8cbdd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/VerifyResourcesCompleteCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/VerifyResourcesCompleteCallback.cs new file mode 100644 index 0000000..0202418 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/VerifyResourcesCompleteCallback.cs @@ -0,0 +1,15 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Resource +{ + /// + /// 使用可更新模式并校验资源完成时的回调函数。 + /// + /// 校验资源结果,全部成功为 true,否则为 false。 + public delegate void VerifyResourcesCompleteCallback(bool result); +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/VerifyResourcesCompleteCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/VerifyResourcesCompleteCallback.cs.meta new file mode 100644 index 0000000..8ff6e96 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Resource/VerifyResourcesCompleteCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ec29233d2ef58ab48aa77876f80c796e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene.meta new file mode 100644 index 0000000..ac8d678 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 40791dd36b5332a4f85177695931ab59 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/ISceneManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/ISceneManager.cs new file mode 100644 index 0000000..554700d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/ISceneManager.cs @@ -0,0 +1,160 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System; +using System.Collections.Generic; + +namespace GameFramework.Scene +{ + /// + /// 场景管理器接口。 + /// + public interface ISceneManager + { + /// + /// 加载场景成功事件。 + /// + event EventHandler LoadSceneSuccess; + + /// + /// 加载场景失败事件。 + /// + event EventHandler LoadSceneFailure; + + /// + /// 加载场景更新事件。 + /// + event EventHandler LoadSceneUpdate; + + /// + /// 加载场景时加载依赖资源事件。 + /// + event EventHandler LoadSceneDependencyAsset; + + /// + /// 卸载场景成功事件。 + /// + event EventHandler UnloadSceneSuccess; + + /// + /// 卸载场景失败事件。 + /// + event EventHandler UnloadSceneFailure; + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + void SetResourceManager(IResourceManager resourceManager); + + /// + /// 获取场景是否已加载。 + /// + /// 场景资源名称。 + /// 场景是否已加载。 + bool SceneIsLoaded(string sceneAssetName); + + /// + /// 获取已加载场景的资源名称。 + /// + /// 已加载场景的资源名称。 + string[] GetLoadedSceneAssetNames(); + + /// + /// 获取已加载场景的资源名称。 + /// + /// 已加载场景的资源名称。 + void GetLoadedSceneAssetNames(List results); + + /// + /// 获取场景是否正在加载。 + /// + /// 场景资源名称。 + /// 场景是否正在加载。 + bool SceneIsLoading(string sceneAssetName); + + /// + /// 获取正在加载场景的资源名称。 + /// + /// 正在加载场景的资源名称。 + string[] GetLoadingSceneAssetNames(); + + /// + /// 获取正在加载场景的资源名称。 + /// + /// 正在加载场景的资源名称。 + void GetLoadingSceneAssetNames(List results); + + /// + /// 获取场景是否正在卸载。 + /// + /// 场景资源名称。 + /// 场景是否正在卸载。 + bool SceneIsUnloading(string sceneAssetName); + + /// + /// 获取正在卸载场景的资源名称。 + /// + /// 正在卸载场景的资源名称。 + string[] GetUnloadingSceneAssetNames(); + + /// + /// 获取正在卸载场景的资源名称。 + /// + /// 正在卸载场景的资源名称。 + void GetUnloadingSceneAssetNames(List results); + + /// + /// 检查场景资源是否存在。 + /// + /// 要检查场景资源的名称。 + /// 场景资源是否存在。 + bool HasScene(string sceneAssetName); + + /// + /// 加载场景。 + /// + /// 场景资源名称。 + void LoadScene(string sceneAssetName); + + /// + /// 加载场景。 + /// + /// 场景资源名称。 + /// 加载场景资源的优先级。 + void LoadScene(string sceneAssetName, int priority); + + /// + /// 加载场景。 + /// + /// 场景资源名称。 + /// 用户自定义数据。 + void LoadScene(string sceneAssetName, object userData); + + /// + /// 加载场景。 + /// + /// 场景资源名称。 + /// 加载场景资源的优先级。 + /// 用户自定义数据。 + void LoadScene(string sceneAssetName, int priority, object userData); + + /// + /// 卸载场景。 + /// + /// 场景资源名称。 + void UnloadScene(string sceneAssetName); + + /// + /// 卸载场景。 + /// + /// 场景资源名称。 + /// 用户自定义数据。 + void UnloadScene(string sceneAssetName, object userData); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/ISceneManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/ISceneManager.cs.meta new file mode 100644 index 0000000..580c419 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/ISceneManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ba232f82a07ad3f458b23261a83754a8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneDependencyAssetEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneDependencyAssetEventArgs.cs new file mode 100644 index 0000000..9c85df6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneDependencyAssetEventArgs.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Scene +{ + /// + /// 加载场景时加载依赖资源事件。 + /// + public sealed class LoadSceneDependencyAssetEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化加载场景时加载依赖资源事件的新实例。 + /// + public LoadSceneDependencyAssetEventArgs() + { + SceneAssetName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + + /// + /// 获取场景资源名称。 + /// + public string SceneAssetName + { + get; + private set; + } + + /// + /// 获取被加载的依赖资源名称。 + /// + public string DependencyAssetName + { + get; + private set; + } + + /// + /// 获取当前已加载依赖资源数量。 + /// + public int LoadedCount + { + get; + private set; + } + + /// + /// 获取总共加载依赖资源数量。 + /// + public int TotalCount + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建场景时加载依赖资源事件。 + /// + /// 场景资源名称。 + /// 被加载的依赖资源名称。 + /// 当前已加载依赖资源数量。 + /// 总共加载依赖资源数量。 + /// 用户自定义数据。 + /// 创建的场景时加载依赖资源事件。 + public static LoadSceneDependencyAssetEventArgs Create(string sceneAssetName, string dependencyAssetName, int loadedCount, int totalCount, object userData) + { + LoadSceneDependencyAssetEventArgs loadSceneDependencyAssetEventArgs = ReferencePool.Acquire(); + loadSceneDependencyAssetEventArgs.SceneAssetName = sceneAssetName; + loadSceneDependencyAssetEventArgs.DependencyAssetName = dependencyAssetName; + loadSceneDependencyAssetEventArgs.LoadedCount = loadedCount; + loadSceneDependencyAssetEventArgs.TotalCount = totalCount; + loadSceneDependencyAssetEventArgs.UserData = userData; + return loadSceneDependencyAssetEventArgs; + } + + /// + /// 清理场景时加载依赖资源事件。 + /// + public override void Clear() + { + SceneAssetName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneDependencyAssetEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneDependencyAssetEventArgs.cs.meta new file mode 100644 index 0000000..b6b95c3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneDependencyAssetEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 684badaad7df8924d9b6919bf424579d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneFailureEventArgs.cs new file mode 100644 index 0000000..ef4d47d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneFailureEventArgs.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Scene +{ + /// + /// 加载场景失败事件。 + /// + public sealed class LoadSceneFailureEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化加载场景失败事件的新实例。 + /// + public LoadSceneFailureEventArgs() + { + SceneAssetName = null; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取场景资源名称。 + /// + public string SceneAssetName + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载场景失败事件。 + /// + /// 场景资源名称。 + /// 错误信息。 + /// 用户自定义数据。 + /// 创建的加载场景失败事件。 + public static LoadSceneFailureEventArgs Create(string sceneAssetName, string errorMessage, object userData) + { + LoadSceneFailureEventArgs loadSceneFailureEventArgs = ReferencePool.Acquire(); + loadSceneFailureEventArgs.SceneAssetName = sceneAssetName; + loadSceneFailureEventArgs.ErrorMessage = errorMessage; + loadSceneFailureEventArgs.UserData = userData; + return loadSceneFailureEventArgs; + } + + /// + /// 清理加载场景失败事件。 + /// + public override void Clear() + { + SceneAssetName = null; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneFailureEventArgs.cs.meta new file mode 100644 index 0000000..bb31494 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 649d2a673e06db3459b8a2430730e16b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneSuccessEventArgs.cs new file mode 100644 index 0000000..497ba78 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneSuccessEventArgs.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Scene +{ + /// + /// 加载场景成功事件。 + /// + public sealed class LoadSceneSuccessEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化加载场景成功事件的新实例。 + /// + public LoadSceneSuccessEventArgs() + { + SceneAssetName = null; + Duration = 0f; + UserData = null; + } + + /// + /// 获取场景资源名称。 + /// + public string SceneAssetName + { + get; + private set; + } + + /// + /// 获取加载持续时间。 + /// + public float Duration + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载场景成功事件。 + /// + /// 场景资源名称。 + /// 加载持续时间。 + /// 用户自定义数据。 + /// 创建的加载场景成功事件。 + public static LoadSceneSuccessEventArgs Create(string sceneAssetName, float duration, object userData) + { + LoadSceneSuccessEventArgs loadSceneSuccessEventArgs = ReferencePool.Acquire(); + loadSceneSuccessEventArgs.SceneAssetName = sceneAssetName; + loadSceneSuccessEventArgs.Duration = duration; + loadSceneSuccessEventArgs.UserData = userData; + return loadSceneSuccessEventArgs; + } + + /// + /// 清理加载场景成功事件。 + /// + public override void Clear() + { + SceneAssetName = null; + Duration = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneSuccessEventArgs.cs.meta new file mode 100644 index 0000000..5ae3cac --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aca459d7d59851d41a55eb2b289ce025 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneUpdateEventArgs.cs new file mode 100644 index 0000000..d98e11b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneUpdateEventArgs.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Scene +{ + /// + /// 加载场景更新事件。 + /// + public sealed class LoadSceneUpdateEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化加载场景更新事件的新实例。 + /// + public LoadSceneUpdateEventArgs() + { + SceneAssetName = null; + Progress = 0f; + UserData = null; + } + + /// + /// 获取场景资源名称。 + /// + public string SceneAssetName + { + get; + private set; + } + + /// + /// 获取加载场景进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载场景更新事件。 + /// + /// 场景资源名称。 + /// 加载场景进度。 + /// 用户自定义数据。 + /// 创建的加载场景更新事件。 + public static LoadSceneUpdateEventArgs Create(string sceneAssetName, float progress, object userData) + { + LoadSceneUpdateEventArgs loadSceneUpdateEventArgs = ReferencePool.Acquire(); + loadSceneUpdateEventArgs.SceneAssetName = sceneAssetName; + loadSceneUpdateEventArgs.Progress = progress; + loadSceneUpdateEventArgs.UserData = userData; + return loadSceneUpdateEventArgs; + } + + /// + /// 清理加载场景更新事件。 + /// + public override void Clear() + { + SceneAssetName = null; + Progress = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneUpdateEventArgs.cs.meta new file mode 100644 index 0000000..fc6b7be --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/LoadSceneUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4ee84ce1eb99bf840b5c011bb848319a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/SceneManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/SceneManager.cs new file mode 100644 index 0000000..7ae7feb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/SceneManager.cs @@ -0,0 +1,508 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System; +using System.Collections.Generic; + +namespace GameFramework.Scene +{ + /// + /// 场景管理器。 + /// + internal sealed class SceneManager : GameFrameworkModule, ISceneManager + { + private readonly List m_LoadedSceneAssetNames; + private readonly List m_LoadingSceneAssetNames; + private readonly List m_UnloadingSceneAssetNames; + private readonly LoadSceneCallbacks m_LoadSceneCallbacks; + private readonly UnloadSceneCallbacks m_UnloadSceneCallbacks; + private IResourceManager m_ResourceManager; + private EventHandler m_LoadSceneSuccessEventHandler; + private EventHandler m_LoadSceneFailureEventHandler; + private EventHandler m_LoadSceneUpdateEventHandler; + private EventHandler m_LoadSceneDependencyAssetEventHandler; + private EventHandler m_UnloadSceneSuccessEventHandler; + private EventHandler m_UnloadSceneFailureEventHandler; + + /// + /// 初始化场景管理器的新实例。 + /// + public SceneManager() + { + m_LoadedSceneAssetNames = new List(); + m_LoadingSceneAssetNames = new List(); + m_UnloadingSceneAssetNames = new List(); + m_LoadSceneCallbacks = new LoadSceneCallbacks(LoadSceneSuccessCallback, LoadSceneFailureCallback, LoadSceneUpdateCallback, LoadSceneDependencyAssetCallback); + m_UnloadSceneCallbacks = new UnloadSceneCallbacks(UnloadSceneSuccessCallback, UnloadSceneFailureCallback); + m_ResourceManager = null; + m_LoadSceneSuccessEventHandler = null; + m_LoadSceneFailureEventHandler = null; + m_LoadSceneUpdateEventHandler = null; + m_LoadSceneDependencyAssetEventHandler = null; + m_UnloadSceneSuccessEventHandler = null; + m_UnloadSceneFailureEventHandler = null; + } + + /// + /// 获取游戏框架模块优先级。 + /// + /// 优先级较高的模块会优先轮询,并且关闭操作会后进行。 + internal override int Priority + { + get + { + return 2; + } + } + + /// + /// 加载场景成功事件。 + /// + public event EventHandler LoadSceneSuccess + { + add + { + m_LoadSceneSuccessEventHandler += value; + } + remove + { + m_LoadSceneSuccessEventHandler -= value; + } + } + + /// + /// 加载场景失败事件。 + /// + public event EventHandler LoadSceneFailure + { + add + { + m_LoadSceneFailureEventHandler += value; + } + remove + { + m_LoadSceneFailureEventHandler -= value; + } + } + + /// + /// 加载场景更新事件。 + /// + public event EventHandler LoadSceneUpdate + { + add + { + m_LoadSceneUpdateEventHandler += value; + } + remove + { + m_LoadSceneUpdateEventHandler -= value; + } + } + + /// + /// 加载场景时加载依赖资源事件。 + /// + public event EventHandler LoadSceneDependencyAsset + { + add + { + m_LoadSceneDependencyAssetEventHandler += value; + } + remove + { + m_LoadSceneDependencyAssetEventHandler -= value; + } + } + + /// + /// 卸载场景成功事件。 + /// + public event EventHandler UnloadSceneSuccess + { + add + { + m_UnloadSceneSuccessEventHandler += value; + } + remove + { + m_UnloadSceneSuccessEventHandler -= value; + } + } + + /// + /// 卸载场景失败事件。 + /// + public event EventHandler UnloadSceneFailure + { + add + { + m_UnloadSceneFailureEventHandler += value; + } + remove + { + m_UnloadSceneFailureEventHandler -= value; + } + } + + /// + /// 场景管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 关闭并清理场景管理器。 + /// + internal override void Shutdown() + { + string[] loadedSceneAssetNames = m_LoadedSceneAssetNames.ToArray(); + foreach (string loadedSceneAssetName in loadedSceneAssetNames) + { + if (SceneIsUnloading(loadedSceneAssetName)) + { + continue; + } + + UnloadScene(loadedSceneAssetName); + } + + m_LoadedSceneAssetNames.Clear(); + m_LoadingSceneAssetNames.Clear(); + m_UnloadingSceneAssetNames.Clear(); + } + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + public void SetResourceManager(IResourceManager resourceManager) + { + if (resourceManager == null) + { + throw new GameFrameworkException("Resource manager is invalid."); + } + + m_ResourceManager = resourceManager; + } + + /// + /// 获取场景是否已加载。 + /// + /// 场景资源名称。 + /// 场景是否已加载。 + public bool SceneIsLoaded(string sceneAssetName) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + throw new GameFrameworkException("Scene asset name is invalid."); + } + + return m_LoadedSceneAssetNames.Contains(sceneAssetName); + } + + /// + /// 获取已加载场景的资源名称。 + /// + /// 已加载场景的资源名称。 + public string[] GetLoadedSceneAssetNames() + { + return m_LoadedSceneAssetNames.ToArray(); + } + + /// + /// 获取已加载场景的资源名称。 + /// + /// 已加载场景的资源名称。 + public void GetLoadedSceneAssetNames(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + results.AddRange(m_LoadedSceneAssetNames); + } + + /// + /// 获取场景是否正在加载。 + /// + /// 场景资源名称。 + /// 场景是否正在加载。 + public bool SceneIsLoading(string sceneAssetName) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + throw new GameFrameworkException("Scene asset name is invalid."); + } + + return m_LoadingSceneAssetNames.Contains(sceneAssetName); + } + + /// + /// 获取正在加载场景的资源名称。 + /// + /// 正在加载场景的资源名称。 + public string[] GetLoadingSceneAssetNames() + { + return m_LoadingSceneAssetNames.ToArray(); + } + + /// + /// 获取正在加载场景的资源名称。 + /// + /// 正在加载场景的资源名称。 + public void GetLoadingSceneAssetNames(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + results.AddRange(m_LoadingSceneAssetNames); + } + + /// + /// 获取场景是否正在卸载。 + /// + /// 场景资源名称。 + /// 场景是否正在卸载。 + public bool SceneIsUnloading(string sceneAssetName) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + throw new GameFrameworkException("Scene asset name is invalid."); + } + + return m_UnloadingSceneAssetNames.Contains(sceneAssetName); + } + + /// + /// 获取正在卸载场景的资源名称。 + /// + /// 正在卸载场景的资源名称。 + public string[] GetUnloadingSceneAssetNames() + { + return m_UnloadingSceneAssetNames.ToArray(); + } + + /// + /// 获取正在卸载场景的资源名称。 + /// + /// 正在卸载场景的资源名称。 + public void GetUnloadingSceneAssetNames(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + results.AddRange(m_UnloadingSceneAssetNames); + } + + /// + /// 检查场景资源是否存在。 + /// + /// 要检查场景资源的名称。 + /// 场景资源是否存在。 + public bool HasScene(string sceneAssetName) + { + return m_ResourceManager.HasAsset(sceneAssetName) != HasAssetResult.NotExist; + } + + /// + /// 加载场景。 + /// + /// 场景资源名称。 + public void LoadScene(string sceneAssetName) + { + LoadScene(sceneAssetName, Constant.DefaultPriority, null); + } + + /// + /// 加载场景。 + /// + /// 场景资源名称。 + /// 加载场景资源的优先级。 + public void LoadScene(string sceneAssetName, int priority) + { + LoadScene(sceneAssetName, priority, null); + } + + /// + /// 加载场景。 + /// + /// 场景资源名称。 + /// 用户自定义数据。 + public void LoadScene(string sceneAssetName, object userData) + { + LoadScene(sceneAssetName, Constant.DefaultPriority, userData); + } + + /// + /// 加载场景。 + /// + /// 场景资源名称。 + /// 加载场景资源的优先级。 + /// 用户自定义数据。 + public void LoadScene(string sceneAssetName, int priority, object userData) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + throw new GameFrameworkException("Scene asset name is invalid."); + } + + if (m_ResourceManager == null) + { + throw new GameFrameworkException("You must set resource manager first."); + } + + if (SceneIsUnloading(sceneAssetName)) + { + throw new GameFrameworkException(Utility.Text.Format("Scene asset '{0}' is being unloaded.", sceneAssetName)); + } + + if (SceneIsLoading(sceneAssetName)) + { + throw new GameFrameworkException(Utility.Text.Format("Scene asset '{0}' is being loaded.", sceneAssetName)); + } + + if (SceneIsLoaded(sceneAssetName)) + { + throw new GameFrameworkException(Utility.Text.Format("Scene asset '{0}' is already loaded.", sceneAssetName)); + } + + m_LoadingSceneAssetNames.Add(sceneAssetName); + m_ResourceManager.LoadScene(sceneAssetName, priority, m_LoadSceneCallbacks, userData); + } + + /// + /// 卸载场景。 + /// + /// 场景资源名称。 + public void UnloadScene(string sceneAssetName) + { + UnloadScene(sceneAssetName, null); + } + + /// + /// 卸载场景。 + /// + /// 场景资源名称。 + /// 用户自定义数据。 + public void UnloadScene(string sceneAssetName, object userData) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + throw new GameFrameworkException("Scene asset name is invalid."); + } + + if (m_ResourceManager == null) + { + throw new GameFrameworkException("You must set resource manager first."); + } + + if (SceneIsUnloading(sceneAssetName)) + { + throw new GameFrameworkException(Utility.Text.Format("Scene asset '{0}' is being unloaded.", sceneAssetName)); + } + + if (SceneIsLoading(sceneAssetName)) + { + throw new GameFrameworkException(Utility.Text.Format("Scene asset '{0}' is being loaded.", sceneAssetName)); + } + + if (!SceneIsLoaded(sceneAssetName)) + { + throw new GameFrameworkException(Utility.Text.Format("Scene asset '{0}' is not loaded yet.", sceneAssetName)); + } + + m_UnloadingSceneAssetNames.Add(sceneAssetName); + m_ResourceManager.UnloadScene(sceneAssetName, m_UnloadSceneCallbacks, userData); + } + + private void LoadSceneSuccessCallback(string sceneAssetName, float duration, object userData) + { + m_LoadingSceneAssetNames.Remove(sceneAssetName); + m_LoadedSceneAssetNames.Add(sceneAssetName); + if (m_LoadSceneSuccessEventHandler != null) + { + LoadSceneSuccessEventArgs loadSceneSuccessEventArgs = LoadSceneSuccessEventArgs.Create(sceneAssetName, duration, userData); + m_LoadSceneSuccessEventHandler(this, loadSceneSuccessEventArgs); + ReferencePool.Release(loadSceneSuccessEventArgs); + } + } + + private void LoadSceneFailureCallback(string sceneAssetName, LoadResourceStatus status, string errorMessage, object userData) + { + m_LoadingSceneAssetNames.Remove(sceneAssetName); + string appendErrorMessage = Utility.Text.Format("Load scene failure, scene asset name '{0}', status '{1}', error message '{2}'.", sceneAssetName, status, errorMessage); + if (m_LoadSceneFailureEventHandler != null) + { + LoadSceneFailureEventArgs loadSceneFailureEventArgs = LoadSceneFailureEventArgs.Create(sceneAssetName, appendErrorMessage, userData); + m_LoadSceneFailureEventHandler(this, loadSceneFailureEventArgs); + ReferencePool.Release(loadSceneFailureEventArgs); + return; + } + + throw new GameFrameworkException(appendErrorMessage); + } + + private void LoadSceneUpdateCallback(string sceneAssetName, float progress, object userData) + { + if (m_LoadSceneUpdateEventHandler != null) + { + LoadSceneUpdateEventArgs loadSceneUpdateEventArgs = LoadSceneUpdateEventArgs.Create(sceneAssetName, progress, userData); + m_LoadSceneUpdateEventHandler(this, loadSceneUpdateEventArgs); + ReferencePool.Release(loadSceneUpdateEventArgs); + } + } + + private void LoadSceneDependencyAssetCallback(string sceneAssetName, string dependencyAssetName, int loadedCount, int totalCount, object userData) + { + if (m_LoadSceneDependencyAssetEventHandler != null) + { + LoadSceneDependencyAssetEventArgs loadSceneDependencyAssetEventArgs = LoadSceneDependencyAssetEventArgs.Create(sceneAssetName, dependencyAssetName, loadedCount, totalCount, userData); + m_LoadSceneDependencyAssetEventHandler(this, loadSceneDependencyAssetEventArgs); + ReferencePool.Release(loadSceneDependencyAssetEventArgs); + } + } + + private void UnloadSceneSuccessCallback(string sceneAssetName, object userData) + { + m_UnloadingSceneAssetNames.Remove(sceneAssetName); + m_LoadedSceneAssetNames.Remove(sceneAssetName); + if (m_UnloadSceneSuccessEventHandler != null) + { + UnloadSceneSuccessEventArgs unloadSceneSuccessEventArgs = UnloadSceneSuccessEventArgs.Create(sceneAssetName, userData); + m_UnloadSceneSuccessEventHandler(this, unloadSceneSuccessEventArgs); + ReferencePool.Release(unloadSceneSuccessEventArgs); + } + } + + private void UnloadSceneFailureCallback(string sceneAssetName, object userData) + { + m_UnloadingSceneAssetNames.Remove(sceneAssetName); + if (m_UnloadSceneFailureEventHandler != null) + { + UnloadSceneFailureEventArgs unloadSceneFailureEventArgs = UnloadSceneFailureEventArgs.Create(sceneAssetName, userData); + m_UnloadSceneFailureEventHandler(this, unloadSceneFailureEventArgs); + ReferencePool.Release(unloadSceneFailureEventArgs); + return; + } + + throw new GameFrameworkException(Utility.Text.Format("Unload scene failure, scene asset name '{0}'.", sceneAssetName)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/SceneManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/SceneManager.cs.meta new file mode 100644 index 0000000..5af88f9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/SceneManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9beaade359bbaac499c456248ad86133 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/UnloadSceneFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/UnloadSceneFailureEventArgs.cs new file mode 100644 index 0000000..9d39a93 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/UnloadSceneFailureEventArgs.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Scene +{ + /// + /// 卸载场景失败事件。 + /// + public sealed class UnloadSceneFailureEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化卸载场景失败事件的新实例。 + /// + public UnloadSceneFailureEventArgs() + { + SceneAssetName = null; + UserData = null; + } + + /// + /// 获取场景资源名称。 + /// + public string SceneAssetName + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建卸载场景失败事件。 + /// + /// 场景资源名称。 + /// 用户自定义数据。 + /// 创建的卸载场景失败事件。 + public static UnloadSceneFailureEventArgs Create(string sceneAssetName, object userData) + { + UnloadSceneFailureEventArgs unloadSceneFailureEventArgs = ReferencePool.Acquire(); + unloadSceneFailureEventArgs.SceneAssetName = sceneAssetName; + unloadSceneFailureEventArgs.UserData = userData; + return unloadSceneFailureEventArgs; + } + + /// + /// 清理卸载场景失败事件。 + /// + public override void Clear() + { + SceneAssetName = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/UnloadSceneFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/UnloadSceneFailureEventArgs.cs.meta new file mode 100644 index 0000000..3098ae5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/UnloadSceneFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf3ddc418ace15e4687690c54ddfaaf5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/UnloadSceneSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/UnloadSceneSuccessEventArgs.cs new file mode 100644 index 0000000..99b5611 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/UnloadSceneSuccessEventArgs.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Scene +{ + /// + /// 卸载场景成功事件。 + /// + public sealed class UnloadSceneSuccessEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化卸载场景成功事件的新实例。 + /// + public UnloadSceneSuccessEventArgs() + { + SceneAssetName = null; + UserData = null; + } + + /// + /// 获取场景资源名称。 + /// + public string SceneAssetName + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建卸载场景成功事件。 + /// + /// 场景资源名称。 + /// 用户自定义数据。 + /// 创建的卸载场景成功事件。 + public static UnloadSceneSuccessEventArgs Create(string sceneAssetName, object userData) + { + UnloadSceneSuccessEventArgs unloadSceneSuccessEventArgs = ReferencePool.Acquire(); + unloadSceneSuccessEventArgs.SceneAssetName = sceneAssetName; + unloadSceneSuccessEventArgs.UserData = userData; + return unloadSceneSuccessEventArgs; + } + + /// + /// 清理卸载场景成功事件。 + /// + public override void Clear() + { + SceneAssetName = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/UnloadSceneSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/UnloadSceneSuccessEventArgs.cs.meta new file mode 100644 index 0000000..1786d47 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Scene/UnloadSceneSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e3d29ec2157d3ca428b45a29b378fb71 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting.meta new file mode 100644 index 0000000..546ae28 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 119808378a10f044590fe3ee8ab7ac63 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/ISettingHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/ISettingHelper.cs new file mode 100644 index 0000000..86777cf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/ISettingHelper.cs @@ -0,0 +1,206 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.Setting +{ + /// + /// 游戏配置辅助器接口。 + /// + public interface ISettingHelper + { + /// + /// 获取游戏配置项数量。 + /// + int Count + { + get; + } + + /// + /// 加载游戏配置。 + /// + /// 是否加载游戏配置成功。 + bool Load(); + + /// + /// 保存游戏配置。 + /// + /// 是否保存游戏配置成功。 + bool Save(); + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + string[] GetAllSettingNames(); + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + void GetAllSettingNames(List results); + + /// + /// 检查是否存在指定游戏配置项。 + /// + /// 要检查游戏配置项的名称。 + /// 指定的游戏配置项是否存在。 + bool HasSetting(string settingName); + + /// + /// 移除指定游戏配置项。 + /// + /// 要移除游戏配置项的名称。 + /// 是否移除指定游戏配置项成功。 + bool RemoveSetting(string settingName); + + /// + /// 清空所有游戏配置项。 + /// + void RemoveAllSettings(); + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的布尔值。 + bool GetBool(string settingName); + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的布尔值。 + bool GetBool(string settingName, bool defaultValue); + + /// + /// 向指定游戏配置项写入布尔值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的布尔值。 + void SetBool(string settingName, bool value); + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的整数值。 + int GetInt(string settingName); + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的整数值。 + int GetInt(string settingName, int defaultValue); + + /// + /// 向指定游戏配置项写入整数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的整数值。 + void SetInt(string settingName, int value); + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的浮点数值。 + float GetFloat(string settingName); + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的浮点数值。 + float GetFloat(string settingName, float defaultValue); + + /// + /// 向指定游戏配置项写入浮点数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的浮点数值。 + void SetFloat(string settingName, float value); + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的字符串值。 + string GetString(string settingName); + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的字符串值。 + string GetString(string settingName, string defaultValue); + + /// + /// 向指定游戏配置项写入字符串值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的字符串值。 + void SetString(string settingName, string value); + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + T GetObject(string settingName); + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + object GetObject(Type objectType, string settingName); + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + T GetObject(string settingName, T defaultObj); + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + object GetObject(Type objectType, string settingName, object defaultObj); + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入对象的类型。 + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + void SetObject(string settingName, T obj); + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + void SetObject(string settingName, object obj); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/ISettingHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/ISettingHelper.cs.meta new file mode 100644 index 0000000..5a95624 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/ISettingHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fd6a8c650ab78ad4fbfab9f888d07ee5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/ISettingManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/ISettingManager.cs new file mode 100644 index 0000000..d0dccbe --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/ISettingManager.cs @@ -0,0 +1,212 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.Setting +{ + /// + /// 游戏配置管理器接口。 + /// + public interface ISettingManager + { + /// + /// 获取游戏配置项数量。 + /// + int Count + { + get; + } + + /// + /// 设置游戏配置辅助器。 + /// + /// 游戏配置辅助器。 + void SetSettingHelper(ISettingHelper settingHelper); + + /// + /// 加载游戏配置。 + /// + /// 是否加载游戏配置成功。 + bool Load(); + + /// + /// 保存游戏配置。 + /// + /// 是否保存游戏配置成功。 + bool Save(); + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + string[] GetAllSettingNames(); + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + void GetAllSettingNames(List results); + + /// + /// 检查是否存在指定游戏配置项。 + /// + /// 要检查游戏配置项的名称。 + /// 指定的游戏配置项是否存在。 + bool HasSetting(string settingName); + + /// + /// 移除指定游戏配置项。 + /// + /// 要移除游戏配置项的名称。 + /// 是否移除指定游戏配置项成功。 + bool RemoveSetting(string settingName); + + /// + /// 清空所有游戏配置项。 + /// + void RemoveAllSettings(); + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的布尔值。 + bool GetBool(string settingName); + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的布尔值。 + bool GetBool(string settingName, bool defaultValue); + + /// + /// 向指定游戏配置项写入布尔值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的布尔值。 + void SetBool(string settingName, bool value); + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的整数值。 + int GetInt(string settingName); + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的整数值。 + int GetInt(string settingName, int defaultValue); + + /// + /// 向指定游戏配置项写入整数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的整数值。 + void SetInt(string settingName, int value); + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的浮点数值。 + float GetFloat(string settingName); + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的浮点数值。 + float GetFloat(string settingName, float defaultValue); + + /// + /// 向指定游戏配置项写入浮点数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的浮点数值。 + void SetFloat(string settingName, float value); + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的字符串值。 + string GetString(string settingName); + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的字符串值。 + string GetString(string settingName, string defaultValue); + + /// + /// 向指定游戏配置项写入字符串值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的字符串值。 + void SetString(string settingName, string value); + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + T GetObject(string settingName); + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + object GetObject(Type objectType, string settingName); + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + T GetObject(string settingName, T defaultObj); + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + object GetObject(Type objectType, string settingName, object defaultObj); + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入对象的类型。 + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + void SetObject(string settingName, T obj); + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + void SetObject(string settingName, object obj); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/ISettingManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/ISettingManager.cs.meta new file mode 100644 index 0000000..b0135f4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/ISettingManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2fd340e8af449e44c851d7336931989b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/SettingManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/SettingManager.cs new file mode 100644 index 0000000..b2373c3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/SettingManager.cs @@ -0,0 +1,565 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.Setting +{ + /// + /// 游戏配置管理器。 + /// + internal sealed class SettingManager : GameFrameworkModule, ISettingManager + { + private ISettingHelper m_SettingHelper; + + /// + /// 初始化游戏配置管理器的新实例。 + /// + public SettingManager() + { + m_SettingHelper = null; + } + + /// + /// 获取游戏配置项数量。 + /// + public int Count + { + get + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + return m_SettingHelper.Count; + } + } + + /// + /// 游戏配置管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 关闭并清理游戏配置管理器。 + /// + internal override void Shutdown() + { + Save(); + } + + /// + /// 设置游戏配置辅助器。 + /// + /// 游戏配置辅助器。 + public void SetSettingHelper(ISettingHelper settingHelper) + { + if (settingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + m_SettingHelper = settingHelper; + } + + /// + /// 加载游戏配置。 + /// + /// 是否加载游戏配置成功。 + public bool Load() + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + return m_SettingHelper.Load(); + } + + /// + /// 保存游戏配置。 + /// + /// 是否保存游戏配置成功。 + public bool Save() + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + return m_SettingHelper.Save(); + } + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + public string[] GetAllSettingNames() + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + return m_SettingHelper.GetAllSettingNames(); + } + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + public void GetAllSettingNames(List results) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + m_SettingHelper.GetAllSettingNames(results); + } + + /// + /// 检查是否存在指定游戏配置项。 + /// + /// 要检查游戏配置项的名称。 + /// 指定的游戏配置项是否存在。 + public bool HasSetting(string settingName) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.HasSetting(settingName); + } + + /// + /// 移除指定游戏配置项。 + /// + /// 要移除游戏配置项的名称。 + /// 是否移除指定游戏配置项成功。 + public bool RemoveSetting(string settingName) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.RemoveSetting(settingName); + } + + /// + /// 清空所有游戏配置项。 + /// + public void RemoveAllSettings() + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + m_SettingHelper.RemoveAllSettings(); + } + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的布尔值。 + public bool GetBool(string settingName) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.GetBool(settingName); + } + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的布尔值。 + public bool GetBool(string settingName, bool defaultValue) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.GetBool(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入布尔值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的布尔值。 + public void SetBool(string settingName, bool value) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + m_SettingHelper.SetBool(settingName, value); + } + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的整数值。 + public int GetInt(string settingName) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.GetInt(settingName); + } + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的整数值。 + public int GetInt(string settingName, int defaultValue) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.GetInt(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入整数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的整数值。 + public void SetInt(string settingName, int value) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + m_SettingHelper.SetInt(settingName, value); + } + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的浮点数值。 + public float GetFloat(string settingName) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.GetFloat(settingName); + } + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的浮点数值。 + public float GetFloat(string settingName, float defaultValue) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.GetFloat(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入浮点数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的浮点数值。 + public void SetFloat(string settingName, float value) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + m_SettingHelper.SetFloat(settingName, value); + } + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的字符串值。 + public string GetString(string settingName) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.GetString(settingName); + } + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的字符串值。 + public string GetString(string settingName, string defaultValue) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.GetString(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入字符串值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的字符串值。 + public void SetString(string settingName, string value) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + m_SettingHelper.SetString(settingName, value); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + public T GetObject(string settingName) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.GetObject(settingName); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + public object GetObject(Type objectType, string settingName) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (objectType == null) + { + throw new GameFrameworkException("Object type is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.GetObject(objectType, settingName); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + public T GetObject(string settingName, T defaultObj) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.GetObject(settingName, defaultObj); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + public object GetObject(Type objectType, string settingName, object defaultObj) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (objectType == null) + { + throw new GameFrameworkException("Object type is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + return m_SettingHelper.GetObject(objectType, settingName, defaultObj); + } + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入对象的类型。 + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + public void SetObject(string settingName, T obj) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + m_SettingHelper.SetObject(settingName, obj); + } + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + public void SetObject(string settingName, object obj) + { + if (m_SettingHelper == null) + { + throw new GameFrameworkException("Setting helper is invalid."); + } + + if (string.IsNullOrEmpty(settingName)) + { + throw new GameFrameworkException("Setting name is invalid."); + } + + m_SettingHelper.SetObject(settingName, obj); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/SettingManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/SettingManager.cs.meta new file mode 100644 index 0000000..4392726 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Setting/SettingManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d2a2ed92ad2214a46970b139fac12534 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound.meta new file mode 100644 index 0000000..0072539 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c6cd89b7b0099e049825ee853b4bf7e8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/Constant.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/Constant.cs new file mode 100644 index 0000000..3171243 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/Constant.cs @@ -0,0 +1,28 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + /// + /// 声音相关常量。 + /// + internal static class Constant + { + internal const float DefaultTime = 0f; + internal const bool DefaultMute = false; + internal const bool DefaultLoop = false; + internal const int DefaultPriority = 0; + internal const float DefaultVolume = 1f; + internal const float DefaultFadeInSeconds = 0f; + internal const float DefaultFadeOutSeconds = 0f; + internal const float DefaultPitch = 1f; + internal const float DefaultPanStereo = 0f; + internal const float DefaultSpatialBlend = 0f; + internal const float DefaultMaxDistance = 100f; + internal const float DefaultDopplerLevel = 1f; + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/Constant.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/Constant.cs.meta new file mode 100644 index 0000000..d285e4c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/Constant.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 73ec2070ae8732540a594a399690a510 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundAgent.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundAgent.cs new file mode 100644 index 0000000..2c39c75 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundAgent.cs @@ -0,0 +1,210 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + /// + /// 声音代理接口。 + /// + public interface ISoundAgent + { + /// + /// 获取所在的声音组。 + /// + ISoundGroup SoundGroup + { + get; + } + + /// + /// 获取声音的序列编号。 + /// + int SerialId + { + get; + } + + /// + /// 获取当前是否正在播放。 + /// + bool IsPlaying + { + get; + } + + /// + /// 获取声音长度。 + /// + float Length + { + get; + } + + /// + /// 获取或设置播放位置。 + /// + float Time + { + get; + set; + } + + /// + /// 获取或设置是否静音。 + /// + bool Mute + { + get; + } + + /// + /// 获取或设置在声音组内是否静音。 + /// + bool MuteInSoundGroup + { + get; + set; + } + + /// + /// 获取或设置是否循环播放。 + /// + bool Loop + { + get; + set; + } + + /// + /// 获取或设置声音优先级。 + /// + int Priority + { + get; + set; + } + + /// + /// 获取音量大小。 + /// + float Volume + { + get; + } + + /// + /// 获取或设置在声音组内音量大小。 + /// + float VolumeInSoundGroup + { + get; + set; + } + + /// + /// 获取或设置声音音调。 + /// + float Pitch + { + get; + set; + } + + /// + /// 获取或设置声音立体声声相。 + /// + float PanStereo + { + get; + set; + } + + /// + /// 获取或设置声音空间混合量。 + /// + float SpatialBlend + { + get; + set; + } + + /// + /// 获取或设置声音最大距离。 + /// + float MaxDistance + { + get; + set; + } + + /// + /// 获取或设置声音多普勒等级。 + /// + float DopplerLevel + { + get; + set; + } + + /// + /// 获取声音代理辅助器。 + /// + ISoundAgentHelper Helper + { + get; + } + + /// + /// 播放声音。 + /// + void Play(); + + /// + /// 播放声音。 + /// + /// 声音淡入时间,以秒为单位。 + void Play(float fadeInSeconds); + + /// + /// 停止播放声音。 + /// + void Stop(); + + /// + /// 停止播放声音。 + /// + /// 声音淡出时间,以秒为单位。 + void Stop(float fadeOutSeconds); + + /// + /// 暂停播放声音。 + /// + void Pause(); + + /// + /// 暂停播放声音。 + /// + /// 声音淡出时间,以秒为单位。 + void Pause(float fadeOutSeconds); + + /// + /// 恢复播放声音。 + /// + void Resume(); + + /// + /// 恢复播放声音。 + /// + /// 声音淡入时间,以秒为单位。 + void Resume(float fadeInSeconds); + + /// + /// 重置声音代理。 + /// + void Reset(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundAgent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundAgent.cs.meta new file mode 100644 index 0000000..b89c3e2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundAgent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 39b05094e2882604786408581f61a677 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundAgentHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundAgentHelper.cs new file mode 100644 index 0000000..791e4fc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundAgentHelper.cs @@ -0,0 +1,164 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.Sound +{ + /// + /// 声音代理辅助器接口。 + /// + public interface ISoundAgentHelper + { + /// + /// 获取当前是否正在播放。 + /// + bool IsPlaying + { + get; + } + + /// + /// 获取声音长度。 + /// + float Length + { + get; + } + + /// + /// 获取或设置播放位置。 + /// + float Time + { + get; + set; + } + + /// + /// 获取或设置是否静音。 + /// + bool Mute + { + get; + set; + } + + /// + /// 获取或设置是否循环播放。 + /// + bool Loop + { + get; + set; + } + + /// + /// 获取或设置声音优先级。 + /// + int Priority + { + get; + set; + } + + /// + /// 获取或设置音量大小。 + /// + float Volume + { + get; + set; + } + + /// + /// 获取或设置声音音调。 + /// + float Pitch + { + get; + set; + } + + /// + /// 获取或设置声音立体声声相。 + /// + float PanStereo + { + get; + set; + } + + /// + /// 获取或设置声音空间混合量。 + /// + float SpatialBlend + { + get; + set; + } + + /// + /// 获取或设置声音最大距离。 + /// + float MaxDistance + { + get; + set; + } + + /// + /// 获取或设置声音多普勒等级。 + /// + float DopplerLevel + { + get; + set; + } + + /// + /// 重置声音代理事件。 + /// + event EventHandler ResetSoundAgent; + + /// + /// 播放声音。 + /// + /// 声音淡入时间,以秒为单位。 + void Play(float fadeInSeconds); + + /// + /// 停止播放声音。 + /// + /// 声音淡出时间,以秒为单位。 + void Stop(float fadeOutSeconds); + + /// + /// 暂停播放声音。 + /// + /// 声音淡出时间,以秒为单位。 + void Pause(float fadeOutSeconds); + + /// + /// 恢复播放声音。 + /// + /// 声音淡入时间,以秒为单位。 + void Resume(float fadeInSeconds); + + /// + /// 重置声音代理辅助器。 + /// + void Reset(); + + /// + /// 设置声音资源。 + /// + /// 声音资源。 + /// 是否设置声音资源成功。 + bool SetSoundAsset(object soundAsset); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundAgentHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundAgentHelper.cs.meta new file mode 100644 index 0000000..be151e5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundAgentHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a198d2b5273597e4a9e92d64e0b9d87d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundGroup.cs new file mode 100644 index 0000000..5b10d73 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundGroup.cs @@ -0,0 +1,77 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + /// + /// 声音组接口。 + /// + public interface ISoundGroup + { + /// + /// 获取声音组名称。 + /// + string Name + { + get; + } + + /// + /// 获取声音代理数。 + /// + int SoundAgentCount + { + get; + } + + /// + /// 获取或设置声音组中的声音是否避免被同优先级声音替换。 + /// + bool AvoidBeingReplacedBySamePriority + { + get; + set; + } + + /// + /// 获取或设置声音组静音。 + /// + bool Mute + { + get; + set; + } + + /// + /// 获取或设置声音组音量。 + /// + float Volume + { + get; + set; + } + + /// + /// 获取声音组辅助器。 + /// + ISoundGroupHelper Helper + { + get; + } + + /// + /// 停止所有已加载的声音。 + /// + void StopAllLoadedSounds(); + + /// + /// 停止所有已加载的声音。 + /// + /// 声音淡出时间,以秒为单位。 + void StopAllLoadedSounds(float fadeOutSeconds); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundGroup.cs.meta new file mode 100644 index 0000000..d1d46ab --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f9f65ec262734184e89412198692aa3d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundGroupHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundGroupHelper.cs new file mode 100644 index 0000000..a692c0b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundGroupHelper.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + /// + /// 声音组辅助器接口。 + /// + public interface ISoundGroupHelper + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundGroupHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundGroupHelper.cs.meta new file mode 100644 index 0000000..83cfefa --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundGroupHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 25b0aadd2f5970b45921cfd849adc2cc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundHelper.cs new file mode 100644 index 0000000..49e782f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundHelper.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + /// + /// 声音辅助器接口。 + /// + public interface ISoundHelper + { + /// + /// 释放声音资源。 + /// + /// 要释放的声音资源。 + void ReleaseSoundAsset(object soundAsset); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundHelper.cs.meta new file mode 100644 index 0000000..f463b5d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d2ab5df40a839f64fa2ad954160d9bb2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundManager.cs new file mode 100644 index 0000000..0a7a61e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundManager.cs @@ -0,0 +1,263 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System; +using System.Collections.Generic; + +namespace GameFramework.Sound +{ + /// + /// 声音管理器接口。 + /// + public interface ISoundManager + { + /// + /// 获取声音组数量。 + /// + int SoundGroupCount + { + get; + } + + /// + /// 播放声音成功事件。 + /// + event EventHandler PlaySoundSuccess; + + /// + /// 播放声音失败事件。 + /// + event EventHandler PlaySoundFailure; + + /// + /// 播放声音更新事件。 + /// + event EventHandler PlaySoundUpdate; + + /// + /// 播放声音时加载依赖资源事件。 + /// + event EventHandler PlaySoundDependencyAsset; + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + void SetResourceManager(IResourceManager resourceManager); + + /// + /// 设置声音辅助器。 + /// + /// 声音辅助器。 + void SetSoundHelper(ISoundHelper soundHelper); + + /// + /// 是否存在指定声音组。 + /// + /// 声音组名称。 + /// 指定声音组是否存在。 + bool HasSoundGroup(string soundGroupName); + + /// + /// 获取指定声音组。 + /// + /// 声音组名称。 + /// 要获取的声音组。 + ISoundGroup GetSoundGroup(string soundGroupName); + + /// + /// 获取所有声音组。 + /// + /// 所有声音组。 + ISoundGroup[] GetAllSoundGroups(); + + /// + /// 获取所有声音组。 + /// + /// 所有声音组。 + void GetAllSoundGroups(List results); + + /// + /// 增加声音组。 + /// + /// 声音组名称。 + /// 声音组辅助器。 + /// 是否增加声音组成功。 + bool AddSoundGroup(string soundGroupName, ISoundGroupHelper soundGroupHelper); + + /// + /// 增加声音组。 + /// + /// 声音组名称。 + /// 声音组中的声音是否避免被同优先级声音替换。 + /// 声音组是否静音。 + /// 声音组音量。 + /// 声音组辅助器。 + /// 是否增加声音组成功。 + bool AddSoundGroup(string soundGroupName, bool soundGroupAvoidBeingReplacedBySamePriority, bool soundGroupMute, float soundGroupVolume, ISoundGroupHelper soundGroupHelper); + + /// + /// 增加声音代理辅助器。 + /// + /// 声音组名称。 + /// 要增加的声音代理辅助器。 + void AddSoundAgentHelper(string soundGroupName, ISoundAgentHelper soundAgentHelper); + + /// + /// 获取所有正在加载声音的序列编号。 + /// + /// 所有正在加载声音的序列编号。 + int[] GetAllLoadingSoundSerialIds(); + + /// + /// 获取所有正在加载声音的序列编号。 + /// + /// 所有正在加载声音的序列编号。 + void GetAllLoadingSoundSerialIds(List results); + + /// + /// 是否正在加载声音。 + /// + /// 声音序列编号。 + /// 是否正在加载声音。 + bool IsLoadingSound(int serialId); + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 声音的序列编号。 + int PlaySound(string soundAssetName, string soundGroupName); + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 声音的序列编号。 + int PlaySound(string soundAssetName, string soundGroupName, int priority); + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 播放声音参数。 + /// 声音的序列编号。 + int PlaySound(string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams); + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 用户自定义数据。 + /// 声音的序列编号。 + int PlaySound(string soundAssetName, string soundGroupName, object userData); + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 播放声音参数。 + /// 声音的序列编号。 + int PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams); + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 用户自定义数据。 + /// 声音的序列编号。 + int PlaySound(string soundAssetName, string soundGroupName, int priority, object userData); + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 播放声音参数。 + /// 用户自定义数据。 + /// 声音的序列编号。 + int PlaySound(string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams, object userData); + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 播放声音参数。 + /// 用户自定义数据。 + /// 声音的序列编号。 + int PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams, object userData); + + /// + /// 停止播放声音。 + /// + /// 要停止播放声音的序列编号。 + /// 是否停止播放声音成功。 + bool StopSound(int serialId); + + /// + /// 停止播放声音。 + /// + /// 要停止播放声音的序列编号。 + /// 声音淡出时间,以秒为单位。 + /// 是否停止播放声音成功。 + bool StopSound(int serialId, float fadeOutSeconds); + + /// + /// 停止所有已加载的声音。 + /// + void StopAllLoadedSounds(); + + /// + /// 停止所有已加载的声音。 + /// + /// 声音淡出时间,以秒为单位。 + void StopAllLoadedSounds(float fadeOutSeconds); + + /// + /// 停止所有正在加载的声音。 + /// + void StopAllLoadingSounds(); + + /// + /// 暂停播放声音。 + /// + /// 要暂停播放声音的序列编号。 + void PauseSound(int serialId); + + /// + /// 暂停播放声音。 + /// + /// 要暂停播放声音的序列编号。 + /// 声音淡出时间,以秒为单位。 + void PauseSound(int serialId, float fadeOutSeconds); + + /// + /// 恢复播放声音。 + /// + /// 要恢复播放声音的序列编号。 + void ResumeSound(int serialId); + + /// + /// 恢复播放声音。 + /// + /// 要恢复播放声音的序列编号。 + /// 声音淡入时间,以秒为单位。 + void ResumeSound(int serialId, float fadeInSeconds); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundManager.cs.meta new file mode 100644 index 0000000..6c6059f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ISoundManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b2231c752fe8bf74389d7b7e1c2cd72b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundDependencyAssetEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundDependencyAssetEventArgs.cs new file mode 100644 index 0000000..c8b50e2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundDependencyAssetEventArgs.cs @@ -0,0 +1,143 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + /// + /// 播放声音时加载依赖资源事件。 + /// + public sealed class PlaySoundDependencyAssetEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化播放声音时加载依赖资源事件的新实例。 + /// + public PlaySoundDependencyAssetEventArgs() + { + SerialId = 0; + SoundAssetName = null; + SoundGroupName = null; + PlaySoundParams = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + + /// + /// 获取声音的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取声音资源名称。 + /// + public string SoundAssetName + { + get; + private set; + } + + /// + /// 获取声音组名称。 + /// + public string SoundGroupName + { + get; + private set; + } + + /// + /// 获取播放声音参数。 + /// + public PlaySoundParams PlaySoundParams + { + get; + private set; + } + + /// + /// 获取被加载的依赖资源名称。 + /// + public string DependencyAssetName + { + get; + private set; + } + + /// + /// 获取当前已加载依赖资源数量。 + /// + public int LoadedCount + { + get; + private set; + } + + /// + /// 获取总共加载依赖资源数量。 + /// + public int TotalCount + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建播放声音时加载依赖资源事件。 + /// + /// 声音的序列编号。 + /// 声音资源名称。 + /// 声音组名称。 + /// 播放声音参数。 + /// 被加载的依赖资源名称。 + /// 当前已加载依赖资源数量。 + /// 总共加载依赖资源数量。 + /// 用户自定义数据。 + /// 创建的播放声音时加载依赖资源事件。 + public static PlaySoundDependencyAssetEventArgs Create(int serialId, string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams, string dependencyAssetName, int loadedCount, int totalCount, object userData) + { + PlaySoundDependencyAssetEventArgs playSoundDependencyAssetEventArgs = ReferencePool.Acquire(); + playSoundDependencyAssetEventArgs.SerialId = serialId; + playSoundDependencyAssetEventArgs.SoundAssetName = soundAssetName; + playSoundDependencyAssetEventArgs.SoundGroupName = soundGroupName; + playSoundDependencyAssetEventArgs.PlaySoundParams = playSoundParams; + playSoundDependencyAssetEventArgs.DependencyAssetName = dependencyAssetName; + playSoundDependencyAssetEventArgs.LoadedCount = loadedCount; + playSoundDependencyAssetEventArgs.TotalCount = totalCount; + playSoundDependencyAssetEventArgs.UserData = userData; + return playSoundDependencyAssetEventArgs; + } + + /// + /// 清理播放声音时加载依赖资源事件。 + /// + public override void Clear() + { + SerialId = 0; + SoundAssetName = null; + SoundGroupName = null; + PlaySoundParams = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundDependencyAssetEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundDependencyAssetEventArgs.cs.meta new file mode 100644 index 0000000..7456059 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundDependencyAssetEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3870242352f33644fa98edaf0f5b714a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundErrorCode.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundErrorCode.cs new file mode 100644 index 0000000..23582fd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundErrorCode.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + /// + /// 播放声音错误码。 + /// + public enum PlaySoundErrorCode : byte + { + /// + /// 未知错误。 + /// + Unknown = 0, + + /// + /// 声音组不存在。 + /// + SoundGroupNotExist, + + /// + /// 声音组没有声音代理。 + /// + SoundGroupHasNoAgent, + + /// + /// 加载资源失败。 + /// + LoadAssetFailure, + + /// + /// 播放声音因优先级低被忽略。 + /// + IgnoredDueToLowPriority, + + /// + /// 设置声音资源失败。 + /// + SetSoundAssetFailure + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundErrorCode.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundErrorCode.cs.meta new file mode 100644 index 0000000..736102c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundErrorCode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 506ffd5cce7d287439d2fd7d0e229b7a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundFailureEventArgs.cs new file mode 100644 index 0000000..9f33655 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundFailureEventArgs.cs @@ -0,0 +1,130 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + /// + /// 播放声音失败事件。 + /// + public sealed class PlaySoundFailureEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化播放声音失败事件的新实例。 + /// + public PlaySoundFailureEventArgs() + { + SerialId = 0; + SoundAssetName = null; + SoundGroupName = null; + PlaySoundParams = null; + ErrorCode = PlaySoundErrorCode.Unknown; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取声音的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取声音资源名称。 + /// + public string SoundAssetName + { + get; + private set; + } + + /// + /// 获取声音组名称。 + /// + public string SoundGroupName + { + get; + private set; + } + + /// + /// 获取播放声音参数。 + /// + public PlaySoundParams PlaySoundParams + { + get; + private set; + } + + /// + /// 获取错误码。 + /// + public PlaySoundErrorCode ErrorCode + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建播放声音失败事件。 + /// + /// 声音的序列编号。 + /// 声音资源名称。 + /// 声音组名称。 + /// 播放声音参数。 + /// 错误码。 + /// 错误信息。 + /// 用户自定义数据。 + /// 创建的播放声音失败事件。 + public static PlaySoundFailureEventArgs Create(int serialId, string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams, PlaySoundErrorCode errorCode, string errorMessage, object userData) + { + PlaySoundFailureEventArgs playSoundFailureEventArgs = ReferencePool.Acquire(); + playSoundFailureEventArgs.SerialId = serialId; + playSoundFailureEventArgs.SoundAssetName = soundAssetName; + playSoundFailureEventArgs.SoundGroupName = soundGroupName; + playSoundFailureEventArgs.PlaySoundParams = playSoundParams; + playSoundFailureEventArgs.ErrorCode = errorCode; + playSoundFailureEventArgs.ErrorMessage = errorMessage; + playSoundFailureEventArgs.UserData = userData; + return playSoundFailureEventArgs; + } + + /// + /// 清理播放声音失败事件。 + /// + public override void Clear() + { + SerialId = 0; + SoundAssetName = null; + SoundGroupName = null; + PlaySoundParams = null; + ErrorCode = PlaySoundErrorCode.Unknown; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundFailureEventArgs.cs.meta new file mode 100644 index 0000000..93e0c4b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dcc0883ff1d420d4abae1eedd6ae4950 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundParams.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundParams.cs new file mode 100644 index 0000000..925b915 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundParams.cs @@ -0,0 +1,249 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + /// + /// 播放声音参数。 + /// + public sealed class PlaySoundParams : IReference + { + private bool m_Referenced; + private float m_Time; + private bool m_MuteInSoundGroup; + private bool m_Loop; + private int m_Priority; + private float m_VolumeInSoundGroup; + private float m_FadeInSeconds; + private float m_Pitch; + private float m_PanStereo; + private float m_SpatialBlend; + private float m_MaxDistance; + private float m_DopplerLevel; + + /// + /// 初始化播放声音参数的新实例。 + /// + public PlaySoundParams() + { + m_Referenced = false; + m_Time = Constant.DefaultTime; + m_MuteInSoundGroup = Constant.DefaultMute; + m_Loop = Constant.DefaultLoop; + m_Priority = Constant.DefaultPriority; + m_VolumeInSoundGroup = Constant.DefaultVolume; + m_FadeInSeconds = Constant.DefaultFadeInSeconds; + m_Pitch = Constant.DefaultPitch; + m_PanStereo = Constant.DefaultPanStereo; + m_SpatialBlend = Constant.DefaultSpatialBlend; + m_MaxDistance = Constant.DefaultMaxDistance; + m_DopplerLevel = Constant.DefaultDopplerLevel; + } + + /// + /// 获取或设置播放位置。 + /// + public float Time + { + get + { + return m_Time; + } + set + { + m_Time = value; + } + } + + /// + /// 获取或设置在声音组内是否静音。 + /// + public bool MuteInSoundGroup + { + get + { + return m_MuteInSoundGroup; + } + set + { + m_MuteInSoundGroup = value; + } + } + + /// + /// 获取或设置是否循环播放。 + /// + public bool Loop + { + get + { + return m_Loop; + } + set + { + m_Loop = value; + } + } + + /// + /// 获取或设置声音优先级。 + /// + public int Priority + { + get + { + return m_Priority; + } + set + { + m_Priority = value; + } + } + + /// + /// 获取或设置在声音组内音量大小。 + /// + public float VolumeInSoundGroup + { + get + { + return m_VolumeInSoundGroup; + } + set + { + m_VolumeInSoundGroup = value; + } + } + + /// + /// 获取或设置声音淡入时间,以秒为单位。 + /// + public float FadeInSeconds + { + get + { + return m_FadeInSeconds; + } + set + { + m_FadeInSeconds = value; + } + } + + /// + /// 获取或设置声音音调。 + /// + public float Pitch + { + get + { + return m_Pitch; + } + set + { + m_Pitch = value; + } + } + + /// + /// 获取或设置声音立体声声相。 + /// + public float PanStereo + { + get + { + return m_PanStereo; + } + set + { + m_PanStereo = value; + } + } + + /// + /// 获取或设置声音空间混合量。 + /// + public float SpatialBlend + { + get + { + return m_SpatialBlend; + } + set + { + m_SpatialBlend = value; + } + } + + /// + /// 获取或设置声音最大距离。 + /// + public float MaxDistance + { + get + { + return m_MaxDistance; + } + set + { + m_MaxDistance = value; + } + } + + /// + /// 获取或设置声音多普勒等级。 + /// + public float DopplerLevel + { + get + { + return m_DopplerLevel; + } + set + { + m_DopplerLevel = value; + } + } + + internal bool Referenced + { + get + { + return m_Referenced; + } + } + + /// + /// 创建播放声音参数。 + /// + /// 创建的播放声音参数。 + public static PlaySoundParams Create() + { + PlaySoundParams playSoundParams = ReferencePool.Acquire(); + playSoundParams.m_Referenced = true; + return playSoundParams; + } + + /// + /// 清理播放声音参数。 + /// + public void Clear() + { + m_Time = Constant.DefaultTime; + m_MuteInSoundGroup = Constant.DefaultMute; + m_Loop = Constant.DefaultLoop; + m_Priority = Constant.DefaultPriority; + m_VolumeInSoundGroup = Constant.DefaultVolume; + m_FadeInSeconds = Constant.DefaultFadeInSeconds; + m_Pitch = Constant.DefaultPitch; + m_PanStereo = Constant.DefaultPanStereo; + m_SpatialBlend = Constant.DefaultSpatialBlend; + m_MaxDistance = Constant.DefaultMaxDistance; + m_DopplerLevel = Constant.DefaultDopplerLevel; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundParams.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundParams.cs.meta new file mode 100644 index 0000000..c07693e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundParams.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1f0ab03dd1e65114ca9878d4e43d0c2b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundSuccessEventArgs.cs new file mode 100644 index 0000000..0f45e48 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundSuccessEventArgs.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + /// + /// 播放声音成功事件。 + /// + public sealed class PlaySoundSuccessEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化播放声音成功事件的新实例。 + /// + public PlaySoundSuccessEventArgs() + { + SerialId = 0; + SoundAssetName = null; + SoundAgent = null; + Duration = 0f; + UserData = null; + } + + /// + /// 获取声音的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取声音资源名称。 + /// + public string SoundAssetName + { + get; + private set; + } + + /// + /// 获取用于播放的声音代理。 + /// + public ISoundAgent SoundAgent + { + get; + private set; + } + + /// + /// 获取加载持续时间。 + /// + public float Duration + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建播放声音成功事件。 + /// + /// 声音的序列编号。 + /// 声音资源名称。 + /// 用于播放的声音代理。 + /// 加载持续时间。 + /// 用户自定义数据。 + /// 创建的播放声音成功事件。 + public static PlaySoundSuccessEventArgs Create(int serialId, string soundAssetName, ISoundAgent soundAgent, float duration, object userData) + { + PlaySoundSuccessEventArgs playSoundSuccessEventArgs = ReferencePool.Acquire(); + playSoundSuccessEventArgs.SerialId = serialId; + playSoundSuccessEventArgs.SoundAssetName = soundAssetName; + playSoundSuccessEventArgs.SoundAgent = soundAgent; + playSoundSuccessEventArgs.Duration = duration; + playSoundSuccessEventArgs.UserData = userData; + return playSoundSuccessEventArgs; + } + + /// + /// 清理播放声音成功事件。 + /// + public override void Clear() + { + SerialId = 0; + SoundAssetName = null; + SoundAgent = null; + Duration = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundSuccessEventArgs.cs.meta new file mode 100644 index 0000000..e2dd2a1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b6ff75b138c7a834883b620337f4af60 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundUpdateEventArgs.cs new file mode 100644 index 0000000..b38d5db --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundUpdateEventArgs.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + /// + /// 播放声音更新事件。 + /// + public sealed class PlaySoundUpdateEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化播放声音更新事件的新实例。 + /// + public PlaySoundUpdateEventArgs() + { + SerialId = 0; + SoundAssetName = null; + SoundGroupName = null; + PlaySoundParams = null; + Progress = 0f; + UserData = null; + } + + /// + /// 获取声音的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取声音资源名称。 + /// + public string SoundAssetName + { + get; + private set; + } + + /// + /// 获取声音组名称。 + /// + public string SoundGroupName + { + get; + private set; + } + + /// + /// 获取播放声音参数。 + /// + public PlaySoundParams PlaySoundParams + { + get; + private set; + } + + /// + /// 获取加载声音进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建播放声音更新事件。 + /// + /// 声音的序列编号。 + /// 声音资源名称。 + /// 声音组名称。 + /// 播放声音参数。 + /// 加载声音进度。 + /// 用户自定义数据。 + /// 创建的播放声音更新事件。 + public static PlaySoundUpdateEventArgs Create(int serialId, string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams, float progress, object userData) + { + PlaySoundUpdateEventArgs playSoundUpdateEventArgs = ReferencePool.Acquire(); + playSoundUpdateEventArgs.SerialId = serialId; + playSoundUpdateEventArgs.SoundAssetName = soundAssetName; + playSoundUpdateEventArgs.SoundGroupName = soundGroupName; + playSoundUpdateEventArgs.PlaySoundParams = playSoundParams; + playSoundUpdateEventArgs.Progress = progress; + playSoundUpdateEventArgs.UserData = userData; + return playSoundUpdateEventArgs; + } + + /// + /// 清理播放声音更新事件。 + /// + public override void Clear() + { + SerialId = 0; + SoundAssetName = null; + SoundGroupName = null; + PlaySoundParams = null; + Progress = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundUpdateEventArgs.cs.meta new file mode 100644 index 0000000..85c3aac --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/PlaySoundUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a9e09c20f9c203d44847a59958af6152 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ResetSoundAgentEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ResetSoundAgentEventArgs.cs new file mode 100644 index 0000000..d7149cb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ResetSoundAgentEventArgs.cs @@ -0,0 +1,39 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + /// + /// 重置声音代理事件。 + /// + public sealed class ResetSoundAgentEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化重置声音代理事件的新实例。 + /// + public ResetSoundAgentEventArgs() + { + } + + /// + /// 创建重置声音代理事件。 + /// + /// 创建的重置声音代理事件。 + public static ResetSoundAgentEventArgs Create() + { + ResetSoundAgentEventArgs resetSoundAgentEventArgs = ReferencePool.Acquire(); + return resetSoundAgentEventArgs; + } + + /// + /// 清理重置声音代理事件。 + /// + public override void Clear() + { + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ResetSoundAgentEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ResetSoundAgentEventArgs.cs.meta new file mode 100644 index 0000000..e51c563 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/ResetSoundAgentEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e55f60639c30d114fb45eb41e641fb7c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.PlaySoundInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.PlaySoundInfo.cs new file mode 100644 index 0000000..c5911e1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.PlaySoundInfo.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.Sound +{ + internal sealed partial class SoundManager : GameFrameworkModule, ISoundManager + { + private sealed class PlaySoundInfo : IReference + { + private int m_SerialId; + private SoundGroup m_SoundGroup; + private PlaySoundParams m_PlaySoundParams; + private object m_UserData; + + public PlaySoundInfo() + { + m_SerialId = 0; + m_SoundGroup = null; + m_PlaySoundParams = null; + m_UserData = null; + } + + public int SerialId + { + get + { + return m_SerialId; + } + } + + public SoundGroup SoundGroup + { + get + { + return m_SoundGroup; + } + } + + public PlaySoundParams PlaySoundParams + { + get + { + return m_PlaySoundParams; + } + } + + public object UserData + { + get + { + return m_UserData; + } + } + + public static PlaySoundInfo Create(int serialId, SoundGroup soundGroup, PlaySoundParams playSoundParams, object userData) + { + PlaySoundInfo playSoundInfo = ReferencePool.Acquire(); + playSoundInfo.m_SerialId = serialId; + playSoundInfo.m_SoundGroup = soundGroup; + playSoundInfo.m_PlaySoundParams = playSoundParams; + playSoundInfo.m_UserData = userData; + return playSoundInfo; + } + + public void Clear() + { + m_SerialId = 0; + m_SoundGroup = null; + m_PlaySoundParams = null; + m_UserData = null; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.PlaySoundInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.PlaySoundInfo.cs.meta new file mode 100644 index 0000000..5576f27 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.PlaySoundInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9d507b6824e0ed74d8b71e9c14ba6f09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.SoundAgent.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.SoundAgent.cs new file mode 100644 index 0000000..33fd630 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.SoundAgent.cs @@ -0,0 +1,421 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.Sound +{ + internal sealed partial class SoundManager : GameFrameworkModule, ISoundManager + { + /// + /// 声音代理。 + /// + private sealed class SoundAgent : ISoundAgent + { + private readonly SoundGroup m_SoundGroup; + private readonly ISoundHelper m_SoundHelper; + private readonly ISoundAgentHelper m_SoundAgentHelper; + private int m_SerialId; + private object m_SoundAsset; + private DateTime m_SetSoundAssetTime; + private bool m_MuteInSoundGroup; + private float m_VolumeInSoundGroup; + + /// + /// 初始化声音代理的新实例。 + /// + /// 所在的声音组。 + /// 声音辅助器接口。 + /// 声音代理辅助器接口。 + public SoundAgent(SoundGroup soundGroup, ISoundHelper soundHelper, ISoundAgentHelper soundAgentHelper) + { + if (soundGroup == null) + { + throw new GameFrameworkException("Sound group is invalid."); + } + + if (soundHelper == null) + { + throw new GameFrameworkException("Sound helper is invalid."); + } + + if (soundAgentHelper == null) + { + throw new GameFrameworkException("Sound agent helper is invalid."); + } + + m_SoundGroup = soundGroup; + m_SoundHelper = soundHelper; + m_SoundAgentHelper = soundAgentHelper; + m_SoundAgentHelper.ResetSoundAgent += OnResetSoundAgent; + m_SerialId = 0; + m_SoundAsset = null; + Reset(); + } + + /// + /// 获取所在的声音组。 + /// + public ISoundGroup SoundGroup + { + get + { + return m_SoundGroup; + } + } + + /// + /// 获取或设置声音的序列编号。 + /// + public int SerialId + { + get + { + return m_SerialId; + } + set + { + m_SerialId = value; + } + } + + /// + /// 获取当前是否正在播放。 + /// + public bool IsPlaying + { + get + { + return m_SoundAgentHelper.IsPlaying; + } + } + + /// + /// 获取声音长度。 + /// + public float Length + { + get + { + return m_SoundAgentHelper.Length; + } + } + + /// + /// 获取或设置播放位置。 + /// + public float Time + { + get + { + return m_SoundAgentHelper.Time; + } + set + { + m_SoundAgentHelper.Time = value; + } + } + + /// + /// 获取是否静音。 + /// + public bool Mute + { + get + { + return m_SoundAgentHelper.Mute; + } + } + + /// + /// 获取或设置在声音组内是否静音。 + /// + public bool MuteInSoundGroup + { + get + { + return m_MuteInSoundGroup; + } + set + { + m_MuteInSoundGroup = value; + RefreshMute(); + } + } + + /// + /// 获取或设置是否循环播放。 + /// + public bool Loop + { + get + { + return m_SoundAgentHelper.Loop; + } + set + { + m_SoundAgentHelper.Loop = value; + } + } + + /// + /// 获取或设置声音优先级。 + /// + public int Priority + { + get + { + return m_SoundAgentHelper.Priority; + } + set + { + m_SoundAgentHelper.Priority = value; + } + } + + /// + /// 获取音量大小。 + /// + public float Volume + { + get + { + return m_SoundAgentHelper.Volume; + } + } + + /// + /// 获取或设置在声音组内音量大小。 + /// + public float VolumeInSoundGroup + { + get + { + return m_VolumeInSoundGroup; + } + set + { + m_VolumeInSoundGroup = value; + RefreshVolume(); + } + } + + /// + /// 获取或设置声音音调。 + /// + public float Pitch + { + get + { + return m_SoundAgentHelper.Pitch; + } + set + { + m_SoundAgentHelper.Pitch = value; + } + } + + /// + /// 获取或设置声音立体声声相。 + /// + public float PanStereo + { + get + { + return m_SoundAgentHelper.PanStereo; + } + set + { + m_SoundAgentHelper.PanStereo = value; + } + } + + /// + /// 获取或设置声音空间混合量。 + /// + public float SpatialBlend + { + get + { + return m_SoundAgentHelper.SpatialBlend; + } + set + { + m_SoundAgentHelper.SpatialBlend = value; + } + } + + /// + /// 获取或设置声音最大距离。 + /// + public float MaxDistance + { + get + { + return m_SoundAgentHelper.MaxDistance; + } + set + { + m_SoundAgentHelper.MaxDistance = value; + } + } + + /// + /// 获取或设置声音多普勒等级。 + /// + public float DopplerLevel + { + get + { + return m_SoundAgentHelper.DopplerLevel; + } + set + { + m_SoundAgentHelper.DopplerLevel = value; + } + } + + /// + /// 获取声音代理辅助器。 + /// + public ISoundAgentHelper Helper + { + get + { + return m_SoundAgentHelper; + } + } + + /// + /// 获取声音创建时间。 + /// + internal DateTime SetSoundAssetTime + { + get + { + return m_SetSoundAssetTime; + } + } + + /// + /// 播放声音。 + /// + public void Play() + { + m_SoundAgentHelper.Play(Constant.DefaultFadeInSeconds); + } + + /// + /// 播放声音。 + /// + /// 声音淡入时间,以秒为单位。 + public void Play(float fadeInSeconds) + { + m_SoundAgentHelper.Play(fadeInSeconds); + } + + /// + /// 停止播放声音。 + /// + public void Stop() + { + m_SoundAgentHelper.Stop(Constant.DefaultFadeOutSeconds); + } + + /// + /// 停止播放声音。 + /// + /// 声音淡出时间,以秒为单位。 + public void Stop(float fadeOutSeconds) + { + m_SoundAgentHelper.Stop(fadeOutSeconds); + } + + /// + /// 暂停播放声音。 + /// + public void Pause() + { + m_SoundAgentHelper.Pause(Constant.DefaultFadeOutSeconds); + } + + /// + /// 暂停播放声音。 + /// + /// 声音淡出时间,以秒为单位。 + public void Pause(float fadeOutSeconds) + { + m_SoundAgentHelper.Pause(fadeOutSeconds); + } + + /// + /// 恢复播放声音。 + /// + public void Resume() + { + m_SoundAgentHelper.Resume(Constant.DefaultFadeInSeconds); + } + + /// + /// 恢复播放声音。 + /// + /// 声音淡入时间,以秒为单位。 + public void Resume(float fadeInSeconds) + { + m_SoundAgentHelper.Resume(fadeInSeconds); + } + + /// + /// 重置声音代理。 + /// + public void Reset() + { + if (m_SoundAsset != null) + { + m_SoundHelper.ReleaseSoundAsset(m_SoundAsset); + m_SoundAsset = null; + } + + m_SetSoundAssetTime = DateTime.MinValue; + Time = Constant.DefaultTime; + MuteInSoundGroup = Constant.DefaultMute; + Loop = Constant.DefaultLoop; + Priority = Constant.DefaultPriority; + VolumeInSoundGroup = Constant.DefaultVolume; + Pitch = Constant.DefaultPitch; + PanStereo = Constant.DefaultPanStereo; + SpatialBlend = Constant.DefaultSpatialBlend; + MaxDistance = Constant.DefaultMaxDistance; + DopplerLevel = Constant.DefaultDopplerLevel; + m_SoundAgentHelper.Reset(); + } + + internal bool SetSoundAsset(object soundAsset) + { + Reset(); + m_SoundAsset = soundAsset; + m_SetSoundAssetTime = DateTime.UtcNow; + return m_SoundAgentHelper.SetSoundAsset(soundAsset); + } + + internal void RefreshMute() + { + m_SoundAgentHelper.Mute = m_SoundGroup.Mute || m_MuteInSoundGroup; + } + + internal void RefreshVolume() + { + m_SoundAgentHelper.Volume = m_SoundGroup.Volume * m_VolumeInSoundGroup; + } + + private void OnResetSoundAgent(object sender, ResetSoundAgentEventArgs e) + { + Reset(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.SoundAgent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.SoundAgent.cs.meta new file mode 100644 index 0000000..cf494bc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.SoundAgent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: adbc4a010dea15343a0f5cf0e94d7bb1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.SoundGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.SoundGroup.cs new file mode 100644 index 0000000..229a563 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.SoundGroup.cs @@ -0,0 +1,303 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.Sound +{ + internal sealed partial class SoundManager : GameFrameworkModule, ISoundManager + { + /// + /// 声音组。 + /// + private sealed class SoundGroup : ISoundGroup + { + private readonly string m_Name; + private readonly ISoundGroupHelper m_SoundGroupHelper; + private readonly List m_SoundAgents; + private bool m_AvoidBeingReplacedBySamePriority; + private bool m_Mute; + private float m_Volume; + + /// + /// 初始化声音组的新实例。 + /// + /// 声音组名称。 + /// 声音组辅助器。 + public SoundGroup(string name, ISoundGroupHelper soundGroupHelper) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("Sound group name is invalid."); + } + + if (soundGroupHelper == null) + { + throw new GameFrameworkException("Sound group helper is invalid."); + } + + m_Name = name; + m_SoundGroupHelper = soundGroupHelper; + m_SoundAgents = new List(); + } + + /// + /// 获取声音组名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取声音代理数。 + /// + public int SoundAgentCount + { + get + { + return m_SoundAgents.Count; + } + } + + /// + /// 获取或设置声音组中的声音是否避免被同优先级声音替换。 + /// + public bool AvoidBeingReplacedBySamePriority + { + get + { + return m_AvoidBeingReplacedBySamePriority; + } + set + { + m_AvoidBeingReplacedBySamePriority = value; + } + } + + /// + /// 获取或设置声音组静音。 + /// + public bool Mute + { + get + { + return m_Mute; + } + set + { + m_Mute = value; + foreach (SoundAgent soundAgent in m_SoundAgents) + { + soundAgent.RefreshMute(); + } + } + } + + /// + /// 获取或设置声音组音量。 + /// + public float Volume + { + get + { + return m_Volume; + } + set + { + m_Volume = value; + foreach (SoundAgent soundAgent in m_SoundAgents) + { + soundAgent.RefreshVolume(); + } + } + } + + /// + /// 获取声音组辅助器。 + /// + public ISoundGroupHelper Helper + { + get + { + return m_SoundGroupHelper; + } + } + + /// + /// 增加声音代理辅助器。 + /// + /// 声音辅助器接口。 + /// 要增加的声音代理辅助器。 + public void AddSoundAgentHelper(ISoundHelper soundHelper, ISoundAgentHelper soundAgentHelper) + { + m_SoundAgents.Add(new SoundAgent(this, soundHelper, soundAgentHelper)); + } + + /// + /// 播放声音。 + /// + /// 声音的序列编号。 + /// 声音资源。 + /// 播放声音参数。 + /// 错误码。 + /// 用于播放的声音代理。 + public ISoundAgent PlaySound(int serialId, object soundAsset, PlaySoundParams playSoundParams, out PlaySoundErrorCode? errorCode) + { + errorCode = null; + SoundAgent candidateAgent = null; + foreach (SoundAgent soundAgent in m_SoundAgents) + { + if (!soundAgent.IsPlaying) + { + candidateAgent = soundAgent; + break; + } + + if (soundAgent.Priority < playSoundParams.Priority) + { + if (candidateAgent == null || soundAgent.Priority < candidateAgent.Priority) + { + candidateAgent = soundAgent; + } + } + else if (!m_AvoidBeingReplacedBySamePriority && soundAgent.Priority == playSoundParams.Priority) + { + if (candidateAgent == null || soundAgent.SetSoundAssetTime < candidateAgent.SetSoundAssetTime) + { + candidateAgent = soundAgent; + } + } + } + + if (candidateAgent == null) + { + errorCode = PlaySoundErrorCode.IgnoredDueToLowPriority; + return null; + } + + if (!candidateAgent.SetSoundAsset(soundAsset)) + { + errorCode = PlaySoundErrorCode.SetSoundAssetFailure; + return null; + } + + candidateAgent.SerialId = serialId; + candidateAgent.Time = playSoundParams.Time; + candidateAgent.MuteInSoundGroup = playSoundParams.MuteInSoundGroup; + candidateAgent.Loop = playSoundParams.Loop; + candidateAgent.Priority = playSoundParams.Priority; + candidateAgent.VolumeInSoundGroup = playSoundParams.VolumeInSoundGroup; + candidateAgent.Pitch = playSoundParams.Pitch; + candidateAgent.PanStereo = playSoundParams.PanStereo; + candidateAgent.SpatialBlend = playSoundParams.SpatialBlend; + candidateAgent.MaxDistance = playSoundParams.MaxDistance; + candidateAgent.DopplerLevel = playSoundParams.DopplerLevel; + candidateAgent.Play(playSoundParams.FadeInSeconds); + return candidateAgent; + } + + /// + /// 停止播放声音。 + /// + /// 要停止播放声音的序列编号。 + /// 声音淡出时间,以秒为单位。 + /// 是否停止播放声音成功。 + public bool StopSound(int serialId, float fadeOutSeconds) + { + foreach (SoundAgent soundAgent in m_SoundAgents) + { + if (soundAgent.SerialId != serialId) + { + continue; + } + + soundAgent.Stop(fadeOutSeconds); + return true; + } + + return false; + } + + /// + /// 暂停播放声音。 + /// + /// 要暂停播放声音的序列编号。 + /// 声音淡出时间,以秒为单位。 + /// 是否暂停播放声音成功。 + public bool PauseSound(int serialId, float fadeOutSeconds) + { + foreach (SoundAgent soundAgent in m_SoundAgents) + { + if (soundAgent.SerialId != serialId) + { + continue; + } + + soundAgent.Pause(fadeOutSeconds); + return true; + } + + return false; + } + + /// + /// 恢复播放声音。 + /// + /// 要恢复播放声音的序列编号。 + /// 声音淡入时间,以秒为单位。 + /// 是否恢复播放声音成功。 + public bool ResumeSound(int serialId, float fadeInSeconds) + { + foreach (SoundAgent soundAgent in m_SoundAgents) + { + if (soundAgent.SerialId != serialId) + { + continue; + } + + soundAgent.Resume(fadeInSeconds); + return true; + } + + return false; + } + + /// + /// 停止所有已加载的声音。 + /// + public void StopAllLoadedSounds() + { + foreach (SoundAgent soundAgent in m_SoundAgents) + { + if (soundAgent.IsPlaying) + { + soundAgent.Stop(); + } + } + } + + /// + /// 停止所有已加载的声音。 + /// + /// 声音淡出时间,以秒为单位。 + public void StopAllLoadedSounds(float fadeOutSeconds) + { + foreach (SoundAgent soundAgent in m_SoundAgents) + { + if (soundAgent.IsPlaying) + { + soundAgent.Stop(fadeOutSeconds); + } + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.SoundGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.SoundGroup.cs.meta new file mode 100644 index 0000000..6471acc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.SoundGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c67bf707bde88ad4d863398b2246312c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.cs new file mode 100644 index 0000000..827bf89 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.cs @@ -0,0 +1,754 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System; +using System.Collections.Generic; + +namespace GameFramework.Sound +{ + /// + /// 声音管理器。 + /// + internal sealed partial class SoundManager : GameFrameworkModule, ISoundManager + { + private readonly Dictionary m_SoundGroups; + private readonly List m_SoundsBeingLoaded; + private readonly HashSet m_SoundsToReleaseOnLoad; + private readonly LoadAssetCallbacks m_LoadAssetCallbacks; + private IResourceManager m_ResourceManager; + private ISoundHelper m_SoundHelper; + private int m_Serial; + private EventHandler m_PlaySoundSuccessEventHandler; + private EventHandler m_PlaySoundFailureEventHandler; + private EventHandler m_PlaySoundUpdateEventHandler; + private EventHandler m_PlaySoundDependencyAssetEventHandler; + + /// + /// 初始化声音管理器的新实例。 + /// + public SoundManager() + { + m_SoundGroups = new Dictionary(StringComparer.Ordinal); + m_SoundsBeingLoaded = new List(); + m_SoundsToReleaseOnLoad = new HashSet(); + m_LoadAssetCallbacks = new LoadAssetCallbacks(LoadAssetSuccessCallback, LoadAssetFailureCallback, LoadAssetUpdateCallback, LoadAssetDependencyAssetCallback); + m_ResourceManager = null; + m_SoundHelper = null; + m_Serial = 0; + m_PlaySoundSuccessEventHandler = null; + m_PlaySoundFailureEventHandler = null; + m_PlaySoundUpdateEventHandler = null; + m_PlaySoundDependencyAssetEventHandler = null; + } + + /// + /// 获取声音组数量。 + /// + public int SoundGroupCount + { + get + { + return m_SoundGroups.Count; + } + } + + /// + /// 播放声音成功事件。 + /// + public event EventHandler PlaySoundSuccess + { + add + { + m_PlaySoundSuccessEventHandler += value; + } + remove + { + m_PlaySoundSuccessEventHandler -= value; + } + } + + /// + /// 播放声音失败事件。 + /// + public event EventHandler PlaySoundFailure + { + add + { + m_PlaySoundFailureEventHandler += value; + } + remove + { + m_PlaySoundFailureEventHandler -= value; + } + } + + /// + /// 播放声音更新事件。 + /// + public event EventHandler PlaySoundUpdate + { + add + { + m_PlaySoundUpdateEventHandler += value; + } + remove + { + m_PlaySoundUpdateEventHandler -= value; + } + } + + /// + /// 播放声音时加载依赖资源事件。 + /// + public event EventHandler PlaySoundDependencyAsset + { + add + { + m_PlaySoundDependencyAssetEventHandler += value; + } + remove + { + m_PlaySoundDependencyAssetEventHandler -= value; + } + } + + /// + /// 声音管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 关闭并清理声音管理器。 + /// + internal override void Shutdown() + { + StopAllLoadedSounds(); + m_SoundGroups.Clear(); + m_SoundsBeingLoaded.Clear(); + m_SoundsToReleaseOnLoad.Clear(); + } + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + public void SetResourceManager(IResourceManager resourceManager) + { + if (resourceManager == null) + { + throw new GameFrameworkException("Resource manager is invalid."); + } + + m_ResourceManager = resourceManager; + } + + /// + /// 设置声音辅助器。 + /// + /// 声音辅助器。 + public void SetSoundHelper(ISoundHelper soundHelper) + { + if (soundHelper == null) + { + throw new GameFrameworkException("Sound helper is invalid."); + } + + m_SoundHelper = soundHelper; + } + + /// + /// 是否存在指定声音组。 + /// + /// 声音组名称。 + /// 指定声音组是否存在。 + public bool HasSoundGroup(string soundGroupName) + { + if (string.IsNullOrEmpty(soundGroupName)) + { + throw new GameFrameworkException("Sound group name is invalid."); + } + + return m_SoundGroups.ContainsKey(soundGroupName); + } + + /// + /// 获取指定声音组。 + /// + /// 声音组名称。 + /// 要获取的声音组。 + public ISoundGroup GetSoundGroup(string soundGroupName) + { + if (string.IsNullOrEmpty(soundGroupName)) + { + throw new GameFrameworkException("Sound group name is invalid."); + } + + SoundGroup soundGroup = null; + if (m_SoundGroups.TryGetValue(soundGroupName, out soundGroup)) + { + return soundGroup; + } + + return null; + } + + /// + /// 获取所有声音组。 + /// + /// 所有声音组。 + public ISoundGroup[] GetAllSoundGroups() + { + int index = 0; + ISoundGroup[] results = new ISoundGroup[m_SoundGroups.Count]; + foreach (KeyValuePair soundGroup in m_SoundGroups) + { + results[index++] = soundGroup.Value; + } + + return results; + } + + /// + /// 获取所有声音组。 + /// + /// 所有声音组。 + public void GetAllSoundGroups(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair soundGroup in m_SoundGroups) + { + results.Add(soundGroup.Value); + } + } + + /// + /// 增加声音组。 + /// + /// 声音组名称。 + /// 声音组辅助器。 + /// 是否增加声音组成功。 + public bool AddSoundGroup(string soundGroupName, ISoundGroupHelper soundGroupHelper) + { + return AddSoundGroup(soundGroupName, false, Constant.DefaultMute, Constant.DefaultVolume, soundGroupHelper); + } + + /// + /// 增加声音组。 + /// + /// 声音组名称。 + /// 声音组中的声音是否避免被同优先级声音替换。 + /// 声音组是否静音。 + /// 声音组音量。 + /// 声音组辅助器。 + /// 是否增加声音组成功。 + public bool AddSoundGroup(string soundGroupName, bool soundGroupAvoidBeingReplacedBySamePriority, bool soundGroupMute, float soundGroupVolume, ISoundGroupHelper soundGroupHelper) + { + if (string.IsNullOrEmpty(soundGroupName)) + { + throw new GameFrameworkException("Sound group name is invalid."); + } + + if (soundGroupHelper == null) + { + throw new GameFrameworkException("Sound group helper is invalid."); + } + + if (HasSoundGroup(soundGroupName)) + { + return false; + } + + SoundGroup soundGroup = new SoundGroup(soundGroupName, soundGroupHelper) + { + AvoidBeingReplacedBySamePriority = soundGroupAvoidBeingReplacedBySamePriority, + Mute = soundGroupMute, + Volume = soundGroupVolume + }; + + m_SoundGroups.Add(soundGroupName, soundGroup); + + return true; + } + + /// + /// 增加声音代理辅助器。 + /// + /// 声音组名称。 + /// 要增加的声音代理辅助器。 + public void AddSoundAgentHelper(string soundGroupName, ISoundAgentHelper soundAgentHelper) + { + if (m_SoundHelper == null) + { + throw new GameFrameworkException("You must set sound helper first."); + } + + SoundGroup soundGroup = (SoundGroup)GetSoundGroup(soundGroupName); + if (soundGroup == null) + { + throw new GameFrameworkException(Utility.Text.Format("Sound group '{0}' is not exist.", soundGroupName)); + } + + soundGroup.AddSoundAgentHelper(m_SoundHelper, soundAgentHelper); + } + + /// + /// 获取所有正在加载声音的序列编号。 + /// + /// 所有正在加载声音的序列编号。 + public int[] GetAllLoadingSoundSerialIds() + { + return m_SoundsBeingLoaded.ToArray(); + } + + /// + /// 获取所有正在加载声音的序列编号。 + /// + /// 所有正在加载声音的序列编号。 + public void GetAllLoadingSoundSerialIds(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + results.AddRange(m_SoundsBeingLoaded); + } + + /// + /// 是否正在加载声音。 + /// + /// 声音序列编号。 + /// 是否正在加载声音。 + public bool IsLoadingSound(int serialId) + { + return m_SoundsBeingLoaded.Contains(serialId); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName) + { + return PlaySound(soundAssetName, soundGroupName, Resource.Constant.DefaultPriority, null, null); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, int priority) + { + return PlaySound(soundAssetName, soundGroupName, priority, null, null); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 播放声音参数。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams) + { + return PlaySound(soundAssetName, soundGroupName, Resource.Constant.DefaultPriority, playSoundParams, null); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 用户自定义数据。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, object userData) + { + return PlaySound(soundAssetName, soundGroupName, Resource.Constant.DefaultPriority, null, userData); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 播放声音参数。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams) + { + return PlaySound(soundAssetName, soundGroupName, priority, playSoundParams, null); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 用户自定义数据。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, int priority, object userData) + { + return PlaySound(soundAssetName, soundGroupName, priority, null, userData); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 播放声音参数。 + /// 用户自定义数据。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams, object userData) + { + return PlaySound(soundAssetName, soundGroupName, Resource.Constant.DefaultPriority, playSoundParams, userData); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 播放声音参数。 + /// 用户自定义数据。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams, object userData) + { + if (m_ResourceManager == null) + { + throw new GameFrameworkException("You must set resource manager first."); + } + + if (m_SoundHelper == null) + { + throw new GameFrameworkException("You must set sound helper first."); + } + + if (playSoundParams == null) + { + playSoundParams = PlaySoundParams.Create(); + } + + int serialId = ++m_Serial; + PlaySoundErrorCode? errorCode = null; + string errorMessage = null; + SoundGroup soundGroup = (SoundGroup)GetSoundGroup(soundGroupName); + if (soundGroup == null) + { + errorCode = PlaySoundErrorCode.SoundGroupNotExist; + errorMessage = Utility.Text.Format("Sound group '{0}' is not exist.", soundGroupName); + } + else if (soundGroup.SoundAgentCount <= 0) + { + errorCode = PlaySoundErrorCode.SoundGroupHasNoAgent; + errorMessage = Utility.Text.Format("Sound group '{0}' is have no sound agent.", soundGroupName); + } + + if (errorCode.HasValue) + { + if (m_PlaySoundFailureEventHandler != null) + { + PlaySoundFailureEventArgs playSoundFailureEventArgs = PlaySoundFailureEventArgs.Create(serialId, soundAssetName, soundGroupName, playSoundParams, errorCode.Value, errorMessage, userData); + m_PlaySoundFailureEventHandler(this, playSoundFailureEventArgs); + ReferencePool.Release(playSoundFailureEventArgs); + + if (playSoundParams.Referenced) + { + ReferencePool.Release(playSoundParams); + } + + return serialId; + } + + throw new GameFrameworkException(errorMessage); + } + + m_SoundsBeingLoaded.Add(serialId); + m_ResourceManager.LoadAsset(soundAssetName, priority, m_LoadAssetCallbacks, PlaySoundInfo.Create(serialId, soundGroup, playSoundParams, userData)); + return serialId; + } + + /// + /// 停止播放声音。 + /// + /// 要停止播放声音的序列编号。 + /// 是否停止播放声音成功。 + public bool StopSound(int serialId) + { + return StopSound(serialId, Constant.DefaultFadeOutSeconds); + } + + /// + /// 停止播放声音。 + /// + /// 要停止播放声音的序列编号。 + /// 声音淡出时间,以秒为单位。 + /// 是否停止播放声音成功。 + public bool StopSound(int serialId, float fadeOutSeconds) + { + if (IsLoadingSound(serialId)) + { + m_SoundsToReleaseOnLoad.Add(serialId); + m_SoundsBeingLoaded.Remove(serialId); + return true; + } + + foreach (KeyValuePair soundGroup in m_SoundGroups) + { + if (soundGroup.Value.StopSound(serialId, fadeOutSeconds)) + { + return true; + } + } + + return false; + } + + /// + /// 停止所有已加载的声音。 + /// + public void StopAllLoadedSounds() + { + StopAllLoadedSounds(Constant.DefaultFadeOutSeconds); + } + + /// + /// 停止所有已加载的声音。 + /// + /// 声音淡出时间,以秒为单位。 + public void StopAllLoadedSounds(float fadeOutSeconds) + { + foreach (KeyValuePair soundGroup in m_SoundGroups) + { + soundGroup.Value.StopAllLoadedSounds(fadeOutSeconds); + } + } + + /// + /// 停止所有正在加载的声音。 + /// + public void StopAllLoadingSounds() + { + foreach (int serialId in m_SoundsBeingLoaded) + { + m_SoundsToReleaseOnLoad.Add(serialId); + } + } + + /// + /// 暂停播放声音。 + /// + /// 要暂停播放声音的序列编号。 + public void PauseSound(int serialId) + { + PauseSound(serialId, Constant.DefaultFadeOutSeconds); + } + + /// + /// 暂停播放声音。 + /// + /// 要暂停播放声音的序列编号。 + /// 声音淡出时间,以秒为单位。 + public void PauseSound(int serialId, float fadeOutSeconds) + { + foreach (KeyValuePair soundGroup in m_SoundGroups) + { + if (soundGroup.Value.PauseSound(serialId, fadeOutSeconds)) + { + return; + } + } + + throw new GameFrameworkException(Utility.Text.Format("Can not find sound '{0}'.", serialId)); + } + + /// + /// 恢复播放声音。 + /// + /// 要恢复播放声音的序列编号。 + public void ResumeSound(int serialId) + { + ResumeSound(serialId, Constant.DefaultFadeInSeconds); + } + + /// + /// 恢复播放声音。 + /// + /// 要恢复播放声音的序列编号。 + /// 声音淡入时间,以秒为单位。 + public void ResumeSound(int serialId, float fadeInSeconds) + { + foreach (KeyValuePair soundGroup in m_SoundGroups) + { + if (soundGroup.Value.ResumeSound(serialId, fadeInSeconds)) + { + return; + } + } + + throw new GameFrameworkException(Utility.Text.Format("Can not find sound '{0}'.", serialId)); + } + + private void LoadAssetSuccessCallback(string soundAssetName, object soundAsset, float duration, object userData) + { + PlaySoundInfo playSoundInfo = (PlaySoundInfo)userData; + if (playSoundInfo == null) + { + throw new GameFrameworkException("Play sound info is invalid."); + } + + if (m_SoundsToReleaseOnLoad.Contains(playSoundInfo.SerialId)) + { + m_SoundsToReleaseOnLoad.Remove(playSoundInfo.SerialId); + if (playSoundInfo.PlaySoundParams.Referenced) + { + ReferencePool.Release(playSoundInfo.PlaySoundParams); + } + + ReferencePool.Release(playSoundInfo); + m_SoundHelper.ReleaseSoundAsset(soundAsset); + return; + } + + m_SoundsBeingLoaded.Remove(playSoundInfo.SerialId); + + PlaySoundErrorCode? errorCode = null; + ISoundAgent soundAgent = playSoundInfo.SoundGroup.PlaySound(playSoundInfo.SerialId, soundAsset, playSoundInfo.PlaySoundParams, out errorCode); + if (soundAgent != null) + { + if (m_PlaySoundSuccessEventHandler != null) + { + PlaySoundSuccessEventArgs playSoundSuccessEventArgs = PlaySoundSuccessEventArgs.Create(playSoundInfo.SerialId, soundAssetName, soundAgent, duration, playSoundInfo.UserData); + m_PlaySoundSuccessEventHandler(this, playSoundSuccessEventArgs); + ReferencePool.Release(playSoundSuccessEventArgs); + } + + if (playSoundInfo.PlaySoundParams.Referenced) + { + ReferencePool.Release(playSoundInfo.PlaySoundParams); + } + + ReferencePool.Release(playSoundInfo); + return; + } + + m_SoundsToReleaseOnLoad.Remove(playSoundInfo.SerialId); + m_SoundHelper.ReleaseSoundAsset(soundAsset); + string errorMessage = Utility.Text.Format("Sound group '{0}' play sound '{1}' failure.", playSoundInfo.SoundGroup.Name, soundAssetName); + if (m_PlaySoundFailureEventHandler != null) + { + PlaySoundFailureEventArgs playSoundFailureEventArgs = PlaySoundFailureEventArgs.Create(playSoundInfo.SerialId, soundAssetName, playSoundInfo.SoundGroup.Name, playSoundInfo.PlaySoundParams, errorCode.Value, errorMessage, playSoundInfo.UserData); + m_PlaySoundFailureEventHandler(this, playSoundFailureEventArgs); + ReferencePool.Release(playSoundFailureEventArgs); + + if (playSoundInfo.PlaySoundParams.Referenced) + { + ReferencePool.Release(playSoundInfo.PlaySoundParams); + } + + ReferencePool.Release(playSoundInfo); + return; + } + + if (playSoundInfo.PlaySoundParams.Referenced) + { + ReferencePool.Release(playSoundInfo.PlaySoundParams); + } + + ReferencePool.Release(playSoundInfo); + throw new GameFrameworkException(errorMessage); + } + + private void LoadAssetFailureCallback(string soundAssetName, LoadResourceStatus status, string errorMessage, object userData) + { + PlaySoundInfo playSoundInfo = (PlaySoundInfo)userData; + if (playSoundInfo == null) + { + throw new GameFrameworkException("Play sound info is invalid."); + } + + if (m_SoundsToReleaseOnLoad.Contains(playSoundInfo.SerialId)) + { + m_SoundsToReleaseOnLoad.Remove(playSoundInfo.SerialId); + if (playSoundInfo.PlaySoundParams.Referenced) + { + ReferencePool.Release(playSoundInfo.PlaySoundParams); + } + + return; + } + + m_SoundsBeingLoaded.Remove(playSoundInfo.SerialId); + string appendErrorMessage = Utility.Text.Format("Load sound failure, asset name '{0}', status '{1}', error message '{2}'.", soundAssetName, status, errorMessage); + if (m_PlaySoundFailureEventHandler != null) + { + PlaySoundFailureEventArgs playSoundFailureEventArgs = PlaySoundFailureEventArgs.Create(playSoundInfo.SerialId, soundAssetName, playSoundInfo.SoundGroup.Name, playSoundInfo.PlaySoundParams, PlaySoundErrorCode.LoadAssetFailure, appendErrorMessage, playSoundInfo.UserData); + m_PlaySoundFailureEventHandler(this, playSoundFailureEventArgs); + ReferencePool.Release(playSoundFailureEventArgs); + + if (playSoundInfo.PlaySoundParams.Referenced) + { + ReferencePool.Release(playSoundInfo.PlaySoundParams); + } + + return; + } + + throw new GameFrameworkException(appendErrorMessage); + } + + private void LoadAssetUpdateCallback(string soundAssetName, float progress, object userData) + { + PlaySoundInfo playSoundInfo = (PlaySoundInfo)userData; + if (playSoundInfo == null) + { + throw new GameFrameworkException("Play sound info is invalid."); + } + + if (m_PlaySoundUpdateEventHandler != null) + { + PlaySoundUpdateEventArgs playSoundUpdateEventArgs = PlaySoundUpdateEventArgs.Create(playSoundInfo.SerialId, soundAssetName, playSoundInfo.SoundGroup.Name, playSoundInfo.PlaySoundParams, progress, playSoundInfo.UserData); + m_PlaySoundUpdateEventHandler(this, playSoundUpdateEventArgs); + ReferencePool.Release(playSoundUpdateEventArgs); + } + } + + private void LoadAssetDependencyAssetCallback(string soundAssetName, string dependencyAssetName, int loadedCount, int totalCount, object userData) + { + PlaySoundInfo playSoundInfo = (PlaySoundInfo)userData; + if (playSoundInfo == null) + { + throw new GameFrameworkException("Play sound info is invalid."); + } + + if (m_PlaySoundDependencyAssetEventHandler != null) + { + PlaySoundDependencyAssetEventArgs playSoundDependencyAssetEventArgs = PlaySoundDependencyAssetEventArgs.Create(playSoundInfo.SerialId, soundAssetName, playSoundInfo.SoundGroup.Name, playSoundInfo.PlaySoundParams, dependencyAssetName, loadedCount, totalCount, playSoundInfo.UserData); + m_PlaySoundDependencyAssetEventHandler(this, playSoundDependencyAssetEventArgs); + ReferencePool.Release(playSoundDependencyAssetEventArgs); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.cs.meta new file mode 100644 index 0000000..204a2ec --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Sound/SoundManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2820687499b14b346b37072be05c629c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI.meta new file mode 100644 index 0000000..d0946a6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4a77a3c43498445439b3e47be9042f7e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/CloseUIFormCompleteEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/CloseUIFormCompleteEventArgs.cs new file mode 100644 index 0000000..f1a4661 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/CloseUIFormCompleteEventArgs.cs @@ -0,0 +1,91 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.UI +{ + /// + /// 关闭界面完成事件。 + /// + public sealed class CloseUIFormCompleteEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化关闭界面完成事件的新实例。 + /// + public CloseUIFormCompleteEventArgs() + { + SerialId = 0; + UIFormAssetName = null; + UIGroup = null; + UserData = null; + } + + /// + /// 获取界面序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取界面资源名称。 + /// + public string UIFormAssetName + { + get; + private set; + } + + /// + /// 获取界面所属的界面组。 + /// + public IUIGroup UIGroup + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建关闭界面完成事件。 + /// + /// 界面序列编号。 + /// 界面资源名称。 + /// 界面所属的界面组。 + /// 用户自定义数据。 + /// 创建的关闭界面完成事件。 + public static CloseUIFormCompleteEventArgs Create(int serialId, string uiFormAssetName, IUIGroup uiGroup, object userData) + { + CloseUIFormCompleteEventArgs closeUIFormCompleteEventArgs = ReferencePool.Acquire(); + closeUIFormCompleteEventArgs.SerialId = serialId; + closeUIFormCompleteEventArgs.UIFormAssetName = uiFormAssetName; + closeUIFormCompleteEventArgs.UIGroup = uiGroup; + closeUIFormCompleteEventArgs.UserData = userData; + return closeUIFormCompleteEventArgs; + } + + /// + /// 清理关闭界面完成事件。 + /// + public override void Clear() + { + SerialId = 0; + UIFormAssetName = null; + UIGroup = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/CloseUIFormCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/CloseUIFormCompleteEventArgs.cs.meta new file mode 100644 index 0000000..6e9dd75 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/CloseUIFormCompleteEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5cbf3474e96359d4b99fdebabb685881 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIForm.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIForm.cs new file mode 100644 index 0000000..3be19e1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIForm.cs @@ -0,0 +1,132 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.UI +{ + /// + /// 界面接口。 + /// + public interface IUIForm + { + /// + /// 获取界面序列编号。 + /// + int SerialId + { + get; + } + + /// + /// 获取界面资源名称。 + /// + string UIFormAssetName + { + get; + } + + /// + /// 获取界面实例。 + /// + object Handle + { + get; + } + + /// + /// 获取界面所属的界面组。 + /// + IUIGroup UIGroup + { + get; + } + + /// + /// 获取界面在界面组中的深度。 + /// + int DepthInUIGroup + { + get; + } + + /// + /// 获取是否暂停被覆盖的界面。 + /// + bool PauseCoveredUIForm + { + get; + } + + /// + /// 初始化界面。 + /// + /// 界面序列编号。 + /// 界面资源名称。 + /// 界面所属的界面组。 + /// 是否暂停被覆盖的界面。 + /// 是否是新实例。 + /// 用户自定义数据。 + void OnInit(int serialId, string uiFormAssetName, IUIGroup uiGroup, bool pauseCoveredUIForm, bool isNewInstance, object userData); + + /// + /// 界面回收。 + /// + void OnRecycle(); + + /// + /// 界面打开。 + /// + /// 用户自定义数据。 + void OnOpen(object userData); + + /// + /// 界面关闭。 + /// + /// 是否是关闭界面管理器时触发。 + /// 用户自定义数据。 + void OnClose(bool isShutdown, object userData); + + /// + /// 界面暂停。 + /// + void OnPause(); + + /// + /// 界面暂停恢复。 + /// + void OnResume(); + + /// + /// 界面遮挡。 + /// + void OnCover(); + + /// + /// 界面遮挡恢复。 + /// + void OnReveal(); + + /// + /// 界面激活。 + /// + /// 用户自定义数据。 + void OnRefocus(object userData); + + /// + /// 界面轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + void OnUpdate(float elapseSeconds, float realElapseSeconds); + + /// + /// 界面深度改变。 + /// + /// 界面组深度。 + /// 界面在界面组中的深度。 + void OnDepthChanged(int uiGroupDepth, int depthInUIGroup); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIForm.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIForm.cs.meta new file mode 100644 index 0000000..367270b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIForm.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4a860fa2f69283745a496a1082b1f2d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIFormHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIFormHelper.cs new file mode 100644 index 0000000..6362107 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIFormHelper.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.UI +{ + /// + /// 界面辅助器接口。 + /// + public interface IUIFormHelper + { + /// + /// 实例化界面。 + /// + /// 要实例化的界面资源。 + /// 实例化后的界面。 + object InstantiateUIForm(object uiFormAsset); + + /// + /// 创建界面。 + /// + /// 界面实例。 + /// 界面所属的界面组。 + /// 用户自定义数据。 + /// 界面。 + IUIForm CreateUIForm(object uiFormInstance, IUIGroup uiGroup, object userData); + + /// + /// 释放界面。 + /// + /// 要释放的界面资源。 + /// 要释放的界面实例。 + void ReleaseUIForm(object uiFormAsset, object uiFormInstance); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIFormHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIFormHelper.cs.meta new file mode 100644 index 0000000..c33a058 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIFormHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 18d585b155a36234f9b30fa4140918c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIGroup.cs new file mode 100644 index 0000000..a2a04db --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIGroup.cs @@ -0,0 +1,121 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.UI +{ + /// + /// 界面组接口。 + /// + public interface IUIGroup + { + /// + /// 获取界面组名称。 + /// + string Name + { + get; + } + + /// + /// 获取或设置界面组深度。 + /// + int Depth + { + get; + set; + } + + /// + /// 获取或设置界面组是否暂停。 + /// + bool Pause + { + get; + set; + } + + /// + /// 获取界面组中界面数量。 + /// + int UIFormCount + { + get; + } + + /// + /// 获取当前界面。 + /// + IUIForm CurrentUIForm + { + get; + } + + /// + /// 获取界面组辅助器。 + /// + IUIGroupHelper Helper + { + get; + } + + /// + /// 界面组中是否存在界面。 + /// + /// 界面序列编号。 + /// 界面组中是否存在界面。 + bool HasUIForm(int serialId); + + /// + /// 界面组中是否存在界面。 + /// + /// 界面资源名称。 + /// 界面组中是否存在界面。 + bool HasUIForm(string uiFormAssetName); + + /// + /// 从界面组中获取界面。 + /// + /// 界面序列编号。 + /// 要获取的界面。 + IUIForm GetUIForm(int serialId); + + /// + /// 从界面组中获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + IUIForm GetUIForm(string uiFormAssetName); + + /// + /// 从界面组中获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + IUIForm[] GetUIForms(string uiFormAssetName); + + /// + /// 从界面组中获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + void GetUIForms(string uiFormAssetName, List results); + + /// + /// 从界面组中获取所有界面。 + /// + /// 界面组中的所有界面。 + IUIForm[] GetAllUIForms(); + + /// + /// 从界面组中获取所有界面。 + /// + /// 界面组中的所有界面。 + void GetAllUIForms(List results); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIGroup.cs.meta new file mode 100644 index 0000000..d6ab36c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2322522491c53b64b8eb5d74643dbbdd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIGroupHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIGroupHelper.cs new file mode 100644 index 0000000..f3ba600 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIGroupHelper.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.UI +{ + /// + /// 界面组辅助器接口。 + /// + public interface IUIGroupHelper + { + /// + /// 设置界面组深度。 + /// + /// 界面组深度。 + void SetDepth(int depth); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIGroupHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIGroupHelper.cs.meta new file mode 100644 index 0000000..27b3c4a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIGroupHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fd7688a03213482438d4e366309f9131 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIManager.cs new file mode 100644 index 0000000..c0d213b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIManager.cs @@ -0,0 +1,382 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.ObjectPool; +using GameFramework.Resource; +using System; +using System.Collections.Generic; + +namespace GameFramework.UI +{ + /// + /// 界面管理器接口。 + /// + public interface IUIManager + { + /// + /// 获取界面组数量。 + /// + int UIGroupCount + { + get; + } + + /// + /// 获取或设置界面实例对象池自动释放可释放对象的间隔秒数。 + /// + float InstanceAutoReleaseInterval + { + get; + set; + } + + /// + /// 获取或设置界面实例对象池的容量。 + /// + int InstanceCapacity + { + get; + set; + } + + /// + /// 获取或设置界面实例对象池对象过期秒数。 + /// + float InstanceExpireTime + { + get; + set; + } + + /// + /// 获取或设置界面实例对象池的优先级。 + /// + int InstancePriority + { + get; + set; + } + + /// + /// 打开界面成功事件。 + /// + event EventHandler OpenUIFormSuccess; + + /// + /// 打开界面失败事件。 + /// + event EventHandler OpenUIFormFailure; + + /// + /// 打开界面更新事件。 + /// + event EventHandler OpenUIFormUpdate; + + /// + /// 打开界面时加载依赖资源事件。 + /// + event EventHandler OpenUIFormDependencyAsset; + + /// + /// 关闭界面完成事件。 + /// + event EventHandler CloseUIFormComplete; + + /// + /// 设置对象池管理器。 + /// + /// 对象池管理器。 + void SetObjectPoolManager(IObjectPoolManager objectPoolManager); + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + void SetResourceManager(IResourceManager resourceManager); + + /// + /// 设置界面辅助器。 + /// + /// 界面辅助器。 + void SetUIFormHelper(IUIFormHelper uiFormHelper); + + /// + /// 是否存在界面组。 + /// + /// 界面组名称。 + /// 是否存在界面组。 + bool HasUIGroup(string uiGroupName); + + /// + /// 获取界面组。 + /// + /// 界面组名称。 + /// 要获取的界面组。 + IUIGroup GetUIGroup(string uiGroupName); + + /// + /// 获取所有界面组。 + /// + /// 所有界面组。 + IUIGroup[] GetAllUIGroups(); + + /// + /// 获取所有界面组。 + /// + /// 所有界面组。 + void GetAllUIGroups(List results); + + /// + /// 增加界面组。 + /// + /// 界面组名称。 + /// 界面组辅助器。 + /// 是否增加界面组成功。 + bool AddUIGroup(string uiGroupName, IUIGroupHelper uiGroupHelper); + + /// + /// 增加界面组。 + /// + /// 界面组名称。 + /// 界面组深度。 + /// 界面组辅助器。 + /// 是否增加界面组成功。 + bool AddUIGroup(string uiGroupName, int uiGroupDepth, IUIGroupHelper uiGroupHelper); + + /// + /// 是否存在界面。 + /// + /// 界面序列编号。 + /// 是否存在界面。 + bool HasUIForm(int serialId); + + /// + /// 是否存在界面。 + /// + /// 界面资源名称。 + /// 是否存在界面。 + bool HasUIForm(string uiFormAssetName); + + /// + /// 获取界面。 + /// + /// 界面序列编号。 + /// 要获取的界面。 + IUIForm GetUIForm(int serialId); + + /// + /// 获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + IUIForm GetUIForm(string uiFormAssetName); + + /// + /// 获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + IUIForm[] GetUIForms(string uiFormAssetName); + + /// + /// 获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + void GetUIForms(string uiFormAssetName, List results); + + /// + /// 获取所有已加载的界面。 + /// + /// 所有已加载的界面。 + IUIForm[] GetAllLoadedUIForms(); + + /// + /// 获取所有已加载的界面。 + /// + /// 所有已加载的界面。 + void GetAllLoadedUIForms(List results); + + /// + /// 获取所有正在加载界面的序列编号。 + /// + /// 所有正在加载界面的序列编号。 + int[] GetAllLoadingUIFormSerialIds(); + + /// + /// 获取所有正在加载界面的序列编号。 + /// + /// 所有正在加载界面的序列编号。 + void GetAllLoadingUIFormSerialIds(List results); + + /// + /// 是否正在加载界面。 + /// + /// 界面序列编号。 + /// 是否正在加载界面。 + bool IsLoadingUIForm(int serialId); + + /// + /// 是否正在加载界面。 + /// + /// 界面资源名称。 + /// 是否正在加载界面。 + bool IsLoadingUIForm(string uiFormAssetName); + + /// + /// 是否是合法的界面。 + /// + /// 界面。 + /// 界面是否合法。 + bool IsValidUIForm(IUIForm uiForm); + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 界面的序列编号。 + int OpenUIForm(string uiFormAssetName, string uiGroupName); + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 加载界面资源的优先级。 + /// 界面的序列编号。 + int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority); + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 是否暂停被覆盖的界面。 + /// 界面的序列编号。 + int OpenUIForm(string uiFormAssetName, string uiGroupName, bool pauseCoveredUIForm); + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 用户自定义数据。 + /// 界面的序列编号。 + int OpenUIForm(string uiFormAssetName, string uiGroupName, object userData); + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 加载界面资源的优先级。 + /// 是否暂停被覆盖的界面。 + /// 界面的序列编号。 + int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, bool pauseCoveredUIForm); + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 加载界面资源的优先级。 + /// 用户自定义数据。 + /// 界面的序列编号。 + int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, object userData); + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 是否暂停被覆盖的界面。 + /// 用户自定义数据。 + /// 界面的序列编号。 + int OpenUIForm(string uiFormAssetName, string uiGroupName, bool pauseCoveredUIForm, object userData); + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 加载界面资源的优先级。 + /// 是否暂停被覆盖的界面。 + /// 用户自定义数据。 + /// 界面的序列编号。 + int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, bool pauseCoveredUIForm, object userData); + + /// + /// 关闭界面。 + /// + /// 要关闭界面的序列编号。 + void CloseUIForm(int serialId); + + /// + /// 关闭界面。 + /// + /// 要关闭界面的序列编号。 + /// 用户自定义数据。 + void CloseUIForm(int serialId, object userData); + + /// + /// 关闭界面。 + /// + /// 要关闭的界面。 + void CloseUIForm(IUIForm uiForm); + + /// + /// 关闭界面。 + /// + /// 要关闭的界面。 + /// 用户自定义数据。 + void CloseUIForm(IUIForm uiForm, object userData); + + /// + /// 关闭所有已加载的界面。 + /// + void CloseAllLoadedUIForms(); + + /// + /// 关闭所有已加载的界面。 + /// + /// 用户自定义数据。 + void CloseAllLoadedUIForms(object userData); + + /// + /// 关闭所有正在加载的界面。 + /// + void CloseAllLoadingUIForms(); + + /// + /// 激活界面。 + /// + /// 要激活的界面。 + void RefocusUIForm(IUIForm uiForm); + + /// + /// 激活界面。 + /// + /// 要激活的界面。 + /// 用户自定义数据。 + void RefocusUIForm(IUIForm uiForm, object userData); + + /// + /// 设置界面实例是否被加锁。 + /// + /// 要设置是否被加锁的界面实例。 + /// 界面实例是否被加锁。 + void SetUIFormInstanceLocked(object uiFormInstance, bool locked); + + /// + /// 设置界面实例的优先级。 + /// + /// 要设置优先级的界面实例。 + /// 界面实例优先级。 + void SetUIFormInstancePriority(object uiFormInstance, int priority); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIManager.cs.meta new file mode 100644 index 0000000..3553eba --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/IUIManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 26b7d8cac1c122a499874e612f6fbddc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormDependencyAssetEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormDependencyAssetEventArgs.cs new file mode 100644 index 0000000..0a483c5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormDependencyAssetEventArgs.cs @@ -0,0 +1,143 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.UI +{ + /// + /// 打开界面时加载依赖资源事件。 + /// + public sealed class OpenUIFormDependencyAssetEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化打开界面时加载依赖资源事件的新实例。 + /// + public OpenUIFormDependencyAssetEventArgs() + { + SerialId = 0; + UIFormAssetName = null; + UIGroupName = null; + PauseCoveredUIForm = false; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + + /// + /// 获取界面序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取界面资源名称。 + /// + public string UIFormAssetName + { + get; + private set; + } + + /// + /// 获取界面组名称。 + /// + public string UIGroupName + { + get; + private set; + } + + /// + /// 获取是否暂停被覆盖的界面。 + /// + public bool PauseCoveredUIForm + { + get; + private set; + } + + /// + /// 获取被加载的依赖资源名称。 + /// + public string DependencyAssetName + { + get; + private set; + } + + /// + /// 获取当前已加载依赖资源数量。 + /// + public int LoadedCount + { + get; + private set; + } + + /// + /// 获取总共加载依赖资源数量。 + /// + public int TotalCount + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建打开界面时加载依赖资源事件。 + /// + /// 界面序列编号。 + /// 界面资源名称。 + /// 界面组名称。 + /// 是否暂停被覆盖的界面。 + /// 被加载的依赖资源名称。 + /// 当前已加载依赖资源数量。 + /// 总共加载依赖资源数量。 + /// 用户自定义数据。 + /// 创建的打开界面时加载依赖资源事件。 + public static OpenUIFormDependencyAssetEventArgs Create(int serialId, string uiFormAssetName, string uiGroupName, bool pauseCoveredUIForm, string dependencyAssetName, int loadedCount, int totalCount, object userData) + { + OpenUIFormDependencyAssetEventArgs openUIFormDependencyAssetEventArgs = ReferencePool.Acquire(); + openUIFormDependencyAssetEventArgs.SerialId = serialId; + openUIFormDependencyAssetEventArgs.UIFormAssetName = uiFormAssetName; + openUIFormDependencyAssetEventArgs.UIGroupName = uiGroupName; + openUIFormDependencyAssetEventArgs.PauseCoveredUIForm = pauseCoveredUIForm; + openUIFormDependencyAssetEventArgs.DependencyAssetName = dependencyAssetName; + openUIFormDependencyAssetEventArgs.LoadedCount = loadedCount; + openUIFormDependencyAssetEventArgs.TotalCount = totalCount; + openUIFormDependencyAssetEventArgs.UserData = userData; + return openUIFormDependencyAssetEventArgs; + } + + /// + /// 清理打开界面时加载依赖资源事件。 + /// + public override void Clear() + { + SerialId = 0; + UIFormAssetName = null; + UIGroupName = null; + PauseCoveredUIForm = false; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormDependencyAssetEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormDependencyAssetEventArgs.cs.meta new file mode 100644 index 0000000..e4494f7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormDependencyAssetEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4b9f70354d8cdf04dac55cb6c02df75b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormFailureEventArgs.cs new file mode 100644 index 0000000..824eef4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormFailureEventArgs.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.UI +{ + /// + /// 打开界面失败事件。 + /// + public sealed class OpenUIFormFailureEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化打开界面失败事件的新实例。 + /// + public OpenUIFormFailureEventArgs() + { + SerialId = 0; + UIFormAssetName = null; + UIGroupName = null; + PauseCoveredUIForm = false; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取界面序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取界面资源名称。 + /// + public string UIFormAssetName + { + get; + private set; + } + + /// + /// 获取界面组名称。 + /// + public string UIGroupName + { + get; + private set; + } + + /// + /// 获取是否暂停被覆盖的界面。 + /// + public bool PauseCoveredUIForm + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建打开界面失败事件。 + /// + /// 界面序列编号。 + /// 界面资源名称。 + /// 界面组名称。 + /// 是否暂停被覆盖的界面。 + /// 错误信息。 + /// 用户自定义数据。 + /// 创建的打开界面失败事件。 + public static OpenUIFormFailureEventArgs Create(int serialId, string uiFormAssetName, string uiGroupName, bool pauseCoveredUIForm, string errorMessage, object userData) + { + OpenUIFormFailureEventArgs openUIFormFailureEventArgs = ReferencePool.Acquire(); + openUIFormFailureEventArgs.SerialId = serialId; + openUIFormFailureEventArgs.UIFormAssetName = uiFormAssetName; + openUIFormFailureEventArgs.UIGroupName = uiGroupName; + openUIFormFailureEventArgs.PauseCoveredUIForm = pauseCoveredUIForm; + openUIFormFailureEventArgs.ErrorMessage = errorMessage; + openUIFormFailureEventArgs.UserData = userData; + return openUIFormFailureEventArgs; + } + + /// + /// 清理打开界面失败事件。 + /// + public override void Clear() + { + SerialId = 0; + UIFormAssetName = null; + UIGroupName = null; + PauseCoveredUIForm = false; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormFailureEventArgs.cs.meta new file mode 100644 index 0000000..c1199d9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 06dcc8caa7a2f034792b508ed67216f5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormSuccessEventArgs.cs new file mode 100644 index 0000000..77fa499 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormSuccessEventArgs.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.UI +{ + /// + /// 打开界面成功事件。 + /// + public sealed class OpenUIFormSuccessEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化打开界面成功事件的新实例。 + /// + public OpenUIFormSuccessEventArgs() + { + UIForm = null; + Duration = 0f; + UserData = null; + } + + /// + /// 获取打开成功的界面。 + /// + public IUIForm UIForm + { + get; + private set; + } + + /// + /// 获取加载持续时间。 + /// + public float Duration + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建打开界面成功事件。 + /// + /// 加载成功的界面。 + /// 加载持续时间。 + /// 用户自定义数据。 + /// 创建的打开界面成功事件。 + public static OpenUIFormSuccessEventArgs Create(IUIForm uiForm, float duration, object userData) + { + OpenUIFormSuccessEventArgs openUIFormSuccessEventArgs = ReferencePool.Acquire(); + openUIFormSuccessEventArgs.UIForm = uiForm; + openUIFormSuccessEventArgs.Duration = duration; + openUIFormSuccessEventArgs.UserData = userData; + return openUIFormSuccessEventArgs; + } + + /// + /// 清理打开界面成功事件。 + /// + public override void Clear() + { + UIForm = null; + Duration = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormSuccessEventArgs.cs.meta new file mode 100644 index 0000000..569d698 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 86756e33468c70042abe51b28effe2f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormUpdateEventArgs.cs new file mode 100644 index 0000000..70704e4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormUpdateEventArgs.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.UI +{ + /// + /// 打开界面更新事件。 + /// + public sealed class OpenUIFormUpdateEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化打开界面更新事件的新实例。 + /// + public OpenUIFormUpdateEventArgs() + { + SerialId = 0; + UIFormAssetName = null; + UIGroupName = null; + PauseCoveredUIForm = false; + Progress = 0f; + UserData = null; + } + + /// + /// 获取界面序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取界面资源名称。 + /// + public string UIFormAssetName + { + get; + private set; + } + + /// + /// 获取界面组名称。 + /// + public string UIGroupName + { + get; + private set; + } + + /// + /// 获取是否暂停被覆盖的界面。 + /// + public bool PauseCoveredUIForm + { + get; + private set; + } + + /// + /// 获取打开界面进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建打开界面更新事件。 + /// + /// 界面序列编号。 + /// 界面资源名称。 + /// 界面组名称。 + /// 是否暂停被覆盖的界面。 + /// 打开界面进度。 + /// 用户自定义数据。 + /// 创建的打开界面更新事件。 + public static OpenUIFormUpdateEventArgs Create(int serialId, string uiFormAssetName, string uiGroupName, bool pauseCoveredUIForm, float progress, object userData) + { + OpenUIFormUpdateEventArgs openUIFormUpdateEventArgs = ReferencePool.Acquire(); + openUIFormUpdateEventArgs.SerialId = serialId; + openUIFormUpdateEventArgs.UIFormAssetName = uiFormAssetName; + openUIFormUpdateEventArgs.UIGroupName = uiGroupName; + openUIFormUpdateEventArgs.PauseCoveredUIForm = pauseCoveredUIForm; + openUIFormUpdateEventArgs.Progress = progress; + openUIFormUpdateEventArgs.UserData = userData; + return openUIFormUpdateEventArgs; + } + + /// + /// 清理打开界面更新事件。 + /// + public override void Clear() + { + SerialId = 0; + UIFormAssetName = null; + UIGroupName = null; + PauseCoveredUIForm = false; + Progress = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormUpdateEventArgs.cs.meta new file mode 100644 index 0000000..0b31314 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/OpenUIFormUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef637eba3eeecdb4a93135f2c922e4ce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.OpenUIFormInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.OpenUIFormInfo.cs new file mode 100644 index 0000000..c942aa5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.OpenUIFormInfo.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.UI +{ + internal sealed partial class UIManager : GameFrameworkModule, IUIManager + { + private sealed class OpenUIFormInfo : IReference + { + private int m_SerialId; + private UIGroup m_UIGroup; + private bool m_PauseCoveredUIForm; + private object m_UserData; + + public OpenUIFormInfo() + { + m_SerialId = 0; + m_UIGroup = null; + m_PauseCoveredUIForm = false; + m_UserData = null; + } + + public int SerialId + { + get + { + return m_SerialId; + } + } + + public UIGroup UIGroup + { + get + { + return m_UIGroup; + } + } + + public bool PauseCoveredUIForm + { + get + { + return m_PauseCoveredUIForm; + } + } + + public object UserData + { + get + { + return m_UserData; + } + } + + public static OpenUIFormInfo Create(int serialId, UIGroup uiGroup, bool pauseCoveredUIForm, object userData) + { + OpenUIFormInfo openUIFormInfo = ReferencePool.Acquire(); + openUIFormInfo.m_SerialId = serialId; + openUIFormInfo.m_UIGroup = uiGroup; + openUIFormInfo.m_PauseCoveredUIForm = pauseCoveredUIForm; + openUIFormInfo.m_UserData = userData; + return openUIFormInfo; + } + + public void Clear() + { + m_SerialId = 0; + m_UIGroup = null; + m_PauseCoveredUIForm = false; + m_UserData = null; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.OpenUIFormInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.OpenUIFormInfo.cs.meta new file mode 100644 index 0000000..1c7c7a7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.OpenUIFormInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 28687acea4a54464b8ca73baed244186 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIFormInstanceObject.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIFormInstanceObject.cs new file mode 100644 index 0000000..0436c88 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIFormInstanceObject.cs @@ -0,0 +1,60 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.ObjectPool; + +namespace GameFramework.UI +{ + internal sealed partial class UIManager : GameFrameworkModule, IUIManager + { + /// + /// 界面实例对象。 + /// + private sealed class UIFormInstanceObject : ObjectBase + { + private object m_UIFormAsset; + private IUIFormHelper m_UIFormHelper; + + public UIFormInstanceObject() + { + m_UIFormAsset = null; + m_UIFormHelper = null; + } + + public static UIFormInstanceObject Create(string name, object uiFormAsset, object uiFormInstance, IUIFormHelper uiFormHelper) + { + if (uiFormAsset == null) + { + throw new GameFrameworkException("UI form asset is invalid."); + } + + if (uiFormHelper == null) + { + throw new GameFrameworkException("UI form helper is invalid."); + } + + UIFormInstanceObject uiFormInstanceObject = ReferencePool.Acquire(); + uiFormInstanceObject.Initialize(name, uiFormInstance); + uiFormInstanceObject.m_UIFormAsset = uiFormAsset; + uiFormInstanceObject.m_UIFormHelper = uiFormHelper; + return uiFormInstanceObject; + } + + public override void Clear() + { + base.Clear(); + m_UIFormAsset = null; + m_UIFormHelper = null; + } + + protected internal override void Release(bool isShutdown) + { + m_UIFormHelper.ReleaseUIForm(m_UIFormAsset, Target); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIFormInstanceObject.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIFormInstanceObject.cs.meta new file mode 100644 index 0000000..03c7540 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIFormInstanceObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9456966fbe78ac042b77d6521bd95764 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIGroup.UIFormInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIGroup.UIFormInfo.cs new file mode 100644 index 0000000..939aa48 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIGroup.UIFormInfo.cs @@ -0,0 +1,85 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.UI +{ + internal sealed partial class UIManager : GameFrameworkModule, IUIManager + { + private sealed partial class UIGroup : IUIGroup + { + /// + /// 界面组界面信息。 + /// + private sealed class UIFormInfo : IReference + { + private IUIForm m_UIForm; + private bool m_Paused; + private bool m_Covered; + + public UIFormInfo() + { + m_UIForm = null; + m_Paused = false; + m_Covered = false; + } + + public IUIForm UIForm + { + get + { + return m_UIForm; + } + } + + public bool Paused + { + get + { + return m_Paused; + } + set + { + m_Paused = value; + } + } + + public bool Covered + { + get + { + return m_Covered; + } + set + { + m_Covered = value; + } + } + + public static UIFormInfo Create(IUIForm uiForm) + { + if (uiForm == null) + { + throw new GameFrameworkException("UI form is invalid."); + } + + UIFormInfo uiFormInfo = ReferencePool.Acquire(); + uiFormInfo.m_UIForm = uiForm; + uiFormInfo.m_Paused = true; + uiFormInfo.m_Covered = true; + return uiFormInfo; + } + + public void Clear() + { + m_UIForm = null; + m_Paused = false; + m_Covered = false; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIGroup.UIFormInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIGroup.UIFormInfo.cs.meta new file mode 100644 index 0000000..c886e9a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIGroup.UIFormInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a985f3b239b81f947976dbc151acf19f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIGroup.cs new file mode 100644 index 0000000..3dea351 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIGroup.cs @@ -0,0 +1,517 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace GameFramework.UI +{ + internal sealed partial class UIManager : GameFrameworkModule, IUIManager + { + /// + /// 界面组。 + /// + private sealed partial class UIGroup : IUIGroup + { + private readonly string m_Name; + private int m_Depth; + private bool m_Pause; + private readonly IUIGroupHelper m_UIGroupHelper; + private readonly GameFrameworkLinkedList m_UIFormInfos; + private LinkedListNode m_CachedNode; + + /// + /// 初始化界面组的新实例。 + /// + /// 界面组名称。 + /// 界面组深度。 + /// 界面组辅助器。 + public UIGroup(string name, int depth, IUIGroupHelper uiGroupHelper) + { + if (string.IsNullOrEmpty(name)) + { + throw new GameFrameworkException("UI group name is invalid."); + } + + if (uiGroupHelper == null) + { + throw new GameFrameworkException("UI group helper is invalid."); + } + + m_Name = name; + m_Pause = false; + m_UIGroupHelper = uiGroupHelper; + m_UIFormInfos = new GameFrameworkLinkedList(); + m_CachedNode = null; + Depth = depth; + } + + /// + /// 获取界面组名称。 + /// + public string Name + { + get + { + return m_Name; + } + } + + /// + /// 获取或设置界面组深度。 + /// + public int Depth + { + get + { + return m_Depth; + } + set + { + if (m_Depth == value) + { + return; + } + + m_Depth = value; + m_UIGroupHelper.SetDepth(m_Depth); + Refresh(); + } + } + + /// + /// 获取或设置界面组是否暂停。 + /// + public bool Pause + { + get + { + return m_Pause; + } + set + { + if (m_Pause == value) + { + return; + } + + m_Pause = value; + Refresh(); + } + } + + /// + /// 获取界面组中界面数量。 + /// + public int UIFormCount + { + get + { + return m_UIFormInfos.Count; + } + } + + /// + /// 获取当前界面。 + /// + public IUIForm CurrentUIForm + { + get + { + return m_UIFormInfos.First != null ? m_UIFormInfos.First.Value.UIForm : null; + } + } + + /// + /// 获取界面组辅助器。 + /// + public IUIGroupHelper Helper + { + get + { + return m_UIGroupHelper; + } + } + + /// + /// 界面组轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void Update(float elapseSeconds, float realElapseSeconds) + { + LinkedListNode current = m_UIFormInfos.First; + while (current != null) + { + if (current.Value.Paused) + { + break; + } + + m_CachedNode = current.Next; + current.Value.UIForm.OnUpdate(elapseSeconds, realElapseSeconds); + current = m_CachedNode; + m_CachedNode = null; + } + } + + /// + /// 界面组中是否存在界面。 + /// + /// 界面序列编号。 + /// 界面组中是否存在界面。 + public bool HasUIForm(int serialId) + { + foreach (UIFormInfo uiFormInfo in m_UIFormInfos) + { + if (uiFormInfo.UIForm.SerialId == serialId) + { + return true; + } + } + + return false; + } + + /// + /// 界面组中是否存在界面。 + /// + /// 界面资源名称。 + /// 界面组中是否存在界面。 + public bool HasUIForm(string uiFormAssetName) + { + if (string.IsNullOrEmpty(uiFormAssetName)) + { + throw new GameFrameworkException("UI form asset name is invalid."); + } + + foreach (UIFormInfo uiFormInfo in m_UIFormInfos) + { + if (uiFormInfo.UIForm.UIFormAssetName == uiFormAssetName) + { + return true; + } + } + + return false; + } + + /// + /// 从界面组中获取界面。 + /// + /// 界面序列编号。 + /// 要获取的界面。 + public IUIForm GetUIForm(int serialId) + { + foreach (UIFormInfo uiFormInfo in m_UIFormInfos) + { + if (uiFormInfo.UIForm.SerialId == serialId) + { + return uiFormInfo.UIForm; + } + } + + return null; + } + + /// + /// 从界面组中获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + public IUIForm GetUIForm(string uiFormAssetName) + { + if (string.IsNullOrEmpty(uiFormAssetName)) + { + throw new GameFrameworkException("UI form asset name is invalid."); + } + + foreach (UIFormInfo uiFormInfo in m_UIFormInfos) + { + if (uiFormInfo.UIForm.UIFormAssetName == uiFormAssetName) + { + return uiFormInfo.UIForm; + } + } + + return null; + } + + /// + /// 从界面组中获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + public IUIForm[] GetUIForms(string uiFormAssetName) + { + if (string.IsNullOrEmpty(uiFormAssetName)) + { + throw new GameFrameworkException("UI form asset name is invalid."); + } + + List results = new List(); + foreach (UIFormInfo uiFormInfo in m_UIFormInfos) + { + if (uiFormInfo.UIForm.UIFormAssetName == uiFormAssetName) + { + results.Add(uiFormInfo.UIForm); + } + } + + return results.ToArray(); + } + + /// + /// 从界面组中获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + public void GetUIForms(string uiFormAssetName, List results) + { + if (string.IsNullOrEmpty(uiFormAssetName)) + { + throw new GameFrameworkException("UI form asset name is invalid."); + } + + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (UIFormInfo uiFormInfo in m_UIFormInfos) + { + if (uiFormInfo.UIForm.UIFormAssetName == uiFormAssetName) + { + results.Add(uiFormInfo.UIForm); + } + } + } + + /// + /// 从界面组中获取所有界面。 + /// + /// 界面组中的所有界面。 + public IUIForm[] GetAllUIForms() + { + List results = new List(); + foreach (UIFormInfo uiFormInfo in m_UIFormInfos) + { + results.Add(uiFormInfo.UIForm); + } + + return results.ToArray(); + } + + /// + /// 从界面组中获取所有界面。 + /// + /// 界面组中的所有界面。 + public void GetAllUIForms(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (UIFormInfo uiFormInfo in m_UIFormInfos) + { + results.Add(uiFormInfo.UIForm); + } + } + + /// + /// 往界面组增加界面。 + /// + /// 要增加的界面。 + public void AddUIForm(IUIForm uiForm) + { + m_UIFormInfos.AddFirst(UIFormInfo.Create(uiForm)); + } + + /// + /// 从界面组移除界面。 + /// + /// 要移除的界面。 + public void RemoveUIForm(IUIForm uiForm) + { + UIFormInfo uiFormInfo = GetUIFormInfo(uiForm); + if (uiFormInfo == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find UI form info for serial id '{0}', UI form asset name is '{1}'.", uiForm.SerialId, uiForm.UIFormAssetName)); + } + + if (!uiFormInfo.Covered) + { + uiFormInfo.Covered = true; + uiForm.OnCover(); + } + + if (!uiFormInfo.Paused) + { + uiFormInfo.Paused = true; + uiForm.OnPause(); + } + + if (m_CachedNode != null && m_CachedNode.Value.UIForm == uiForm) + { + m_CachedNode = m_CachedNode.Next; + } + + if (!m_UIFormInfos.Remove(uiFormInfo)) + { + throw new GameFrameworkException(Utility.Text.Format("UI group '{0}' not exists specified UI form '[{1}]{2}'.", m_Name, uiForm.SerialId, uiForm.UIFormAssetName)); + } + + ReferencePool.Release(uiFormInfo); + } + + /// + /// 激活界面。 + /// + /// 要激活的界面。 + /// 用户自定义数据。 + public void RefocusUIForm(IUIForm uiForm, object userData) + { + UIFormInfo uiFormInfo = GetUIFormInfo(uiForm); + if (uiFormInfo == null) + { + throw new GameFrameworkException("Can not find UI form info."); + } + + m_UIFormInfos.Remove(uiFormInfo); + m_UIFormInfos.AddFirst(uiFormInfo); + } + + /// + /// 刷新界面组。 + /// + public void Refresh() + { + LinkedListNode current = m_UIFormInfos.First; + bool pause = m_Pause; + bool cover = false; + int depth = UIFormCount; + while (current != null && current.Value != null) + { + LinkedListNode next = current.Next; + current.Value.UIForm.OnDepthChanged(Depth, depth--); + if (current.Value == null) + { + return; + } + + if (pause) + { + if (!current.Value.Covered) + { + current.Value.Covered = true; + current.Value.UIForm.OnCover(); + if (current.Value == null) + { + return; + } + } + + if (!current.Value.Paused) + { + current.Value.Paused = true; + current.Value.UIForm.OnPause(); + if (current.Value == null) + { + return; + } + } + } + else + { + if (current.Value.Paused) + { + current.Value.Paused = false; + current.Value.UIForm.OnResume(); + if (current.Value == null) + { + return; + } + } + + if (current.Value.UIForm.PauseCoveredUIForm) + { + pause = true; + } + + if (cover) + { + if (!current.Value.Covered) + { + current.Value.Covered = true; + current.Value.UIForm.OnCover(); + if (current.Value == null) + { + return; + } + } + } + else + { + if (current.Value.Covered) + { + current.Value.Covered = false; + current.Value.UIForm.OnReveal(); + if (current.Value == null) + { + return; + } + } + + cover = true; + } + } + + current = next; + } + } + + internal void InternalGetUIForms(string uiFormAssetName, List results) + { + foreach (UIFormInfo uiFormInfo in m_UIFormInfos) + { + if (uiFormInfo.UIForm.UIFormAssetName == uiFormAssetName) + { + results.Add(uiFormInfo.UIForm); + } + } + } + + internal void InternalGetAllUIForms(List results) + { + foreach (UIFormInfo uiFormInfo in m_UIFormInfos) + { + results.Add(uiFormInfo.UIForm); + } + } + + private UIFormInfo GetUIFormInfo(IUIForm uiForm) + { + if (uiForm == null) + { + throw new GameFrameworkException("UI form is invalid."); + } + + foreach (UIFormInfo uiFormInfo in m_UIFormInfos) + { + if (uiFormInfo.UIForm == uiForm) + { + return uiFormInfo; + } + } + + return null; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIGroup.cs.meta new file mode 100644 index 0000000..55c39db --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.UIGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 32bd5e9b8ec175c49b05b152d21cf9bc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.cs new file mode 100644 index 0000000..05dc87e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.cs @@ -0,0 +1,1059 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.ObjectPool; +using GameFramework.Resource; +using System; +using System.Collections.Generic; + +namespace GameFramework.UI +{ + /// + /// 界面管理器。 + /// + internal sealed partial class UIManager : GameFrameworkModule, IUIManager + { + private readonly Dictionary m_UIGroups; + private readonly Dictionary m_UIFormsBeingLoaded; + private readonly HashSet m_UIFormsToReleaseOnLoad; + private readonly Queue m_RecycleQueue; + private readonly LoadAssetCallbacks m_LoadAssetCallbacks; + private IObjectPoolManager m_ObjectPoolManager; + private IResourceManager m_ResourceManager; + private IObjectPool m_InstancePool; + private IUIFormHelper m_UIFormHelper; + private int m_Serial; + private bool m_IsShutdown; + private EventHandler m_OpenUIFormSuccessEventHandler; + private EventHandler m_OpenUIFormFailureEventHandler; + private EventHandler m_OpenUIFormUpdateEventHandler; + private EventHandler m_OpenUIFormDependencyAssetEventHandler; + private EventHandler m_CloseUIFormCompleteEventHandler; + + /// + /// 初始化界面管理器的新实例。 + /// + public UIManager() + { + m_UIGroups = new Dictionary(StringComparer.Ordinal); + m_UIFormsBeingLoaded = new Dictionary(); + m_UIFormsToReleaseOnLoad = new HashSet(); + m_RecycleQueue = new Queue(); + m_LoadAssetCallbacks = new LoadAssetCallbacks(LoadAssetSuccessCallback, LoadAssetFailureCallback, LoadAssetUpdateCallback, LoadAssetDependencyAssetCallback); + m_ObjectPoolManager = null; + m_ResourceManager = null; + m_InstancePool = null; + m_UIFormHelper = null; + m_Serial = 0; + m_IsShutdown = false; + m_OpenUIFormSuccessEventHandler = null; + m_OpenUIFormFailureEventHandler = null; + m_OpenUIFormUpdateEventHandler = null; + m_OpenUIFormDependencyAssetEventHandler = null; + m_CloseUIFormCompleteEventHandler = null; + } + + /// + /// 获取界面组数量。 + /// + public int UIGroupCount + { + get + { + return m_UIGroups.Count; + } + } + + /// + /// 获取或设置界面实例对象池自动释放可释放对象的间隔秒数。 + /// + public float InstanceAutoReleaseInterval + { + get + { + return m_InstancePool.AutoReleaseInterval; + } + set + { + m_InstancePool.AutoReleaseInterval = value; + } + } + + /// + /// 获取或设置界面实例对象池的容量。 + /// + public int InstanceCapacity + { + get + { + return m_InstancePool.Capacity; + } + set + { + m_InstancePool.Capacity = value; + } + } + + /// + /// 获取或设置界面实例对象池对象过期秒数。 + /// + public float InstanceExpireTime + { + get + { + return m_InstancePool.ExpireTime; + } + set + { + m_InstancePool.ExpireTime = value; + } + } + + /// + /// 获取或设置界面实例对象池的优先级。 + /// + public int InstancePriority + { + get + { + return m_InstancePool.Priority; + } + set + { + m_InstancePool.Priority = value; + } + } + + /// + /// 打开界面成功事件。 + /// + public event EventHandler OpenUIFormSuccess + { + add + { + m_OpenUIFormSuccessEventHandler += value; + } + remove + { + m_OpenUIFormSuccessEventHandler -= value; + } + } + + /// + /// 打开界面失败事件。 + /// + public event EventHandler OpenUIFormFailure + { + add + { + m_OpenUIFormFailureEventHandler += value; + } + remove + { + m_OpenUIFormFailureEventHandler -= value; + } + } + + /// + /// 打开界面更新事件。 + /// + public event EventHandler OpenUIFormUpdate + { + add + { + m_OpenUIFormUpdateEventHandler += value; + } + remove + { + m_OpenUIFormUpdateEventHandler -= value; + } + } + + /// + /// 打开界面时加载依赖资源事件。 + /// + public event EventHandler OpenUIFormDependencyAsset + { + add + { + m_OpenUIFormDependencyAssetEventHandler += value; + } + remove + { + m_OpenUIFormDependencyAssetEventHandler -= value; + } + } + + /// + /// 关闭界面完成事件。 + /// + public event EventHandler CloseUIFormComplete + { + add + { + m_CloseUIFormCompleteEventHandler += value; + } + remove + { + m_CloseUIFormCompleteEventHandler -= value; + } + } + + /// + /// 界面管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + while (m_RecycleQueue.Count > 0) + { + IUIForm uiForm = m_RecycleQueue.Dequeue(); + uiForm.OnRecycle(); + m_InstancePool.Unspawn(uiForm.Handle); + } + + foreach (KeyValuePair uiGroup in m_UIGroups) + { + uiGroup.Value.Update(elapseSeconds, realElapseSeconds); + } + } + + /// + /// 关闭并清理界面管理器。 + /// + internal override void Shutdown() + { + m_IsShutdown = true; + CloseAllLoadedUIForms(); + m_UIGroups.Clear(); + m_UIFormsBeingLoaded.Clear(); + m_UIFormsToReleaseOnLoad.Clear(); + m_RecycleQueue.Clear(); + } + + /// + /// 设置对象池管理器。 + /// + /// 对象池管理器。 + public void SetObjectPoolManager(IObjectPoolManager objectPoolManager) + { + if (objectPoolManager == null) + { + throw new GameFrameworkException("Object pool manager is invalid."); + } + + m_ObjectPoolManager = objectPoolManager; + m_InstancePool = m_ObjectPoolManager.CreateSingleSpawnObjectPool("UI Instance Pool"); + } + + /// + /// 设置资源管理器。 + /// + /// 资源管理器。 + public void SetResourceManager(IResourceManager resourceManager) + { + if (resourceManager == null) + { + throw new GameFrameworkException("Resource manager is invalid."); + } + + m_ResourceManager = resourceManager; + } + + /// + /// 设置界面辅助器。 + /// + /// 界面辅助器。 + public void SetUIFormHelper(IUIFormHelper uiFormHelper) + { + if (uiFormHelper == null) + { + throw new GameFrameworkException("UI form helper is invalid."); + } + + m_UIFormHelper = uiFormHelper; + } + + /// + /// 是否存在界面组。 + /// + /// 界面组名称。 + /// 是否存在界面组。 + public bool HasUIGroup(string uiGroupName) + { + if (string.IsNullOrEmpty(uiGroupName)) + { + throw new GameFrameworkException("UI group name is invalid."); + } + + return m_UIGroups.ContainsKey(uiGroupName); + } + + /// + /// 获取界面组。 + /// + /// 界面组名称。 + /// 要获取的界面组。 + public IUIGroup GetUIGroup(string uiGroupName) + { + if (string.IsNullOrEmpty(uiGroupName)) + { + throw new GameFrameworkException("UI group name is invalid."); + } + + UIGroup uiGroup = null; + if (m_UIGroups.TryGetValue(uiGroupName, out uiGroup)) + { + return uiGroup; + } + + return null; + } + + /// + /// 获取所有界面组。 + /// + /// 所有界面组。 + public IUIGroup[] GetAllUIGroups() + { + int index = 0; + IUIGroup[] results = new IUIGroup[m_UIGroups.Count]; + foreach (KeyValuePair uiGroup in m_UIGroups) + { + results[index++] = uiGroup.Value; + } + + return results; + } + + /// + /// 获取所有界面组。 + /// + /// 所有界面组。 + public void GetAllUIGroups(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair uiGroup in m_UIGroups) + { + results.Add(uiGroup.Value); + } + } + + /// + /// 增加界面组。 + /// + /// 界面组名称。 + /// 界面组辅助器。 + /// 是否增加界面组成功。 + public bool AddUIGroup(string uiGroupName, IUIGroupHelper uiGroupHelper) + { + return AddUIGroup(uiGroupName, 0, uiGroupHelper); + } + + /// + /// 增加界面组。 + /// + /// 界面组名称。 + /// 界面组深度。 + /// 界面组辅助器。 + /// 是否增加界面组成功。 + public bool AddUIGroup(string uiGroupName, int uiGroupDepth, IUIGroupHelper uiGroupHelper) + { + if (string.IsNullOrEmpty(uiGroupName)) + { + throw new GameFrameworkException("UI group name is invalid."); + } + + if (uiGroupHelper == null) + { + throw new GameFrameworkException("UI group helper is invalid."); + } + + if (HasUIGroup(uiGroupName)) + { + return false; + } + + m_UIGroups.Add(uiGroupName, new UIGroup(uiGroupName, uiGroupDepth, uiGroupHelper)); + + return true; + } + + /// + /// 是否存在界面。 + /// + /// 界面序列编号。 + /// 是否存在界面。 + public bool HasUIForm(int serialId) + { + foreach (KeyValuePair uiGroup in m_UIGroups) + { + if (uiGroup.Value.HasUIForm(serialId)) + { + return true; + } + } + + return false; + } + + /// + /// 是否存在界面。 + /// + /// 界面资源名称。 + /// 是否存在界面。 + public bool HasUIForm(string uiFormAssetName) + { + if (string.IsNullOrEmpty(uiFormAssetName)) + { + throw new GameFrameworkException("UI form asset name is invalid."); + } + + foreach (KeyValuePair uiGroup in m_UIGroups) + { + if (uiGroup.Value.HasUIForm(uiFormAssetName)) + { + return true; + } + } + + return false; + } + + /// + /// 获取界面。 + /// + /// 界面序列编号。 + /// 要获取的界面。 + public IUIForm GetUIForm(int serialId) + { + foreach (KeyValuePair uiGroup in m_UIGroups) + { + IUIForm uiForm = uiGroup.Value.GetUIForm(serialId); + if (uiForm != null) + { + return uiForm; + } + } + + return null; + } + + /// + /// 获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + public IUIForm GetUIForm(string uiFormAssetName) + { + if (string.IsNullOrEmpty(uiFormAssetName)) + { + throw new GameFrameworkException("UI form asset name is invalid."); + } + + foreach (KeyValuePair uiGroup in m_UIGroups) + { + IUIForm uiForm = uiGroup.Value.GetUIForm(uiFormAssetName); + if (uiForm != null) + { + return uiForm; + } + } + + return null; + } + + /// + /// 获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + public IUIForm[] GetUIForms(string uiFormAssetName) + { + if (string.IsNullOrEmpty(uiFormAssetName)) + { + throw new GameFrameworkException("UI form asset name is invalid."); + } + + List results = new List(); + foreach (KeyValuePair uiGroup in m_UIGroups) + { + results.AddRange(uiGroup.Value.GetUIForms(uiFormAssetName)); + } + + return results.ToArray(); + } + + /// + /// 获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + public void GetUIForms(string uiFormAssetName, List results) + { + if (string.IsNullOrEmpty(uiFormAssetName)) + { + throw new GameFrameworkException("UI form asset name is invalid."); + } + + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair uiGroup in m_UIGroups) + { + uiGroup.Value.InternalGetUIForms(uiFormAssetName, results); + } + } + + /// + /// 获取所有已加载的界面。 + /// + /// 所有已加载的界面。 + public IUIForm[] GetAllLoadedUIForms() + { + List results = new List(); + foreach (KeyValuePair uiGroup in m_UIGroups) + { + results.AddRange(uiGroup.Value.GetAllUIForms()); + } + + return results.ToArray(); + } + + /// + /// 获取所有已加载的界面。 + /// + /// 所有已加载的界面。 + public void GetAllLoadedUIForms(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair uiGroup in m_UIGroups) + { + uiGroup.Value.InternalGetAllUIForms(results); + } + } + + /// + /// 获取所有正在加载界面的序列编号。 + /// + /// 所有正在加载界面的序列编号。 + public int[] GetAllLoadingUIFormSerialIds() + { + int index = 0; + int[] results = new int[m_UIFormsBeingLoaded.Count]; + foreach (KeyValuePair uiFormBeingLoaded in m_UIFormsBeingLoaded) + { + results[index++] = uiFormBeingLoaded.Key; + } + + return results; + } + + /// + /// 获取所有正在加载界面的序列编号。 + /// + /// 所有正在加载界面的序列编号。 + public void GetAllLoadingUIFormSerialIds(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair uiFormBeingLoaded in m_UIFormsBeingLoaded) + { + results.Add(uiFormBeingLoaded.Key); + } + } + + /// + /// 是否正在加载界面。 + /// + /// 界面序列编号。 + /// 是否正在加载界面。 + public bool IsLoadingUIForm(int serialId) + { + return m_UIFormsBeingLoaded.ContainsKey(serialId); + } + + /// + /// 是否正在加载界面。 + /// + /// 界面资源名称。 + /// 是否正在加载界面。 + public bool IsLoadingUIForm(string uiFormAssetName) + { + if (string.IsNullOrEmpty(uiFormAssetName)) + { + throw new GameFrameworkException("UI form asset name is invalid."); + } + + return m_UIFormsBeingLoaded.ContainsValue(uiFormAssetName); + } + + /// + /// 是否是合法的界面。 + /// + /// 界面。 + /// 界面是否合法。 + public bool IsValidUIForm(IUIForm uiForm) + { + if (uiForm == null) + { + return false; + } + + return HasUIForm(uiForm.SerialId); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName) + { + return OpenUIForm(uiFormAssetName, uiGroupName, Constant.DefaultPriority, false, null); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 加载界面资源的优先级。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority) + { + return OpenUIForm(uiFormAssetName, uiGroupName, priority, false, null); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 是否暂停被覆盖的界面。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, bool pauseCoveredUIForm) + { + return OpenUIForm(uiFormAssetName, uiGroupName, Constant.DefaultPriority, pauseCoveredUIForm, null); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 用户自定义数据。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, object userData) + { + return OpenUIForm(uiFormAssetName, uiGroupName, Constant.DefaultPriority, false, userData); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 加载界面资源的优先级。 + /// 是否暂停被覆盖的界面。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, bool pauseCoveredUIForm) + { + return OpenUIForm(uiFormAssetName, uiGroupName, priority, pauseCoveredUIForm, null); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 加载界面资源的优先级。 + /// 用户自定义数据。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, object userData) + { + return OpenUIForm(uiFormAssetName, uiGroupName, priority, false, userData); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 是否暂停被覆盖的界面。 + /// 用户自定义数据。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, bool pauseCoveredUIForm, object userData) + { + return OpenUIForm(uiFormAssetName, uiGroupName, Constant.DefaultPriority, pauseCoveredUIForm, userData); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 加载界面资源的优先级。 + /// 是否暂停被覆盖的界面。 + /// 用户自定义数据。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, bool pauseCoveredUIForm, object userData) + { + if (m_ResourceManager == null) + { + throw new GameFrameworkException("You must set resource manager first."); + } + + if (m_UIFormHelper == null) + { + throw new GameFrameworkException("You must set UI form helper first."); + } + + if (string.IsNullOrEmpty(uiFormAssetName)) + { + throw new GameFrameworkException("UI form asset name is invalid."); + } + + if (string.IsNullOrEmpty(uiGroupName)) + { + throw new GameFrameworkException("UI group name is invalid."); + } + + UIGroup uiGroup = (UIGroup)GetUIGroup(uiGroupName); + if (uiGroup == null) + { + throw new GameFrameworkException(Utility.Text.Format("UI group '{0}' is not exist.", uiGroupName)); + } + + int serialId = ++m_Serial; + UIFormInstanceObject uiFormInstanceObject = m_InstancePool.Spawn(uiFormAssetName); + if (uiFormInstanceObject == null) + { + m_UIFormsBeingLoaded.Add(serialId, uiFormAssetName); + m_ResourceManager.LoadAsset(uiFormAssetName, priority, m_LoadAssetCallbacks, OpenUIFormInfo.Create(serialId, uiGroup, pauseCoveredUIForm, userData)); + } + else + { + InternalOpenUIForm(serialId, uiFormAssetName, uiGroup, uiFormInstanceObject.Target, pauseCoveredUIForm, false, 0f, userData); + } + + return serialId; + } + + /// + /// 关闭界面。 + /// + /// 要关闭界面的序列编号。 + public void CloseUIForm(int serialId) + { + CloseUIForm(serialId, null); + } + + /// + /// 关闭界面。 + /// + /// 要关闭界面的序列编号。 + /// 用户自定义数据。 + public void CloseUIForm(int serialId, object userData) + { + if (IsLoadingUIForm(serialId)) + { + m_UIFormsToReleaseOnLoad.Add(serialId); + m_UIFormsBeingLoaded.Remove(serialId); + return; + } + + IUIForm uiForm = GetUIForm(serialId); + if (uiForm == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find UI form '{0}'.", serialId)); + } + + CloseUIForm(uiForm, userData); + } + + /// + /// 关闭界面。 + /// + /// 要关闭的界面。 + public void CloseUIForm(IUIForm uiForm) + { + CloseUIForm(uiForm, null); + } + + /// + /// 关闭界面。 + /// + /// 要关闭的界面。 + /// 用户自定义数据。 + public void CloseUIForm(IUIForm uiForm, object userData) + { + if (uiForm == null) + { + throw new GameFrameworkException("UI form is invalid."); + } + + UIGroup uiGroup = (UIGroup)uiForm.UIGroup; + if (uiGroup == null) + { + throw new GameFrameworkException("UI group is invalid."); + } + + uiGroup.RemoveUIForm(uiForm); + uiForm.OnClose(m_IsShutdown, userData); + uiGroup.Refresh(); + + if (m_CloseUIFormCompleteEventHandler != null) + { + CloseUIFormCompleteEventArgs closeUIFormCompleteEventArgs = CloseUIFormCompleteEventArgs.Create(uiForm.SerialId, uiForm.UIFormAssetName, uiGroup, userData); + m_CloseUIFormCompleteEventHandler(this, closeUIFormCompleteEventArgs); + ReferencePool.Release(closeUIFormCompleteEventArgs); + } + + m_RecycleQueue.Enqueue(uiForm); + } + + /// + /// 关闭所有已加载的界面。 + /// + public void CloseAllLoadedUIForms() + { + CloseAllLoadedUIForms(null); + } + + /// + /// 关闭所有已加载的界面。 + /// + /// 用户自定义数据。 + public void CloseAllLoadedUIForms(object userData) + { + IUIForm[] uiForms = GetAllLoadedUIForms(); + foreach (IUIForm uiForm in uiForms) + { + if (!HasUIForm(uiForm.SerialId)) + { + continue; + } + + CloseUIForm(uiForm, userData); + } + } + + /// + /// 关闭所有正在加载的界面。 + /// + public void CloseAllLoadingUIForms() + { + foreach (KeyValuePair uiFormBeingLoaded in m_UIFormsBeingLoaded) + { + m_UIFormsToReleaseOnLoad.Add(uiFormBeingLoaded.Key); + } + + m_UIFormsBeingLoaded.Clear(); + } + + /// + /// 激活界面。 + /// + /// 要激活的界面。 + public void RefocusUIForm(IUIForm uiForm) + { + RefocusUIForm(uiForm, null); + } + + /// + /// 激活界面。 + /// + /// 要激活的界面。 + /// 用户自定义数据。 + public void RefocusUIForm(IUIForm uiForm, object userData) + { + if (uiForm == null) + { + throw new GameFrameworkException("UI form is invalid."); + } + + UIGroup uiGroup = (UIGroup)uiForm.UIGroup; + if (uiGroup == null) + { + throw new GameFrameworkException("UI group is invalid."); + } + + uiGroup.RefocusUIForm(uiForm, userData); + uiGroup.Refresh(); + uiForm.OnRefocus(userData); + } + + /// + /// 设置界面实例是否被加锁。 + /// + /// 要设置是否被加锁的界面实例。 + /// 界面实例是否被加锁。 + public void SetUIFormInstanceLocked(object uiFormInstance, bool locked) + { + if (uiFormInstance == null) + { + throw new GameFrameworkException("UI form instance is invalid."); + } + + m_InstancePool.SetLocked(uiFormInstance, locked); + } + + /// + /// 设置界面实例的优先级。 + /// + /// 要设置优先级的界面实例。 + /// 界面实例优先级。 + public void SetUIFormInstancePriority(object uiFormInstance, int priority) + { + if (uiFormInstance == null) + { + throw new GameFrameworkException("UI form instance is invalid."); + } + + m_InstancePool.SetPriority(uiFormInstance, priority); + } + + private void InternalOpenUIForm(int serialId, string uiFormAssetName, UIGroup uiGroup, object uiFormInstance, bool pauseCoveredUIForm, bool isNewInstance, float duration, object userData) + { + try + { + IUIForm uiForm = m_UIFormHelper.CreateUIForm(uiFormInstance, uiGroup, userData); + if (uiForm == null) + { + throw new GameFrameworkException("Can not create UI form in UI form helper."); + } + + uiForm.OnInit(serialId, uiFormAssetName, uiGroup, pauseCoveredUIForm, isNewInstance, userData); + uiGroup.AddUIForm(uiForm); + uiForm.OnOpen(userData); + uiGroup.Refresh(); + + if (m_OpenUIFormSuccessEventHandler != null) + { + OpenUIFormSuccessEventArgs openUIFormSuccessEventArgs = OpenUIFormSuccessEventArgs.Create(uiForm, duration, userData); + m_OpenUIFormSuccessEventHandler(this, openUIFormSuccessEventArgs); + ReferencePool.Release(openUIFormSuccessEventArgs); + } + } + catch (Exception exception) + { + if (m_OpenUIFormFailureEventHandler != null) + { + OpenUIFormFailureEventArgs openUIFormFailureEventArgs = OpenUIFormFailureEventArgs.Create(serialId, uiFormAssetName, uiGroup.Name, pauseCoveredUIForm, exception.ToString(), userData); + m_OpenUIFormFailureEventHandler(this, openUIFormFailureEventArgs); + ReferencePool.Release(openUIFormFailureEventArgs); + return; + } + + throw; + } + } + + private void LoadAssetSuccessCallback(string uiFormAssetName, object uiFormAsset, float duration, object userData) + { + OpenUIFormInfo openUIFormInfo = (OpenUIFormInfo)userData; + if (openUIFormInfo == null) + { + throw new GameFrameworkException("Open UI form info is invalid."); + } + + if (m_UIFormsToReleaseOnLoad.Contains(openUIFormInfo.SerialId)) + { + m_UIFormsToReleaseOnLoad.Remove(openUIFormInfo.SerialId); + ReferencePool.Release(openUIFormInfo); + m_UIFormHelper.ReleaseUIForm(uiFormAsset, null); + return; + } + + m_UIFormsBeingLoaded.Remove(openUIFormInfo.SerialId); + UIFormInstanceObject uiFormInstanceObject = UIFormInstanceObject.Create(uiFormAssetName, uiFormAsset, m_UIFormHelper.InstantiateUIForm(uiFormAsset), m_UIFormHelper); + m_InstancePool.Register(uiFormInstanceObject, true); + + InternalOpenUIForm(openUIFormInfo.SerialId, uiFormAssetName, openUIFormInfo.UIGroup, uiFormInstanceObject.Target, openUIFormInfo.PauseCoveredUIForm, true, duration, openUIFormInfo.UserData); + ReferencePool.Release(openUIFormInfo); + } + + private void LoadAssetFailureCallback(string uiFormAssetName, LoadResourceStatus status, string errorMessage, object userData) + { + OpenUIFormInfo openUIFormInfo = (OpenUIFormInfo)userData; + if (openUIFormInfo == null) + { + throw new GameFrameworkException("Open UI form info is invalid."); + } + + if (m_UIFormsToReleaseOnLoad.Contains(openUIFormInfo.SerialId)) + { + m_UIFormsToReleaseOnLoad.Remove(openUIFormInfo.SerialId); + return; + } + + m_UIFormsBeingLoaded.Remove(openUIFormInfo.SerialId); + string appendErrorMessage = Utility.Text.Format("Load UI form failure, asset name '{0}', status '{1}', error message '{2}'.", uiFormAssetName, status, errorMessage); + if (m_OpenUIFormFailureEventHandler != null) + { + OpenUIFormFailureEventArgs openUIFormFailureEventArgs = OpenUIFormFailureEventArgs.Create(openUIFormInfo.SerialId, uiFormAssetName, openUIFormInfo.UIGroup.Name, openUIFormInfo.PauseCoveredUIForm, appendErrorMessage, openUIFormInfo.UserData); + m_OpenUIFormFailureEventHandler(this, openUIFormFailureEventArgs); + ReferencePool.Release(openUIFormFailureEventArgs); + return; + } + + throw new GameFrameworkException(appendErrorMessage); + } + + private void LoadAssetUpdateCallback(string uiFormAssetName, float progress, object userData) + { + OpenUIFormInfo openUIFormInfo = (OpenUIFormInfo)userData; + if (openUIFormInfo == null) + { + throw new GameFrameworkException("Open UI form info is invalid."); + } + + if (m_OpenUIFormUpdateEventHandler != null) + { + OpenUIFormUpdateEventArgs openUIFormUpdateEventArgs = OpenUIFormUpdateEventArgs.Create(openUIFormInfo.SerialId, uiFormAssetName, openUIFormInfo.UIGroup.Name, openUIFormInfo.PauseCoveredUIForm, progress, openUIFormInfo.UserData); + m_OpenUIFormUpdateEventHandler(this, openUIFormUpdateEventArgs); + ReferencePool.Release(openUIFormUpdateEventArgs); + } + } + + private void LoadAssetDependencyAssetCallback(string uiFormAssetName, string dependencyAssetName, int loadedCount, int totalCount, object userData) + { + OpenUIFormInfo openUIFormInfo = (OpenUIFormInfo)userData; + if (openUIFormInfo == null) + { + throw new GameFrameworkException("Open UI form info is invalid."); + } + + if (m_OpenUIFormDependencyAssetEventHandler != null) + { + OpenUIFormDependencyAssetEventArgs openUIFormDependencyAssetEventArgs = OpenUIFormDependencyAssetEventArgs.Create(openUIFormInfo.SerialId, uiFormAssetName, openUIFormInfo.UIGroup.Name, openUIFormInfo.PauseCoveredUIForm, dependencyAssetName, loadedCount, totalCount, openUIFormInfo.UserData); + m_OpenUIFormDependencyAssetEventHandler(this, openUIFormDependencyAssetEventArgs); + ReferencePool.Release(openUIFormDependencyAssetEventArgs); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.cs.meta new file mode 100644 index 0000000..ca26035 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/UI/UIManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 60cc85a690b85b949a77b27ba98a68d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility.meta new file mode 100644 index 0000000..63463d3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fda02aac454562249a337cbfa4d99e01 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Assembly.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Assembly.cs new file mode 100644 index 0000000..22143e4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Assembly.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework +{ + public static partial class Utility + { + /// + /// 程序集相关的实用函数。 + /// + public static class Assembly + { + private static readonly System.Reflection.Assembly[] s_Assemblies = null; + private static readonly Dictionary s_CachedTypes = new Dictionary(StringComparer.Ordinal); + + static Assembly() + { + s_Assemblies = AppDomain.CurrentDomain.GetAssemblies(); + } + + /// + /// 获取已加载的程序集。 + /// + /// 已加载的程序集。 + public static System.Reflection.Assembly[] GetAssemblies() + { + return s_Assemblies; + } + + /// + /// 获取已加载的程序集中的所有类型。 + /// + /// 已加载的程序集中的所有类型。 + public static Type[] GetTypes() + { + List results = new List(); + foreach (System.Reflection.Assembly assembly in s_Assemblies) + { + results.AddRange(assembly.GetTypes()); + } + + return results.ToArray(); + } + + /// + /// 获取已加载的程序集中的所有类型。 + /// + /// 已加载的程序集中的所有类型。 + public static void GetTypes(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (System.Reflection.Assembly assembly in s_Assemblies) + { + results.AddRange(assembly.GetTypes()); + } + } + + /// + /// 获取已加载的程序集中的指定类型。 + /// + /// 要获取的类型名。 + /// 已加载的程序集中的指定类型。 + public static Type GetType(string typeName) + { + if (string.IsNullOrEmpty(typeName)) + { + throw new GameFrameworkException("Type name is invalid."); + } + + Type type = null; + if (s_CachedTypes.TryGetValue(typeName, out type)) + { + return type; + } + + type = Type.GetType(typeName); + if (type != null) + { + s_CachedTypes.Add(typeName, type); + return type; + } + + foreach (System.Reflection.Assembly assembly in s_Assemblies) + { + type = Type.GetType(Text.Format("{0}, {1}", typeName, assembly.FullName)); + if (type != null) + { + s_CachedTypes.Add(typeName, type); + return type; + } + } + + return null; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Assembly.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Assembly.cs.meta new file mode 100644 index 0000000..6311554 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Assembly.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9083ccb040eb9d5479195c1e3d54a408 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Compression.ICompressionHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Compression.ICompressionHelper.cs new file mode 100644 index 0000000..3ecda01 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Compression.ICompressionHelper.cs @@ -0,0 +1,59 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.IO; + +namespace GameFramework +{ + public static partial class Utility + { + public static partial class Compression + { + /// + /// 压缩解压缩辅助器接口。 + /// + public interface ICompressionHelper + { + /// + /// 压缩数据。 + /// + /// 要压缩的数据的二进制流。 + /// 要压缩的数据的二进制流的偏移。 + /// 要压缩的数据的二进制流的长度。 + /// 压缩后的数据的二进制流。 + /// 是否压缩数据成功。 + bool Compress(byte[] bytes, int offset, int length, Stream compressedStream); + + /// + /// 压缩数据。 + /// + /// 要压缩的数据的二进制流。 + /// 压缩后的数据的二进制流。 + /// 是否压缩数据成功。 + bool Compress(Stream stream, Stream compressedStream); + + /// + /// 解压缩数据。 + /// + /// 要解压缩的数据的二进制流。 + /// 要解压缩的数据的二进制流的偏移。 + /// 要解压缩的数据的二进制流的长度。 + /// 解压缩后的数据的二进制流。 + /// 是否解压缩数据成功。 + bool Decompress(byte[] bytes, int offset, int length, Stream decompressedStream); + + /// + /// 解压缩数据。 + /// + /// 要解压缩的数据的二进制流。 + /// 解压缩后的数据的二进制流。 + /// 是否解压缩数据成功。 + bool Decompress(Stream stream, Stream decompressedStream); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Compression.ICompressionHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Compression.ICompressionHelper.cs.meta new file mode 100644 index 0000000..44c21d6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Compression.ICompressionHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 062b672ef8dbcc24ca054d8f890047aa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Compression.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Compression.cs new file mode 100644 index 0000000..64a2840 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Compression.cs @@ -0,0 +1,344 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.IO; + +namespace GameFramework +{ + public static partial class Utility + { + /// + /// 压缩解压缩相关的实用函数。 + /// + public static partial class Compression + { + private static ICompressionHelper s_CompressionHelper = null; + + /// + /// 设置压缩解压缩辅助器。 + /// + /// 要设置的压缩解压缩辅助器。 + public static void SetCompressionHelper(ICompressionHelper compressionHelper) + { + s_CompressionHelper = compressionHelper; + } + + /// + /// 压缩数据。 + /// + /// 要压缩的数据的二进制流。 + /// 压缩后的数据的二进制流。 + public static byte[] Compress(byte[] bytes) + { + if (bytes == null) + { + throw new GameFrameworkException("Bytes is invalid."); + } + + return Compress(bytes, 0, bytes.Length); + } + + /// + /// 压缩数据。 + /// + /// 要压缩的数据的二进制流。 + /// 压缩后的数据的二进制流。 + /// 是否压缩数据成功。 + public static bool Compress(byte[] bytes, Stream compressedStream) + { + if (bytes == null) + { + throw new GameFrameworkException("Bytes is invalid."); + } + + return Compress(bytes, 0, bytes.Length, compressedStream); + } + + /// + /// 压缩数据。 + /// + /// 要压缩的数据的二进制流。 + /// 要压缩的数据的二进制流的偏移。 + /// 要压缩的数据的二进制流的长度。 + /// 压缩后的数据的二进制流。 + public static byte[] Compress(byte[] bytes, int offset, int length) + { + using (MemoryStream compressedStream = new MemoryStream()) + { + if (Compress(bytes, offset, length, compressedStream)) + { + return compressedStream.ToArray(); + } + else + { + return null; + } + } + } + + /// + /// 压缩数据。 + /// + /// 要压缩的数据的二进制流。 + /// 要压缩的数据的二进制流的偏移。 + /// 要压缩的数据的二进制流的长度。 + /// 压缩后的数据的二进制流。 + /// 是否压缩数据成功。 + public static bool Compress(byte[] bytes, int offset, int length, Stream compressedStream) + { + if (s_CompressionHelper == null) + { + throw new GameFrameworkException("Compressed helper is invalid."); + } + + if (bytes == null) + { + throw new GameFrameworkException("Bytes is invalid."); + } + + if (offset < 0 || length < 0 || offset + length > bytes.Length) + { + throw new GameFrameworkException("Offset or length is invalid."); + } + + if (compressedStream == null) + { + throw new GameFrameworkException("Compressed stream is invalid."); + } + + try + { + return s_CompressionHelper.Compress(bytes, offset, length, compressedStream); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Text.Format("Can not compress with exception '{0}'.", exception), exception); + } + } + + /// + /// 压缩数据。 + /// + /// 要压缩的数据的二进制流。 + /// 压缩后的数据的二进制流。 + public static byte[] Compress(Stream stream) + { + using (MemoryStream compressedStream = new MemoryStream()) + { + if (Compress(stream, compressedStream)) + { + return compressedStream.ToArray(); + } + else + { + return null; + } + } + } + + /// + /// 压缩数据。 + /// + /// 要压缩的数据的二进制流。 + /// 压缩后的数据的二进制流。 + /// 是否压缩数据成功。 + public static bool Compress(Stream stream, Stream compressedStream) + { + if (s_CompressionHelper == null) + { + throw new GameFrameworkException("Compressed helper is invalid."); + } + + if (stream == null) + { + throw new GameFrameworkException("Stream is invalid."); + } + + if (compressedStream == null) + { + throw new GameFrameworkException("Compressed stream is invalid."); + } + + try + { + return s_CompressionHelper.Compress(stream, compressedStream); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Text.Format("Can not compress with exception '{0}'.", exception), exception); + } + } + + /// + /// 解压缩数据。 + /// + /// 要解压缩的数据的二进制流。 + /// 解压缩后的数据的二进制流。 + public static byte[] Decompress(byte[] bytes) + { + if (bytes == null) + { + throw new GameFrameworkException("Bytes is invalid."); + } + + return Decompress(bytes, 0, bytes.Length); + } + + /// + /// 解压缩数据。 + /// + /// 要解压缩的数据的二进制流。 + /// 解压缩后的数据的二进制流。 + /// 是否解压缩数据成功。 + public static bool Decompress(byte[] bytes, Stream decompressedStream) + { + if (bytes == null) + { + throw new GameFrameworkException("Bytes is invalid."); + } + + return Decompress(bytes, 0, bytes.Length, decompressedStream); + } + + /// + /// 解压缩数据。 + /// + /// 要解压缩的数据的二进制流。 + /// 要解压缩的数据的二进制流的偏移。 + /// 要解压缩的数据的二进制流的长度。 + /// 解压缩后的数据的二进制流。 + public static byte[] Decompress(byte[] bytes, int offset, int length) + { + using (MemoryStream decompressedStream = new MemoryStream()) + { + if (Decompress(bytes, offset, length, decompressedStream)) + { + return decompressedStream.ToArray(); + } + else + { + return null; + } + } + } + + /// + /// 解压缩数据。 + /// + /// 要解压缩的数据的二进制流。 + /// 要解压缩的数据的二进制流的偏移。 + /// 要解压缩的数据的二进制流的长度。 + /// 解压缩后的数据的二进制流。 + /// 是否解压缩数据成功。 + public static bool Decompress(byte[] bytes, int offset, int length, Stream decompressedStream) + { + if (s_CompressionHelper == null) + { + throw new GameFrameworkException("Compressed helper is invalid."); + } + + if (bytes == null) + { + throw new GameFrameworkException("Bytes is invalid."); + } + + if (offset < 0 || length < 0 || offset + length > bytes.Length) + { + throw new GameFrameworkException("Offset or length is invalid."); + } + + if (decompressedStream == null) + { + throw new GameFrameworkException("Decompressed stream is invalid."); + } + + try + { + return s_CompressionHelper.Decompress(bytes, offset, length, decompressedStream); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Text.Format("Can not decompress with exception '{0}'.", exception), exception); + } + } + + /// + /// 解压缩数据。 + /// + /// 要解压缩的数据的二进制流。 + /// 是否解压缩数据成功。 + public static byte[] Decompress(Stream stream) + { + using (MemoryStream decompressedStream = new MemoryStream()) + { + if (Decompress(stream, decompressedStream)) + { + return decompressedStream.ToArray(); + } + else + { + return null; + } + } + } + + /// + /// 解压缩数据。 + /// + /// 要解压缩的数据的二进制流。 + /// 解压缩后的数据的二进制流。 + /// 是否解压缩数据成功。 + public static bool Decompress(Stream stream, Stream decompressedStream) + { + if (s_CompressionHelper == null) + { + throw new GameFrameworkException("Compressed helper is invalid."); + } + + if (stream == null) + { + throw new GameFrameworkException("Stream is invalid."); + } + + if (decompressedStream == null) + { + throw new GameFrameworkException("Decompressed stream is invalid."); + } + + try + { + return s_CompressionHelper.Decompress(stream, decompressedStream); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Text.Format("Can not decompress with exception '{0}'.", exception), exception); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Compression.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Compression.cs.meta new file mode 100644 index 0000000..5b9b9ec --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Compression.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e8f137320b778cb4aa7b0521aeb6d88c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Converter.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Converter.cs new file mode 100644 index 0000000..ba750b1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Converter.cs @@ -0,0 +1,848 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Text; + +namespace GameFramework +{ + public static partial class Utility + { + /// + /// 类型转换相关的实用函数。 + /// + public static class Converter + { + private const float InchesToCentimeters = 2.54f; // 1 inch = 2.54 cm + private const float CentimetersToInches = 1f / InchesToCentimeters; // 1 cm = 0.3937 inches + + /// + /// 获取数据在此计算机结构中存储时的字节顺序。 + /// + public static bool IsLittleEndian + { + get + { + return BitConverter.IsLittleEndian; + } + } + + /// + /// 获取或设置屏幕每英寸点数。 + /// + public static float ScreenDpi + { + get; + set; + } + + /// + /// 将像素转换为厘米。 + /// + /// 像素。 + /// 厘米。 + public static float GetCentimetersFromPixels(float pixels) + { + if (ScreenDpi <= 0) + { + throw new GameFrameworkException("You must set screen DPI first."); + } + + return InchesToCentimeters * pixels / ScreenDpi; + } + + /// + /// 将厘米转换为像素。 + /// + /// 厘米。 + /// 像素。 + public static float GetPixelsFromCentimeters(float centimeters) + { + if (ScreenDpi <= 0) + { + throw new GameFrameworkException("You must set screen DPI first."); + } + + return CentimetersToInches * centimeters * ScreenDpi; + } + + /// + /// 将像素转换为英寸。 + /// + /// 像素。 + /// 英寸。 + public static float GetInchesFromPixels(float pixels) + { + if (ScreenDpi <= 0) + { + throw new GameFrameworkException("You must set screen DPI first."); + } + + return pixels / ScreenDpi; + } + + /// + /// 将英寸转换为像素。 + /// + /// 英寸。 + /// 像素。 + public static float GetPixelsFromInches(float inches) + { + if (ScreenDpi <= 0) + { + throw new GameFrameworkException("You must set screen DPI first."); + } + + return inches * ScreenDpi; + } + + /// + /// 以字节数组的形式获取指定的布尔值。 + /// + /// 要转换的布尔值。 + /// 用于存放结果的字节数组。 + public static byte[] GetBytes(bool value) + { + byte[] buffer = new byte[1]; + GetBytes(value, buffer, 0); + return buffer; + } + + /// + /// 以字节数组的形式获取指定的布尔值。 + /// + /// 要转换的布尔值。 + /// 用于存放结果的字节数组。 + public static void GetBytes(bool value, byte[] buffer) + { + GetBytes(value, buffer, 0); + } + + /// + /// 以字节数组的形式获取指定的布尔值。 + /// + /// 要转换的布尔值。 + /// 用于存放结果的字节数组。 + /// buffer 内的起始位置。 + public static void GetBytes(bool value, byte[] buffer, int startIndex) + { + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + if (startIndex < 0 || startIndex + 1 > buffer.Length) + { + throw new GameFrameworkException("Start index is invalid."); + } + + buffer[startIndex] = value ? (byte)1 : (byte)0; + } + + /// + /// 返回由字节数组中首字节转换来的布尔值。 + /// + /// 字节数组。 + /// 如果 value 中的首字节非零,则为 true,否则为 false。 + public static bool GetBoolean(byte[] value) + { + return BitConverter.ToBoolean(value, 0); + } + + /// + /// 返回由字节数组中指定位置的一个字节转换来的布尔值。 + /// + /// 字节数组。 + /// value 内的起始位置。 + /// 如果 value 中指定位置的字节非零,则为 true,否则为 false。 + public static bool GetBoolean(byte[] value, int startIndex) + { + return BitConverter.ToBoolean(value, startIndex); + } + + /// + /// 以字节数组的形式获取指定的 Unicode 字符值。 + /// + /// 要转换的字符。 + /// 用于存放结果的字节数组。 + public static byte[] GetBytes(char value) + { + byte[] buffer = new byte[2]; + GetBytes((short)value, buffer, 0); + return buffer; + } + + /// + /// 以字节数组的形式获取指定的 Unicode 字符值。 + /// + /// 要转换的字符。 + /// 用于存放结果的字节数组。 + public static void GetBytes(char value, byte[] buffer) + { + GetBytes((short)value, buffer, 0); + } + + /// + /// 以字节数组的形式获取指定的 Unicode 字符值。 + /// + /// 要转换的字符。 + /// 用于存放结果的字节数组。 + /// buffer 内的起始位置。 + public static void GetBytes(char value, byte[] buffer, int startIndex) + { + GetBytes((short)value, buffer, startIndex); + } + + /// + /// 返回由字节数组中前两个字节转换来的 Unicode 字符。 + /// + /// 字节数组。 + /// 由两个字节构成的字符。 + public static char GetChar(byte[] value) + { + return BitConverter.ToChar(value, 0); + } + + /// + /// 返回由字节数组中指定位置的两个字节转换来的 Unicode 字符。 + /// + /// 字节数组。 + /// value 内的起始位置。 + /// 由两个字节构成的字符。 + public static char GetChar(byte[] value, int startIndex) + { + return BitConverter.ToChar(value, startIndex); + } + + /// + /// 以字节数组的形式获取指定的 16 位有符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static byte[] GetBytes(short value) + { + byte[] buffer = new byte[2]; + GetBytes(value, buffer, 0); + return buffer; + } + + /// + /// 以字节数组的形式获取指定的 16 位有符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static void GetBytes(short value, byte[] buffer) + { + GetBytes(value, buffer, 0); + } + + /// + /// 以字节数组的形式获取指定的 16 位有符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + /// buffer 内的起始位置。 + public static unsafe void GetBytes(short value, byte[] buffer, int startIndex) + { + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + if (startIndex < 0 || startIndex + 2 > buffer.Length) + { + throw new GameFrameworkException("Start index is invalid."); + } + + fixed (byte* valueRef = buffer) + { + *(short*)(valueRef + startIndex) = value; + } + } + + /// + /// 返回由字节数组中前两个字节转换来的 16 位有符号整数。 + /// + /// 字节数组。 + /// 由两个字节构成的 16 位有符号整数。 + public static short GetInt16(byte[] value) + { + return BitConverter.ToInt16(value, 0); + } + + /// + /// 返回由字节数组中指定位置的两个字节转换来的 16 位有符号整数。 + /// + /// 字节数组。 + /// value 内的起始位置。 + /// 由两个字节构成的 16 位有符号整数。 + public static short GetInt16(byte[] value, int startIndex) + { + return BitConverter.ToInt16(value, startIndex); + } + + /// + /// 以字节数组的形式获取指定的 16 位无符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static byte[] GetBytes(ushort value) + { + byte[] buffer = new byte[2]; + GetBytes((short)value, buffer, 0); + return buffer; + } + + /// + /// 以字节数组的形式获取指定的 16 位无符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static void GetBytes(ushort value, byte[] buffer) + { + GetBytes((short)value, buffer, 0); + } + + /// + /// 以字节数组的形式获取指定的 16 位无符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + /// buffer 内的起始位置。 + public static void GetBytes(ushort value, byte[] buffer, int startIndex) + { + GetBytes((short)value, buffer, startIndex); + } + + /// + /// 返回由字节数组中前两个字节转换来的 16 位无符号整数。 + /// + /// 字节数组。 + /// 由两个字节构成的 16 位无符号整数。 + public static ushort GetUInt16(byte[] value) + { + return BitConverter.ToUInt16(value, 0); + } + + /// + /// 返回由字节数组中指定位置的两个字节转换来的 16 位无符号整数。 + /// + /// 字节数组。 + /// value 内的起始位置。 + /// 由两个字节构成的 16 位无符号整数。 + public static ushort GetUInt16(byte[] value, int startIndex) + { + return BitConverter.ToUInt16(value, startIndex); + } + + /// + /// 以字节数组的形式获取指定的 32 位有符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static byte[] GetBytes(int value) + { + byte[] buffer = new byte[4]; + GetBytes(value, buffer, 0); + return buffer; + } + + /// + /// 以字节数组的形式获取指定的 32 位有符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static void GetBytes(int value, byte[] buffer) + { + GetBytes(value, buffer, 0); + } + + /// + /// 以字节数组的形式获取指定的 32 位有符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + /// buffer 内的起始位置。 + public static unsafe void GetBytes(int value, byte[] buffer, int startIndex) + { + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + if (startIndex < 0 || startIndex + 4 > buffer.Length) + { + throw new GameFrameworkException("Start index is invalid."); + } + + fixed (byte* valueRef = buffer) + { + *(int*)(valueRef + startIndex) = value; + } + } + + /// + /// 返回由字节数组中前四个字节转换来的 32 位有符号整数。 + /// + /// 字节数组。 + /// 由四个字节构成的 32 位有符号整数。 + public static int GetInt32(byte[] value) + { + return BitConverter.ToInt32(value, 0); + } + + /// + /// 返回由字节数组中指定位置的四个字节转换来的 32 位有符号整数。 + /// + /// 字节数组。 + /// value 内的起始位置。 + /// 由四个字节构成的 32 位有符号整数。 + public static int GetInt32(byte[] value, int startIndex) + { + return BitConverter.ToInt32(value, startIndex); + } + + /// + /// 以字节数组的形式获取指定的 32 位无符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static byte[] GetBytes(uint value) + { + byte[] buffer = new byte[4]; + GetBytes((int)value, buffer, 0); + return buffer; + } + + /// + /// 以字节数组的形式获取指定的 32 位无符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static void GetBytes(uint value, byte[] buffer) + { + GetBytes((int)value, buffer, 0); + } + + /// + /// 以字节数组的形式获取指定的 32 位无符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + /// buffer 内的起始位置。 + public static void GetBytes(uint value, byte[] buffer, int startIndex) + { + GetBytes((int)value, buffer, startIndex); + } + + /// + /// 返回由字节数组中前四个字节转换来的 32 位无符号整数。 + /// + /// 字节数组。 + /// 由四个字节构成的 32 位无符号整数。 + public static uint GetUInt32(byte[] value) + { + return BitConverter.ToUInt32(value, 0); + } + + /// + /// 返回由字节数组中指定位置的四个字节转换来的 32 位无符号整数。 + /// + /// 字节数组。 + /// value 内的起始位置。 + /// 由四个字节构成的 32 位无符号整数。 + public static uint GetUInt32(byte[] value, int startIndex) + { + return BitConverter.ToUInt32(value, startIndex); + } + + /// + /// 以字节数组的形式获取指定的 64 位有符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static byte[] GetBytes(long value) + { + byte[] buffer = new byte[8]; + GetBytes(value, buffer, 0); + return buffer; + } + + /// + /// 以字节数组的形式获取指定的 64 位有符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static void GetBytes(long value, byte[] buffer) + { + GetBytes(value, buffer, 0); + } + + /// + /// 以字节数组的形式获取指定的 64 位有符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + /// buffer 内的起始位置。 + public static unsafe void GetBytes(long value, byte[] buffer, int startIndex) + { + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + if (startIndex < 0 || startIndex + 8 > buffer.Length) + { + throw new GameFrameworkException("Start index is invalid."); + } + + fixed (byte* valueRef = buffer) + { + *(long*)(valueRef + startIndex) = value; + } + } + + /// + /// 返回由字节数组中前八个字节转换来的 64 位有符号整数。 + /// + /// 字节数组。 + /// 由八个字节构成的 64 位有符号整数。 + public static long GetInt64(byte[] value) + { + return BitConverter.ToInt64(value, 0); + } + + /// + /// 返回由字节数组中指定位置的八个字节转换来的 64 位有符号整数。 + /// + /// 字节数组。 + /// value 内的起始位置。 + /// 由八个字节构成的 64 位有符号整数。 + public static long GetInt64(byte[] value, int startIndex) + { + return BitConverter.ToInt64(value, startIndex); + } + + /// + /// 以字节数组的形式获取指定的 64 位无符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static byte[] GetBytes(ulong value) + { + byte[] buffer = new byte[8]; + GetBytes((long)value, buffer, 0); + return buffer; + } + + /// + /// 以字节数组的形式获取指定的 64 位无符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static void GetBytes(ulong value, byte[] buffer) + { + GetBytes((long)value, buffer, 0); + } + + /// + /// 以字节数组的形式获取指定的 64 位无符号整数值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + /// buffer 内的起始位置。 + public static void GetBytes(ulong value, byte[] buffer, int startIndex) + { + GetBytes((long)value, buffer, startIndex); + } + + /// + /// 返回由字节数组中前八个字节转换来的 64 位无符号整数。 + /// + /// 字节数组。 + /// 由八个字节构成的 64 位无符号整数。 + public static ulong GetUInt64(byte[] value) + { + return BitConverter.ToUInt64(value, 0); + } + + /// + /// 返回由字节数组中指定位置的八个字节转换来的 64 位无符号整数。 + /// + /// 字节数组。 + /// value 内的起始位置。 + /// 由八个字节构成的 64 位无符号整数。 + public static ulong GetUInt64(byte[] value, int startIndex) + { + return BitConverter.ToUInt64(value, startIndex); + } + + /// + /// 以字节数组的形式获取指定的单精度浮点值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static unsafe byte[] GetBytes(float value) + { + byte[] buffer = new byte[4]; + GetBytes(*(int*)&value, buffer, 0); + return buffer; + } + + /// + /// 以字节数组的形式获取指定的单精度浮点值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static unsafe void GetBytes(float value, byte[] buffer) + { + GetBytes(*(int*)&value, buffer, 0); + } + + /// + /// 以字节数组的形式获取指定的单精度浮点值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + /// buffer 内的起始位置。 + public static unsafe void GetBytes(float value, byte[] buffer, int startIndex) + { + GetBytes(*(int*)&value, buffer, startIndex); + } + + /// + /// 返回由字节数组中前四个字节转换来的单精度浮点数。 + /// + /// 字节数组。 + /// 由四个字节构成的单精度浮点数。 + public static float GetSingle(byte[] value) + { + return BitConverter.ToSingle(value, 0); + } + + /// + /// 返回由字节数组中指定位置的四个字节转换来的单精度浮点数。 + /// + /// 字节数组。 + /// value 内的起始位置。 + /// 由四个字节构成的单精度浮点数。 + public static float GetSingle(byte[] value, int startIndex) + { + return BitConverter.ToSingle(value, startIndex); + } + + /// + /// 以字节数组的形式获取指定的双精度浮点值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static unsafe byte[] GetBytes(double value) + { + byte[] buffer = new byte[8]; + GetBytes(*(long*)&value, buffer, 0); + return buffer; + } + + /// + /// 以字节数组的形式获取指定的双精度浮点值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + public static unsafe void GetBytes(double value, byte[] buffer) + { + GetBytes(*(long*)&value, buffer, 0); + } + + /// + /// 以字节数组的形式获取指定的双精度浮点值。 + /// + /// 要转换的数字。 + /// 用于存放结果的字节数组。 + /// buffer 内的起始位置。 + public static unsafe void GetBytes(double value, byte[] buffer, int startIndex) + { + GetBytes(*(long*)&value, buffer, startIndex); + } + + /// + /// 返回由字节数组中前八个字节转换来的双精度浮点数。 + /// + /// 字节数组。 + /// 由八个字节构成的双精度浮点数。 + public static double GetDouble(byte[] value) + { + return BitConverter.ToDouble(value, 0); + } + + /// + /// 返回由字节数组中指定位置的八个字节转换来的双精度浮点数。 + /// + /// 字节数组。 + /// value 内的起始位置。 + /// 由八个字节构成的双精度浮点数。 + public static double GetDouble(byte[] value, int startIndex) + { + return BitConverter.ToDouble(value, startIndex); + } + + /// + /// 以字节数组的形式获取 UTF-8 编码的字符串。 + /// + /// 要转换的字符串。 + /// 用于存放结果的字节数组。 + public static byte[] GetBytes(string value) + { + return GetBytes(value, Encoding.UTF8); + } + + /// + /// 以字节数组的形式获取 UTF-8 编码的字符串。 + /// + /// 要转换的字符串。 + /// 用于存放结果的字节数组。 + /// buffer 内实际填充了多少字节。 + public static int GetBytes(string value, byte[] buffer) + { + return GetBytes(value, Encoding.UTF8, buffer, 0); + } + + /// + /// 以字节数组的形式获取 UTF-8 编码的字符串。 + /// + /// 要转换的字符串。 + /// 用于存放结果的字节数组。 + /// buffer 内的起始位置。 + /// buffer 内实际填充了多少字节。 + public static int GetBytes(string value, byte[] buffer, int startIndex) + { + return GetBytes(value, Encoding.UTF8, buffer, startIndex); + } + + /// + /// 以字节数组的形式获取指定编码的字符串。 + /// + /// 要转换的字符串。 + /// 要使用的编码。 + /// 用于存放结果的字节数组。 + public static byte[] GetBytes(string value, Encoding encoding) + { + if (value == null) + { + throw new GameFrameworkException("Value is invalid."); + } + + if (encoding == null) + { + throw new GameFrameworkException("Encoding is invalid."); + } + + return encoding.GetBytes(value); + } + + /// + /// 以字节数组的形式获取指定编码的字符串。 + /// + /// 要转换的字符串。 + /// 要使用的编码。 + /// 用于存放结果的字节数组。 + /// buffer 内实际填充了多少字节。 + public static int GetBytes(string value, Encoding encoding, byte[] buffer) + { + return GetBytes(value, encoding, buffer, 0); + } + + /// + /// 以字节数组的形式获取指定编码的字符串。 + /// + /// 要转换的字符串。 + /// 要使用的编码。 + /// 用于存放结果的字节数组。 + /// buffer 内的起始位置。 + /// buffer 内实际填充了多少字节。 + public static int GetBytes(string value, Encoding encoding, byte[] buffer, int startIndex) + { + if (value == null) + { + throw new GameFrameworkException("Value is invalid."); + } + + if (encoding == null) + { + throw new GameFrameworkException("Encoding is invalid."); + } + + return encoding.GetBytes(value, 0, value.Length, buffer, startIndex); + } + + /// + /// 返回由字节数组使用 UTF-8 编码转换成的字符串。 + /// + /// 字节数组。 + /// 转换后的字符串。 + public static string GetString(byte[] value) + { + return GetString(value, Encoding.UTF8); + } + + /// + /// 返回由字节数组使用指定编码转换成的字符串。 + /// + /// 字节数组。 + /// 要使用的编码。 + /// 转换后的字符串。 + public static string GetString(byte[] value, Encoding encoding) + { + if (value == null) + { + throw new GameFrameworkException("Value is invalid."); + } + + if (encoding == null) + { + throw new GameFrameworkException("Encoding is invalid."); + } + + return encoding.GetString(value); + } + + /// + /// 返回由字节数组使用 UTF-8 编码转换成的字符串。 + /// + /// 字节数组。 + /// value 内的起始位置。 + /// 长度。 + /// 转换后的字符串。 + public static string GetString(byte[] value, int startIndex, int length) + { + return GetString(value, startIndex, length, Encoding.UTF8); + } + + /// + /// 返回由字节数组使用指定编码转换成的字符串。 + /// + /// 字节数组。 + /// value 内的起始位置。 + /// 长度。 + /// 要使用的编码。 + /// 转换后的字符串。 + public static string GetString(byte[] value, int startIndex, int length, Encoding encoding) + { + if (value == null) + { + throw new GameFrameworkException("Value is invalid."); + } + + if (encoding == null) + { + throw new GameFrameworkException("Encoding is invalid."); + } + + return encoding.GetString(value, startIndex, length); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Converter.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Converter.cs.meta new file mode 100644 index 0000000..6498977 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Converter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ad024314ea72bb34fa1477a414887b1f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Encryption.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Encryption.cs new file mode 100644 index 0000000..ae40afc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Encryption.cs @@ -0,0 +1,134 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework +{ + public static partial class Utility + { + /// + /// 加密解密相关的实用函数。 + /// + public static class Encryption + { + internal const int QuickEncryptLength = 220; + + /// + /// 将 bytes 使用 code 做异或运算的快速版本。 + /// + /// 原始二进制流。 + /// 异或二进制流。 + /// 异或后的二进制流。 + public static byte[] GetQuickXorBytes(byte[] bytes, byte[] code) + { + return GetXorBytes(bytes, 0, QuickEncryptLength, code); + } + + /// + /// 将 bytes 使用 code 做异或运算的快速版本。此方法将复用并改写传入的 bytes 作为返回值,而不额外分配内存空间。 + /// + /// 原始及异或后的二进制流。 + /// 异或二进制流。 + public static void GetQuickSelfXorBytes(byte[] bytes, byte[] code) + { + GetSelfXorBytes(bytes, 0, QuickEncryptLength, code); + } + + /// + /// 将 bytes 使用 code 做异或运算。 + /// + /// 原始二进制流。 + /// 异或二进制流。 + /// 异或后的二进制流。 + public static byte[] GetXorBytes(byte[] bytes, byte[] code) + { + if (bytes == null) + { + return null; + } + + return GetXorBytes(bytes, 0, bytes.Length, code); + } + + /// + /// 将 bytes 使用 code 做异或运算。此方法将复用并改写传入的 bytes 作为返回值,而不额外分配内存空间。 + /// + /// 原始及异或后的二进制流。 + /// 异或二进制流。 + public static void GetSelfXorBytes(byte[] bytes, byte[] code) + { + if (bytes == null) + { + return; + } + + GetSelfXorBytes(bytes, 0, bytes.Length, code); + } + + /// + /// 将 bytes 使用 code 做异或运算。 + /// + /// 原始二进制流。 + /// 异或计算的开始位置。 + /// 异或计算长度,若小于 0,则计算整个二进制流。 + /// 异或二进制流。 + /// 异或后的二进制流。 + public static byte[] GetXorBytes(byte[] bytes, int startIndex, int length, byte[] code) + { + if (bytes == null) + { + return null; + } + + int bytesLength = bytes.Length; + byte[] results = new byte[bytesLength]; + Array.Copy(bytes, 0, results, 0, bytesLength); + GetSelfXorBytes(results, startIndex, length, code); + return results; + } + + /// + /// 将 bytes 使用 code 做异或运算。此方法将复用并改写传入的 bytes 作为返回值,而不额外分配内存空间。 + /// + /// 原始及异或后的二进制流。 + /// 异或计算的开始位置。 + /// 异或计算长度。 + /// 异或二进制流。 + public static void GetSelfXorBytes(byte[] bytes, int startIndex, int length, byte[] code) + { + if (bytes == null) + { + return; + } + + if (code == null) + { + throw new GameFrameworkException("Code is invalid."); + } + + int codeLength = code.Length; + if (codeLength <= 0) + { + throw new GameFrameworkException("Code length is invalid."); + } + + if (startIndex < 0 || length < 0 || startIndex + length > bytes.Length) + { + throw new GameFrameworkException("Start index or length is invalid."); + } + + int codeIndex = startIndex % codeLength; + for (int i = startIndex; i < length; i++) + { + bytes[i] ^= code[codeIndex++]; + codeIndex %= codeLength; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Encryption.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Encryption.cs.meta new file mode 100644 index 0000000..667c7fc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Encryption.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eaf16ba2a46cb9945bc28e37b6bf7da8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Json.IJsonHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Json.IJsonHelper.cs new file mode 100644 index 0000000..04e6385 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Json.IJsonHelper.cs @@ -0,0 +1,46 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework +{ + public static partial class Utility + { + public static partial class Json + { + /// + /// JSON 辅助器接口。 + /// + public interface IJsonHelper + { + /// + /// 将对象序列化为 JSON 字符串。 + /// + /// 要序列化的对象。 + /// 序列化后的 JSON 字符串。 + string ToJson(object obj); + + /// + /// 将 JSON 字符串反序列化为对象。 + /// + /// 对象类型。 + /// 要反序列化的 JSON 字符串。 + /// 反序列化后的对象。 + T ToObject(string json); + + /// + /// 将 JSON 字符串反序列化为对象。 + /// + /// 对象类型。 + /// 要反序列化的 JSON 字符串。 + /// 反序列化后的对象。 + object ToObject(Type objectType, string json); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Json.IJsonHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Json.IJsonHelper.cs.meta new file mode 100644 index 0000000..a9f0615 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Json.IJsonHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fc8ca8ec9911cb84faa9f71b4fb651a5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Json.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Json.cs new file mode 100644 index 0000000..d522db1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Json.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework +{ + public static partial class Utility + { + /// + /// JSON 相关的实用函数。 + /// + public static partial class Json + { + private static IJsonHelper s_JsonHelper = null; + + /// + /// 设置 JSON 辅助器。 + /// + /// 要设置的 JSON 辅助器。 + public static void SetJsonHelper(IJsonHelper jsonHelper) + { + s_JsonHelper = jsonHelper; + } + + /// + /// 将对象序列化为 JSON 字符串。 + /// + /// 要序列化的对象。 + /// 序列化后的 JSON 字符串。 + public static string ToJson(object obj) + { + if (s_JsonHelper == null) + { + throw new GameFrameworkException("JSON helper is invalid."); + } + + try + { + return s_JsonHelper.ToJson(obj); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Text.Format("Can not convert to JSON with exception '{0}'.", exception), exception); + } + } + + /// + /// 将 JSON 字符串反序列化为对象。 + /// + /// 对象类型。 + /// 要反序列化的 JSON 字符串。 + /// 反序列化后的对象。 + public static T ToObject(string json) + { + if (s_JsonHelper == null) + { + throw new GameFrameworkException("JSON helper is invalid."); + } + + try + { + return s_JsonHelper.ToObject(json); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Text.Format("Can not convert to object with exception '{0}'.", exception), exception); + } + } + + /// + /// 将 JSON 字符串反序列化为对象。 + /// + /// 对象类型。 + /// 要反序列化的 JSON 字符串。 + /// 反序列化后的对象。 + public static object ToObject(Type objectType, string json) + { + if (s_JsonHelper == null) + { + throw new GameFrameworkException("JSON helper is invalid."); + } + + if (objectType == null) + { + throw new GameFrameworkException("Object type is invalid."); + } + + try + { + return s_JsonHelper.ToObject(objectType, json); + } + catch (Exception exception) + { + if (exception is GameFrameworkException) + { + throw; + } + + throw new GameFrameworkException(Text.Format("Can not convert to object with exception '{0}'.", exception), exception); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Json.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Json.cs.meta new file mode 100644 index 0000000..7cf1265 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Json.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ccb42a278568d5444b1f52b1bdd798d8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Marshal.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Marshal.cs new file mode 100644 index 0000000..9f238e7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Marshal.cs @@ -0,0 +1,240 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework +{ + public static partial class Utility + { + /// + /// Marshal 相关的实用函数。 + /// + public static class Marshal + { + private const int BlockSize = 1024 * 4; + private static IntPtr s_CachedHGlobalPtr = IntPtr.Zero; + private static int s_CachedHGlobalSize = 0; + + /// + /// 获取缓存的从进程的非托管内存中分配的内存的大小。 + /// + public static int CachedHGlobalSize + { + get + { + return s_CachedHGlobalSize; + } + } + + /// + /// 确保从进程的非托管内存中分配足够大小的内存并缓存。 + /// + /// 要确保从进程的非托管内存中分配内存的大小。 + public static void EnsureCachedHGlobalSize(int ensureSize) + { + if (ensureSize < 0) + { + throw new GameFrameworkException("Ensure size is invalid."); + } + + if (s_CachedHGlobalPtr == IntPtr.Zero || s_CachedHGlobalSize < ensureSize) + { + FreeCachedHGlobal(); + int size = (ensureSize - 1 + BlockSize) / BlockSize * BlockSize; + s_CachedHGlobalPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(size); + s_CachedHGlobalSize = size; + } + } + + /// + /// 释放缓存的从进程的非托管内存中分配的内存。 + /// + public static void FreeCachedHGlobal() + { + if (s_CachedHGlobalPtr != IntPtr.Zero) + { + System.Runtime.InteropServices.Marshal.FreeHGlobal(s_CachedHGlobalPtr); + s_CachedHGlobalPtr = IntPtr.Zero; + s_CachedHGlobalSize = 0; + } + } + + /// + /// 将数据从对象转换为二进制流。 + /// + /// 要转换的对象的类型。 + /// 要转换的对象。 + /// 存储转换结果的二进制流。 + public static byte[] StructureToBytes(T structure) + { + return StructureToBytes(structure, System.Runtime.InteropServices.Marshal.SizeOf(typeof(T))); + } + + /// + /// 将数据从对象转换为二进制流。 + /// + /// 要转换的对象的类型。 + /// 要转换的对象。 + /// 要转换的对象的大小。 + /// 存储转换结果的二进制流。 + internal static byte[] StructureToBytes(T structure, int structureSize) + { + if (structureSize < 0) + { + throw new GameFrameworkException("Structure size is invalid."); + } + + EnsureCachedHGlobalSize(structureSize); + System.Runtime.InteropServices.Marshal.StructureToPtr(structure, s_CachedHGlobalPtr, true); + byte[] result = new byte[structureSize]; + System.Runtime.InteropServices.Marshal.Copy(s_CachedHGlobalPtr, result, 0, structureSize); + return result; + } + + /// + /// 将数据从对象转换为二进制流。 + /// + /// 要转换的对象的类型。 + /// 要转换的对象。 + /// 存储转换结果的二进制流。 + public static void StructureToBytes(T structure, byte[] result) + { + StructureToBytes(structure, System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), result, 0); + } + + /// + /// 将数据从对象转换为二进制流。 + /// + /// 要转换的对象的类型。 + /// 要转换的对象。 + /// 要转换的对象的大小。 + /// 存储转换结果的二进制流。 + internal static void StructureToBytes(T structure, int structureSize, byte[] result) + { + StructureToBytes(structure, structureSize, result, 0); + } + + /// + /// 将数据从对象转换为二进制流。 + /// + /// 要转换的对象的类型。 + /// 要转换的对象。 + /// 存储转换结果的二进制流。 + /// 写入存储转换结果的二进制流的起始位置。 + public static void StructureToBytes(T structure, byte[] result, int startIndex) + { + StructureToBytes(structure, System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), result, startIndex); + } + + /// + /// 将数据从对象转换为二进制流。 + /// + /// 要转换的对象的类型。 + /// 要转换的对象。 + /// 要转换的对象的大小。 + /// 存储转换结果的二进制流。 + /// 写入存储转换结果的二进制流的起始位置。 + internal static void StructureToBytes(T structure, int structureSize, byte[] result, int startIndex) + { + if (structureSize < 0) + { + throw new GameFrameworkException("Structure size is invalid."); + } + + if (result == null) + { + throw new GameFrameworkException("Result is invalid."); + } + + if (startIndex < 0) + { + throw new GameFrameworkException("Start index is invalid."); + } + + if (startIndex + structureSize > result.Length) + { + throw new GameFrameworkException("Result length is not enough."); + } + + EnsureCachedHGlobalSize(structureSize); + System.Runtime.InteropServices.Marshal.StructureToPtr(structure, s_CachedHGlobalPtr, true); + System.Runtime.InteropServices.Marshal.Copy(s_CachedHGlobalPtr, result, startIndex, structureSize); + } + + /// + /// 将数据从二进制流转换为对象。 + /// + /// 要转换的对象的类型。 + /// 要转换的二进制流。 + /// 存储转换结果的对象。 + public static T BytesToStructure(byte[] buffer) + { + return BytesToStructure(System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), buffer, 0); + } + + /// + /// 将数据从二进制流转换为对象。 + /// + /// 要转换的对象的类型。 + /// 要转换的二进制流。 + /// 读取要转换的二进制流的起始位置。 + /// 存储转换结果的对象。 + public static T BytesToStructure(byte[] buffer, int startIndex) + { + return BytesToStructure(System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)), buffer, startIndex); + } + + /// + /// 将数据从二进制流转换为对象。 + /// + /// 要转换的对象的类型。 + /// 要转换的对象的大小。 + /// 要转换的二进制流。 + /// 存储转换结果的对象。 + internal static T BytesToStructure(int structureSize, byte[] buffer) + { + return BytesToStructure(structureSize, buffer, 0); + } + + /// + /// 将数据从二进制流转换为对象。 + /// + /// 要转换的对象的类型。 + /// 要转换的对象的大小。 + /// 要转换的二进制流。 + /// 读取要转换的二进制流的起始位置。 + /// 存储转换结果的对象。 + internal static T BytesToStructure(int structureSize, byte[] buffer, int startIndex) + { + if (structureSize < 0) + { + throw new GameFrameworkException("Structure size is invalid."); + } + + if (buffer == null) + { + throw new GameFrameworkException("Buffer is invalid."); + } + + if (startIndex < 0) + { + throw new GameFrameworkException("Start index is invalid."); + } + + if (startIndex + structureSize > buffer.Length) + { + throw new GameFrameworkException("Buffer length is not enough."); + } + + EnsureCachedHGlobalSize(structureSize); + System.Runtime.InteropServices.Marshal.Copy(buffer, startIndex, s_CachedHGlobalPtr, structureSize); + return (T)System.Runtime.InteropServices.Marshal.PtrToStructure(s_CachedHGlobalPtr, typeof(T)); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Marshal.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Marshal.cs.meta new file mode 100644 index 0000000..976aa19 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Marshal.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d1c8a66fce3964f4588dda74e6b49919 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Path.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Path.cs new file mode 100644 index 0000000..9311135 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Path.cs @@ -0,0 +1,100 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.IO; + +namespace GameFramework +{ + public static partial class Utility + { + /// + /// 路径相关的实用函数。 + /// + public static class Path + { + /// + /// 获取规范的路径。 + /// + /// 要规范的路径。 + /// 规范的路径。 + public static string GetRegularPath(string path) + { + if (path == null) + { + return null; + } + + return path.Replace('\\', '/'); + } + + /// + /// 获取远程格式的路径(带有file:// 或 http:// 前缀)。 + /// + /// 原始路径。 + /// 远程格式路径。 + public static string GetRemotePath(string path) + { + string regularPath = GetRegularPath(path); + if (regularPath == null) + { + return null; + } + + return regularPath.Contains("://") ? regularPath : ("file:///" + regularPath).Replace("file:////", "file:///"); + } + + /// + /// 移除空文件夹。 + /// + /// 要处理的文件夹名称。 + /// 是否移除空文件夹成功。 + public static bool RemoveEmptyDirectory(string directoryName) + { + if (string.IsNullOrEmpty(directoryName)) + { + throw new GameFrameworkException("Directory name is invalid."); + } + + try + { + if (!Directory.Exists(directoryName)) + { + return false; + } + + // 不使用 SearchOption.AllDirectories,以便于在可能产生异常的环境下删除尽可能多的目录 + string[] subDirectoryNames = Directory.GetDirectories(directoryName, "*"); + int subDirectoryCount = subDirectoryNames.Length; + foreach (string subDirectoryName in subDirectoryNames) + { + if (RemoveEmptyDirectory(subDirectoryName)) + { + subDirectoryCount--; + } + } + + if (subDirectoryCount > 0) + { + return false; + } + + if (Directory.GetFiles(directoryName, "*").Length > 0) + { + return false; + } + + Directory.Delete(directoryName); + return true; + } + catch + { + return false; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Path.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Path.cs.meta new file mode 100644 index 0000000..d0ba2ff --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Path.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3595ba8a0743b91458204379ef60da6c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Random.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Random.cs new file mode 100644 index 0000000..1bfccf1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Random.cs @@ -0,0 +1,79 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework +{ + public static partial class Utility + { + /// + /// 随机相关的实用函数。 + /// + public static class Random + { + private static System.Random s_Random = new System.Random((int)DateTime.UtcNow.Ticks); + + /// + /// 设置随机数种子。 + /// + /// 随机数种子。 + public static void SetSeed(int seed) + { + s_Random = new System.Random(seed); + } + + /// + /// 返回非负随机数。 + /// + /// 大于等于零且小于 System.Int32.MaxValue 的 32 位带符号整数。 + public static int GetRandom() + { + return s_Random.Next(); + } + + /// + /// 返回一个小于所指定最大值的非负随机数。 + /// + /// 要生成的随机数的上界(随机数不能取该上界值)。maxValue 必须大于等于零。 + /// 大于等于零且小于 maxValue 的 32 位带符号整数,即:返回值的范围通常包括零但不包括 maxValue。不过,如果 maxValue 等于零,则返回 maxValue。 + public static int GetRandom(int maxValue) + { + return s_Random.Next(maxValue); + } + + /// + /// 返回一个指定范围内的随机数。 + /// + /// 返回的随机数的下界(随机数可取该下界值)。 + /// 返回的随机数的上界(随机数不能取该上界值)。maxValue 必须大于等于 minValue。 + /// 一个大于等于 minValue 且小于 maxValue 的 32 位带符号整数,即:返回的值范围包括 minValue 但不包括 maxValue。如果 minValue 等于 maxValue,则返回 minValue。 + public static int GetRandom(int minValue, int maxValue) + { + return s_Random.Next(minValue, maxValue); + } + + /// + /// 返回一个介于 0.0 和 1.0 之间的随机数。 + /// + /// 大于等于 0.0 并且小于 1.0 的双精度浮点数。 + public static double GetRandomDouble() + { + return s_Random.NextDouble(); + } + + /// + /// 用随机数填充指定字节数组的元素。 + /// + /// 包含随机数的字节数组。 + public static void GetRandomBytes(byte[] buffer) + { + s_Random.NextBytes(buffer); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Random.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Random.cs.meta new file mode 100644 index 0000000..2c11839 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Random.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 44c9b20e14037994c98d0cb677471c2a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Text.ITextHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Text.ITextHelper.cs new file mode 100644 index 0000000..a8f115d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Text.ITextHelper.cs @@ -0,0 +1,405 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + public static partial class Utility + { + public static partial class Text + { + /// + /// 字符辅助器接口。 + /// + public interface ITextHelper + { + /// + /// 获取格式化字符串。 + /// + /// 字符串参数的类型。 + /// 字符串格式。 + /// 字符串参数。 + /// 格式化后的字符串。 + string Format(string format, T arg); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串参数 13 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 字符串参数 13。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串参数 13 的类型。 + /// 字符串参数 14 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 字符串参数 13。 + /// 字符串参数 14。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串参数 13 的类型。 + /// 字符串参数 14 的类型。 + /// 字符串参数 15 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 字符串参数 13。 + /// 字符串参数 14。 + /// 字符串参数 15。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串参数 13 的类型。 + /// 字符串参数 14 的类型。 + /// 字符串参数 15 的类型。 + /// 字符串参数 16 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 字符串参数 13。 + /// 字符串参数 14。 + /// 字符串参数 15。 + /// 字符串参数 16。 + /// 格式化后的字符串。 + string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Text.ITextHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Text.ITextHelper.cs.meta new file mode 100644 index 0000000..25230cc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Text.ITextHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 307f762c164f0794ab24bfba8df1cb7a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Text.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Text.cs new file mode 100644 index 0000000..e5e5ccd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Text.cs @@ -0,0 +1,621 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + public static partial class Utility + { + /// + /// 字符相关的实用函数。 + /// + public static partial class Text + { + private static ITextHelper s_TextHelper = null; + + /// + /// 设置字符辅助器。 + /// + /// 要设置的字符辅助器。 + public static void SetTextHelper(ITextHelper textHelper) + { + s_TextHelper = textHelper; + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数的类型。 + /// 字符串格式。 + /// 字符串参数。 + /// 格式化后的字符串。 + public static string Format(string format, T arg) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg); + } + + return s_TextHelper.Format(format, arg); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2); + } + + return s_TextHelper.Format(format, arg1, arg2); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4, arg5); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4, arg5); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4, arg5, arg6); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4, arg5, arg6); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串参数 13 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 字符串参数 13。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串参数 13 的类型。 + /// 字符串参数 14 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 字符串参数 13。 + /// 字符串参数 14。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串参数 13 的类型。 + /// 字符串参数 14 的类型。 + /// 字符串参数 15 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 字符串参数 13。 + /// 字符串参数 14。 + /// 字符串参数 15。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串参数 13 的类型。 + /// 字符串参数 14 的类型。 + /// 字符串参数 15 的类型。 + /// 字符串参数 16 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 字符串参数 13。 + /// 字符串参数 14。 + /// 字符串参数 15。 + /// 字符串参数 16。 + /// 格式化后的字符串。 + public static string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + if (s_TextHelper == null) + { + return string.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); + } + + return s_TextHelper.Format(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Text.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Text.cs.meta new file mode 100644 index 0000000..f152514 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Text.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 24bccde1da28e4e41b23d685a3717db6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Verifier.Crc32.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Verifier.Crc32.cs new file mode 100644 index 0000000..673677d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Verifier.Crc32.cs @@ -0,0 +1,94 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + public static partial class Utility + { + public static partial class Verifier + { + /// + /// CRC32 算法。 + /// + private sealed class Crc32 + { + private const int TableLength = 256; + private const uint DefaultPolynomial = 0xedb88320; + private const uint DefaultSeed = 0xffffffff; + + private readonly uint m_Seed; + private readonly uint[] m_Table; + private uint m_Hash; + + public Crc32() + : this(DefaultPolynomial, DefaultSeed) + { + } + + public Crc32(uint polynomial, uint seed) + { + m_Seed = seed; + m_Table = InitializeTable(polynomial); + m_Hash = seed; + } + + public void Initialize() + { + m_Hash = m_Seed; + } + + public void HashCore(byte[] bytes, int offset, int length) + { + m_Hash = CalculateHash(m_Table, m_Hash, bytes, offset, length); + } + + public uint HashFinal() + { + return ~m_Hash; + } + + private static uint CalculateHash(uint[] table, uint value, byte[] bytes, int offset, int length) + { + int last = offset + length; + for (int i = offset; i < last; i++) + { + unchecked + { + value = (value >> 8) ^ table[bytes[i] ^ value & 0xff]; + } + } + + return value; + } + + private static uint[] InitializeTable(uint polynomial) + { + uint[] table = new uint[TableLength]; + for (int i = 0; i < TableLength; i++) + { + uint entry = (uint)i; + for (int j = 0; j < 8; j++) + { + if ((entry & 1) == 1) + { + entry = (entry >> 1) ^ polynomial; + } + else + { + entry >>= 1; + } + } + + table[i] = entry; + } + + return table; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Verifier.Crc32.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Verifier.Crc32.cs.meta new file mode 100644 index 0000000..d009d76 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Verifier.Crc32.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: faf9c03d5beeb1e4a9ae0cd1e8fd80a6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Verifier.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Verifier.cs new file mode 100644 index 0000000..1ab5529 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Verifier.cs @@ -0,0 +1,195 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.IO; + +namespace GameFramework +{ + public static partial class Utility + { + /// + /// 校验相关的实用函数。 + /// + public static partial class Verifier + { + private const int CachedBytesLength = 0x1000; + private static readonly byte[] s_CachedBytes = new byte[CachedBytesLength]; + private static readonly Crc32 s_Algorithm = new Crc32(); + + /// + /// 计算二进制流的 CRC32。 + /// + /// 指定的二进制流。 + /// 计算后的 CRC32。 + public static int GetCrc32(byte[] bytes) + { + if (bytes == null) + { + throw new GameFrameworkException("Bytes is invalid."); + } + + return GetCrc32(bytes, 0, bytes.Length); + } + + /// + /// 计算二进制流的 CRC32。 + /// + /// 指定的二进制流。 + /// 二进制流的偏移。 + /// 二进制流的长度。 + /// 计算后的 CRC32。 + public static int GetCrc32(byte[] bytes, int offset, int length) + { + if (bytes == null) + { + throw new GameFrameworkException("Bytes is invalid."); + } + + if (offset < 0 || length < 0 || offset + length > bytes.Length) + { + throw new GameFrameworkException("Offset or length is invalid."); + } + + s_Algorithm.HashCore(bytes, offset, length); + int result = (int)s_Algorithm.HashFinal(); + s_Algorithm.Initialize(); + return result; + } + + /// + /// 计算二进制流的 CRC32。 + /// + /// 指定的二进制流。 + /// 计算后的 CRC32。 + public static int GetCrc32(Stream stream) + { + if (stream == null) + { + throw new GameFrameworkException("Stream is invalid."); + } + + while (true) + { + int bytesRead = stream.Read(s_CachedBytes, 0, CachedBytesLength); + if (bytesRead > 0) + { + s_Algorithm.HashCore(s_CachedBytes, 0, bytesRead); + } + else + { + break; + } + } + + int result = (int)s_Algorithm.HashFinal(); + s_Algorithm.Initialize(); + Array.Clear(s_CachedBytes, 0, CachedBytesLength); + return result; + } + + /// + /// 获取 CRC32 数值的二进制数组。 + /// + /// CRC32 数值。 + /// CRC32 数值的二进制数组。 + public static byte[] GetCrc32Bytes(int crc32) + { + return new byte[] { (byte)((crc32 >> 24) & 0xff), (byte)((crc32 >> 16) & 0xff), (byte)((crc32 >> 8) & 0xff), (byte)(crc32 & 0xff) }; + } + + /// + /// 获取 CRC32 数值的二进制数组。 + /// + /// CRC32 数值。 + /// 要存放结果的数组。 + public static void GetCrc32Bytes(int crc32, byte[] bytes) + { + GetCrc32Bytes(crc32, bytes, 0); + } + + /// + /// 获取 CRC32 数值的二进制数组。 + /// + /// CRC32 数值。 + /// 要存放结果的数组。 + /// CRC32 数值的二进制数组在结果数组内的起始位置。 + public static void GetCrc32Bytes(int crc32, byte[] bytes, int offset) + { + if (bytes == null) + { + throw new GameFrameworkException("Result is invalid."); + } + + if (offset < 0 || offset + 4 > bytes.Length) + { + throw new GameFrameworkException("Offset or length is invalid."); + } + + bytes[offset] = (byte)((crc32 >> 24) & 0xff); + bytes[offset + 1] = (byte)((crc32 >> 16) & 0xff); + bytes[offset + 2] = (byte)((crc32 >> 8) & 0xff); + bytes[offset + 3] = (byte)(crc32 & 0xff); + } + + internal static int GetCrc32(Stream stream, byte[] code, int length) + { + if (stream == null) + { + throw new GameFrameworkException("Stream is invalid."); + } + + if (code == null) + { + throw new GameFrameworkException("Code is invalid."); + } + + int codeLength = code.Length; + if (codeLength <= 0) + { + throw new GameFrameworkException("Code length is invalid."); + } + + int bytesLength = (int)stream.Length; + if (length < 0 || length > bytesLength) + { + length = bytesLength; + } + + int codeIndex = 0; + while (true) + { + int bytesRead = stream.Read(s_CachedBytes, 0, CachedBytesLength); + if (bytesRead > 0) + { + if (length > 0) + { + for (int i = 0; i < bytesRead && i < length; i++) + { + s_CachedBytes[i] ^= code[codeIndex++]; + codeIndex %= codeLength; + } + + length -= bytesRead; + } + + s_Algorithm.HashCore(s_CachedBytes, 0, bytesRead); + } + else + { + break; + } + } + + int result = (int)s_Algorithm.HashFinal(); + s_Algorithm.Initialize(); + Array.Clear(s_CachedBytes, 0, CachedBytesLength); + return result; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Verifier.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Verifier.cs.meta new file mode 100644 index 0000000..d48180c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.Verifier.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2635809a199845647be4647122414003 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.cs new file mode 100644 index 0000000..f713195 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework +{ + /// + /// 实用函数集。 + /// + public static partial class Utility + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.cs.meta new file mode 100644 index 0000000..cdce1bf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/Utility/Utility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ca58825e822b0544bb50667e99cde3db +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest.meta new file mode 100644 index 0000000..497b607 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: edab58e22a981c24ebbf4b9e64b26f5c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/Constant.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/Constant.cs new file mode 100644 index 0000000..bf5e8f9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/Constant.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.WebRequest +{ + /// + /// Web 请求相关常量。 + /// + internal static class Constant + { + /// + /// 默认 Web 请求任务优先级。 + /// + internal const int DefaultPriority = 0; + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/Constant.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/Constant.cs.meta new file mode 100644 index 0000000..8c85587 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/Constant.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5aa39fab3ac22cf4994d6b228ccd2f64 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/IWebRequestAgentHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/IWebRequestAgentHelper.cs new file mode 100644 index 0000000..994447b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/IWebRequestAgentHelper.cs @@ -0,0 +1,47 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; + +namespace GameFramework.WebRequest +{ + /// + /// Web 请求代理辅助器接口。 + /// + public interface IWebRequestAgentHelper + { + /// + /// Web 请求代理辅助器完成事件。 + /// + event EventHandler WebRequestAgentHelperComplete; + + /// + /// Web 请求代理辅助器错误事件。 + /// + event EventHandler WebRequestAgentHelperError; + + /// + /// 通过 Web 请求代理辅助器发送 Web 请求。 + /// + /// Web 请求地址。 + /// 用户自定义数据。 + void Request(string webRequestUri, object userData); + + /// + /// 通过 Web 请求代理辅助器发送 Web 请求。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// 用户自定义数据。 + void Request(string webRequestUri, byte[] postData, object userData); + + /// + /// 重置 Web 请求代理辅助器。 + /// + void Reset(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/IWebRequestAgentHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/IWebRequestAgentHelper.cs.meta new file mode 100644 index 0000000..71a9616 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/IWebRequestAgentHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 087454fb195eea246a3261448e5fc8f8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/IWebRequestManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/IWebRequestManager.cs new file mode 100644 index 0000000..b51cf55 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/IWebRequestManager.cs @@ -0,0 +1,277 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.WebRequest +{ + /// + /// Web 请求管理器接口。 + /// + public interface IWebRequestManager + { + /// + /// 获取 Web 请求代理总数量。 + /// + int TotalAgentCount + { + get; + } + + /// + /// 获取可用 Web 请求代理数量。 + /// + int FreeAgentCount + { + get; + } + + /// + /// 获取工作中 Web 请求代理数量。 + /// + int WorkingAgentCount + { + get; + } + + /// + /// 获取等待 Web 请求数量。 + /// + int WaitingTaskCount + { + get; + } + + /// + /// 获取或设置 Web 请求超时时长,以秒为单位。 + /// + float Timeout + { + get; + set; + } + + /// + /// Web 请求开始事件。 + /// + event EventHandler WebRequestStart; + + /// + /// Web 请求成功事件。 + /// + event EventHandler WebRequestSuccess; + + /// + /// Web 请求失败事件。 + /// + event EventHandler WebRequestFailure; + + /// + /// 增加 Web 请求代理辅助器。 + /// + /// 要增加的 Web 请求代理辅助器。 + void AddWebRequestAgentHelper(IWebRequestAgentHelper webRequestAgentHelper); + + /// + /// 根据 Web 请求任务的序列编号获取 Web 请求任务的信息。 + /// + /// 要获取信息的 Web 请求任务的序列编号。 + /// Web 请求任务的信息。 + TaskInfo GetWebRequestInfo(int serialId); + + /// + /// 根据 Web 请求任务的标签获取 Web 请求任务的信息。 + /// + /// 要获取信息的 Web 请求任务的标签。 + /// Web 请求任务的信息。 + TaskInfo[] GetWebRequestInfos(string tag); + + /// + /// 根据 Web 请求任务的标签获取 Web 请求任务的信息。 + /// + /// 要获取信息的 Web 请求任务的标签。 + /// Web 请求任务的信息。 + void GetAllWebRequestInfos(string tag, List results); + + /// + /// 获取所有 Web 请求任务的信息。 + /// + /// 所有 Web 请求任务的信息。 + TaskInfo[] GetAllWebRequestInfos(); + + /// + /// 获取所有 Web 请求任务的信息。 + /// + /// 所有 Web 请求任务的信息。 + void GetAllWebRequestInfos(List results); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, byte[] postData); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的标签。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, string tag); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, int priority); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, object userData); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, byte[] postData, string tag); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, byte[] postData, int priority); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, byte[] postData, object userData); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, string tag, int priority); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的标签。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, string tag, object userData); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, int priority, object userData); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, byte[] postData, string tag, int priority); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, byte[] postData, string tag, object userData); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, byte[] postData, int priority, object userData); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, string tag, int priority, object userData); + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + int AddWebRequest(string webRequestUri, byte[] postData, string tag, int priority, object userData); + + /// + /// 根据 Web 请求任务的序列编号移除 Web 请求任务。 + /// + /// 要移除 Web 请求任务的序列编号。 + /// 是否移除 Web 请求任务成功。 + bool RemoveWebRequest(int serialId); + + /// + /// 根据 Web 请求任务的标签移除 Web 请求任务。 + /// + /// 要移除 Web 请求任务的标签。 + /// 移除 Web 请求任务的数量。 + int RemoveWebRequests(string tag); + + /// + /// 移除所有 Web 请求任务。 + /// + /// 移除 Web 请求任务的数量。 + int RemoveAllWebRequests(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/IWebRequestManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/IWebRequestManager.cs.meta new file mode 100644 index 0000000..a8058c1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/IWebRequestManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45df1d440bdd6dc4988347c1ca3a7c3f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestAgentHelperCompleteEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestAgentHelperCompleteEventArgs.cs new file mode 100644 index 0000000..c9ebcab --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestAgentHelperCompleteEventArgs.cs @@ -0,0 +1,54 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.WebRequest +{ + /// + /// Web 请求代理辅助器完成事件。 + /// + public sealed class WebRequestAgentHelperCompleteEventArgs : GameFrameworkEventArgs + { + private byte[] m_WebResponseBytes; + + /// + /// 初始化 Web 请求代理辅助器完成事件的新实例。 + /// + public WebRequestAgentHelperCompleteEventArgs() + { + m_WebResponseBytes = null; + } + + /// + /// 创建 Web 请求代理辅助器完成事件。 + /// + /// Web 响应的数据流。 + /// 创建的 Web 请求代理辅助器完成事件。 + public static WebRequestAgentHelperCompleteEventArgs Create(byte[] webResponseBytes) + { + WebRequestAgentHelperCompleteEventArgs webRequestAgentHelperCompleteEventArgs = ReferencePool.Acquire(); + webRequestAgentHelperCompleteEventArgs.m_WebResponseBytes = webResponseBytes; + return webRequestAgentHelperCompleteEventArgs; + } + + /// + /// 清理 Web 请求代理辅助器完成事件。 + /// + public override void Clear() + { + m_WebResponseBytes = null; + } + + /// + /// 获取 Web 响应的数据流。 + /// + /// Web 响应的数据流。 + public byte[] GetWebResponseBytes() + { + return m_WebResponseBytes; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestAgentHelperCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestAgentHelperCompleteEventArgs.cs.meta new file mode 100644 index 0000000..363f0c1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestAgentHelperCompleteEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2ab455894b86c6246b5c74bc0713ef59 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestAgentHelperErrorEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestAgentHelperErrorEventArgs.cs new file mode 100644 index 0000000..e035d0c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestAgentHelperErrorEventArgs.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.WebRequest +{ + /// + /// Web 请求代理辅助器错误事件。 + /// + public sealed class WebRequestAgentHelperErrorEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化 Web 请求代理辅助器错误事件的新实例。 + /// + public WebRequestAgentHelperErrorEventArgs() + { + ErrorMessage = null; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 创建 Web 请求代理辅助器错误事件。 + /// + /// 错误信息。 + /// 创建的 Web 请求代理辅助器错误事件。 + public static WebRequestAgentHelperErrorEventArgs Create(string errorMessage) + { + WebRequestAgentHelperErrorEventArgs webRequestAgentHelperErrorEventArgs = ReferencePool.Acquire(); + webRequestAgentHelperErrorEventArgs.ErrorMessage = errorMessage; + return webRequestAgentHelperErrorEventArgs; + } + + /// + /// 清理 Web 请求代理辅助器错误事件。 + /// + public override void Clear() + { + ErrorMessage = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestAgentHelperErrorEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestAgentHelperErrorEventArgs.cs.meta new file mode 100644 index 0000000..1212d80 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestAgentHelperErrorEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 879f5108f24ee8143a20f8441a02ba56 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestFailureEventArgs.cs new file mode 100644 index 0000000..72799ee --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestFailureEventArgs.cs @@ -0,0 +1,91 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.WebRequest +{ + /// + /// Web 请求失败事件。 + /// + public sealed class WebRequestFailureEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化 Web 请求失败事件的新实例。 + /// + public WebRequestFailureEventArgs() + { + SerialId = 0; + WebRequestUri = null; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取 Web 请求任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取 Web 请求地址。 + /// + public string WebRequestUri + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建 Web 请求失败事件。 + /// + /// Web 请求任务的序列编号。 + /// Web 请求地址。 + /// 错误信息。 + /// 用户自定义数据。 + /// 创建的 Web 请求失败事件。 + public static WebRequestFailureEventArgs Create(int serialId, string webRequestUri, string errorMessage, object userData) + { + WebRequestFailureEventArgs webRequestFailureEventArgs = ReferencePool.Acquire(); + webRequestFailureEventArgs.SerialId = serialId; + webRequestFailureEventArgs.WebRequestUri = webRequestUri; + webRequestFailureEventArgs.ErrorMessage = errorMessage; + webRequestFailureEventArgs.UserData = userData; + return webRequestFailureEventArgs; + } + + /// + /// 清理 Web 请求失败事件。 + /// + public override void Clear() + { + SerialId = 0; + WebRequestUri = null; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestFailureEventArgs.cs.meta new file mode 100644 index 0000000..3b1a56f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 660f466cc1a44f643bfb3ddc2e3e6b06 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestAgent.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestAgent.cs new file mode 100644 index 0000000..b79d8ad --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestAgent.cs @@ -0,0 +1,176 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.WebRequest +{ + internal sealed partial class WebRequestManager : GameFrameworkModule, IWebRequestManager + { + /// + /// Web 请求代理。 + /// + private sealed class WebRequestAgent : ITaskAgent + { + private readonly IWebRequestAgentHelper m_Helper; + private WebRequestTask m_Task; + private float m_WaitTime; + + public GameFrameworkAction WebRequestAgentStart; + public GameFrameworkAction WebRequestAgentSuccess; + public GameFrameworkAction WebRequestAgentFailure; + + /// + /// 初始化 Web 请求代理的新实例。 + /// + /// Web 请求代理辅助器。 + public WebRequestAgent(IWebRequestAgentHelper webRequestAgentHelper) + { + if (webRequestAgentHelper == null) + { + throw new GameFrameworkException("Web request agent helper is invalid."); + } + + m_Helper = webRequestAgentHelper; + m_Task = null; + m_WaitTime = 0f; + + WebRequestAgentStart = null; + WebRequestAgentSuccess = null; + WebRequestAgentFailure = null; + } + + /// + /// 获取 Web 请求任务。 + /// + public WebRequestTask Task + { + get + { + return m_Task; + } + } + + /// + /// 获取已经等待时间。 + /// + public float WaitTime + { + get + { + return m_WaitTime; + } + } + + /// + /// 初始化 Web 请求代理。 + /// + public void Initialize() + { + m_Helper.WebRequestAgentHelperComplete += OnWebRequestAgentHelperComplete; + m_Helper.WebRequestAgentHelperError += OnWebRequestAgentHelperError; + } + + /// + /// Web 请求代理轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void Update(float elapseSeconds, float realElapseSeconds) + { + if (m_Task.Status == WebRequestTaskStatus.Doing) + { + m_WaitTime += realElapseSeconds; + if (m_WaitTime >= m_Task.Timeout) + { + WebRequestAgentHelperErrorEventArgs webRequestAgentHelperErrorEventArgs = WebRequestAgentHelperErrorEventArgs.Create("Timeout"); + OnWebRequestAgentHelperError(this, webRequestAgentHelperErrorEventArgs); + ReferencePool.Release(webRequestAgentHelperErrorEventArgs); + } + } + } + + /// + /// 关闭并清理 Web 请求代理。 + /// + public void Shutdown() + { + Reset(); + m_Helper.WebRequestAgentHelperComplete -= OnWebRequestAgentHelperComplete; + m_Helper.WebRequestAgentHelperError -= OnWebRequestAgentHelperError; + } + + /// + /// 开始处理 Web 请求任务。 + /// + /// 要处理的 Web 请求任务。 + /// 开始处理任务的状态。 + public StartTaskStatus Start(WebRequestTask task) + { + if (task == null) + { + throw new GameFrameworkException("Task is invalid."); + } + + m_Task = task; + m_Task.Status = WebRequestTaskStatus.Doing; + + if (WebRequestAgentStart != null) + { + WebRequestAgentStart(this); + } + + byte[] postData = m_Task.GetPostData(); + if (postData == null) + { + m_Helper.Request(m_Task.WebRequestUri, m_Task.UserData); + } + else + { + m_Helper.Request(m_Task.WebRequestUri, postData, m_Task.UserData); + } + + m_WaitTime = 0f; + return StartTaskStatus.CanResume; + } + + /// + /// 重置 Web 请求代理。 + /// + public void Reset() + { + m_Helper.Reset(); + m_Task = null; + m_WaitTime = 0f; + } + + private void OnWebRequestAgentHelperComplete(object sender, WebRequestAgentHelperCompleteEventArgs e) + { + m_Helper.Reset(); + m_Task.Status = WebRequestTaskStatus.Done; + + if (WebRequestAgentSuccess != null) + { + WebRequestAgentSuccess(this, e.GetWebResponseBytes()); + } + + m_Task.Done = true; + } + + private void OnWebRequestAgentHelperError(object sender, WebRequestAgentHelperErrorEventArgs e) + { + m_Helper.Reset(); + m_Task.Status = WebRequestTaskStatus.Error; + + if (WebRequestAgentFailure != null) + { + WebRequestAgentFailure(this, e.ErrorMessage); + } + + m_Task.Done = true; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestAgent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestAgent.cs.meta new file mode 100644 index 0000000..00c5fea --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestAgent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: acd6a4551781afa449250e1e652a8970 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestTask.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestTask.cs new file mode 100644 index 0000000..e07a345 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestTask.cs @@ -0,0 +1,121 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.WebRequest +{ + internal sealed partial class WebRequestManager : GameFrameworkModule, IWebRequestManager + { + /// + /// Web 请求任务。 + /// + private sealed class WebRequestTask : TaskBase + { + private static int s_Serial = 0; + + private WebRequestTaskStatus m_Status; + private string m_WebRequestUri; + private byte[] m_PostData; + private float m_Timeout; + + public WebRequestTask() + { + m_Status = WebRequestTaskStatus.Todo; + m_WebRequestUri = null; + m_PostData = null; + m_Timeout = 0f; + } + + /// + /// 获取或设置 Web 请求任务的状态。 + /// + public WebRequestTaskStatus Status + { + get + { + return m_Status; + } + set + { + m_Status = value; + } + } + + /// + /// 获取要发送的远程地址。 + /// + public string WebRequestUri + { + get + { + return m_WebRequestUri; + } + } + + /// + /// 获取 Web 请求超时时长,以秒为单位。 + /// + public float Timeout + { + get + { + return m_Timeout; + } + } + + /// + /// 获取 Web 请求任务的描述。 + /// + public override string Description + { + get + { + return m_WebRequestUri; + } + } + + /// + /// 创建 Web 请求任务。 + /// + /// 要发送的远程地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 下载超时时长,以秒为单位。 + /// 用户自定义数据。 + /// 创建的 Web 请求任务。 + public static WebRequestTask Create(string webRequestUri, byte[] postData, string tag, int priority, float timeout, object userData) + { + WebRequestTask webRequestTask = ReferencePool.Acquire(); + webRequestTask.Initialize(++s_Serial, tag, priority, userData); + webRequestTask.m_WebRequestUri = webRequestUri; + webRequestTask.m_PostData = postData; + webRequestTask.m_Timeout = timeout; + return webRequestTask; + } + + /// + /// 清理 Web 请求任务。 + /// + public override void Clear() + { + base.Clear(); + m_Status = WebRequestTaskStatus.Todo; + m_WebRequestUri = null; + m_PostData = null; + m_Timeout = 0f; + } + + /// + /// 获取要发送的数据流。 + /// + public byte[] GetPostData() + { + return m_PostData; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestTask.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestTask.cs.meta new file mode 100644 index 0000000..5b022f0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestTask.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aa35a8348bbf90247afaf20a551478de +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestTaskStatus.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestTaskStatus.cs new file mode 100644 index 0000000..61d8296 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestTaskStatus.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.WebRequest +{ + internal sealed partial class WebRequestManager : GameFrameworkModule, IWebRequestManager + { + /// + /// Web 请求任务的状态。 + /// + private enum WebRequestTaskStatus : byte + { + /// + /// 准备请求。 + /// + Todo = 0, + + /// + /// 请求中。 + /// + Doing, + + /// + /// 请求完成。 + /// + Done, + + /// + /// 请求错误。 + /// + Error + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestTaskStatus.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestTaskStatus.cs.meta new file mode 100644 index 0000000..0e08e8a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.WebRequestTaskStatus.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1dd215640353a984bb49aa4532b5a4ce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.cs new file mode 100644 index 0000000..4d8bb51 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.cs @@ -0,0 +1,483 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; + +namespace GameFramework.WebRequest +{ + /// + /// Web 请求管理器。 + /// + internal sealed partial class WebRequestManager : GameFrameworkModule, IWebRequestManager + { + private readonly TaskPool m_TaskPool; + private float m_Timeout; + private EventHandler m_WebRequestStartEventHandler; + private EventHandler m_WebRequestSuccessEventHandler; + private EventHandler m_WebRequestFailureEventHandler; + + /// + /// 初始化 Web 请求管理器的新实例。 + /// + public WebRequestManager() + { + m_TaskPool = new TaskPool(); + m_Timeout = 30f; + m_WebRequestStartEventHandler = null; + m_WebRequestSuccessEventHandler = null; + m_WebRequestFailureEventHandler = null; + } + + /// + /// 获取 Web 请求代理总数量。 + /// + public int TotalAgentCount + { + get + { + return m_TaskPool.TotalAgentCount; + } + } + + /// + /// 获取可用 Web 请求代理数量。 + /// + public int FreeAgentCount + { + get + { + return m_TaskPool.FreeAgentCount; + } + } + + /// + /// 获取工作中 Web 请求代理数量。 + /// + public int WorkingAgentCount + { + get + { + return m_TaskPool.WorkingAgentCount; + } + } + + /// + /// 获取等待 Web 请求数量。 + /// + public int WaitingTaskCount + { + get + { + return m_TaskPool.WaitingTaskCount; + } + } + + /// + /// 获取或设置 Web 请求超时时长,以秒为单位。 + /// + public float Timeout + { + get + { + return m_Timeout; + } + set + { + m_Timeout = value; + } + } + + /// + /// Web 请求开始事件。 + /// + public event EventHandler WebRequestStart + { + add + { + m_WebRequestStartEventHandler += value; + } + remove + { + m_WebRequestStartEventHandler -= value; + } + } + + /// + /// Web 请求成功事件。 + /// + public event EventHandler WebRequestSuccess + { + add + { + m_WebRequestSuccessEventHandler += value; + } + remove + { + m_WebRequestSuccessEventHandler -= value; + } + } + + /// + /// Web 请求失败事件。 + /// + public event EventHandler WebRequestFailure + { + add + { + m_WebRequestFailureEventHandler += value; + } + remove + { + m_WebRequestFailureEventHandler -= value; + } + } + + /// + /// Web 请求管理器轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + internal override void Update(float elapseSeconds, float realElapseSeconds) + { + m_TaskPool.Update(elapseSeconds, realElapseSeconds); + } + + /// + /// 关闭并清理 Web 请求管理器。 + /// + internal override void Shutdown() + { + m_TaskPool.Shutdown(); + } + + /// + /// 增加 Web 请求代理辅助器。 + /// + /// 要增加的 Web 请求代理辅助器。 + public void AddWebRequestAgentHelper(IWebRequestAgentHelper webRequestAgentHelper) + { + WebRequestAgent agent = new WebRequestAgent(webRequestAgentHelper); + agent.WebRequestAgentStart += OnWebRequestAgentStart; + agent.WebRequestAgentSuccess += OnWebRequestAgentSuccess; + agent.WebRequestAgentFailure += OnWebRequestAgentFailure; + + m_TaskPool.AddAgent(agent); + } + + /// + /// 根据 Web 请求任务的序列编号获取 Web 请求任务的信息。 + /// + /// 要获取信息的 Web 请求任务的序列编号。 + /// Web 请求任务的信息。 + public TaskInfo GetWebRequestInfo(int serialId) + { + return m_TaskPool.GetTaskInfo(serialId); + } + + /// + /// 根据 Web 请求任务的标签获取 Web 请求任务的信息。 + /// + /// 要获取信息的 Web 请求任务的标签。 + /// Web 请求任务的信息。 + public TaskInfo[] GetWebRequestInfos(string tag) + { + return m_TaskPool.GetTaskInfos(tag); + } + + /// + /// 根据 Web 请求任务的标签获取 Web 请求任务的信息。 + /// + /// 要获取信息的 Web 请求任务的标签。 + /// Web 请求任务的信息。 + public void GetAllWebRequestInfos(string tag, List results) + { + m_TaskPool.GetTaskInfos(tag, results); + } + + /// + /// 获取所有 Web 请求任务的信息。 + /// + /// 所有 Web 请求任务的信息。 + public TaskInfo[] GetAllWebRequestInfos() + { + return m_TaskPool.GetAllTaskInfos(); + } + + /// + /// 获取所有 Web 请求任务的信息。 + /// + /// 所有 Web 请求任务的信息。 + public void GetAllWebRequestInfos(List results) + { + m_TaskPool.GetAllTaskInfos(results); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri) + { + return AddWebRequest(webRequestUri, null, null, Constant.DefaultPriority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData) + { + return AddWebRequest(webRequestUri, postData, null, Constant.DefaultPriority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的标签。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, string tag) + { + return AddWebRequest(webRequestUri, null, tag, Constant.DefaultPriority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, int priority) + { + return AddWebRequest(webRequestUri, null, null, priority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, object userData) + { + return AddWebRequest(webRequestUri, null, null, Constant.DefaultPriority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, string tag) + { + return AddWebRequest(webRequestUri, postData, tag, Constant.DefaultPriority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, int priority) + { + return AddWebRequest(webRequestUri, postData, null, priority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, object userData) + { + return AddWebRequest(webRequestUri, postData, null, Constant.DefaultPriority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, string tag, int priority) + { + return AddWebRequest(webRequestUri, null, tag, priority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的标签。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, string tag, object userData) + { + return AddWebRequest(webRequestUri, null, tag, Constant.DefaultPriority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, int priority, object userData) + { + return AddWebRequest(webRequestUri, null, null, priority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, string tag, int priority) + { + return AddWebRequest(webRequestUri, postData, tag, priority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, string tag, object userData) + { + return AddWebRequest(webRequestUri, postData, tag, Constant.DefaultPriority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, int priority, object userData) + { + return AddWebRequest(webRequestUri, postData, null, priority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, string tag, int priority, object userData) + { + return AddWebRequest(webRequestUri, null, tag, priority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, string tag, int priority, object userData) + { + if (string.IsNullOrEmpty(webRequestUri)) + { + throw new GameFrameworkException("Web request uri is invalid."); + } + + if (TotalAgentCount <= 0) + { + throw new GameFrameworkException("You must add web request agent first."); + } + + WebRequestTask webRequestTask = WebRequestTask.Create(webRequestUri, postData, tag, priority, m_Timeout, userData); + m_TaskPool.AddTask(webRequestTask); + return webRequestTask.SerialId; + } + + /// + /// 根据 Web 请求任务的序列编号移除 Web 请求任务。 + /// + /// 要移除 Web 请求任务的序列编号。 + /// 是否移除 Web 请求任务成功。 + public bool RemoveWebRequest(int serialId) + { + return m_TaskPool.RemoveTask(serialId); + } + + /// + /// 根据 Web 请求任务的标签移除 Web 请求任务。 + /// + /// 要移除 Web 请求任务的标签。 + /// 移除 Web 请求任务的数量。 + public int RemoveWebRequests(string tag) + { + return m_TaskPool.RemoveTasks(tag); + } + + /// + /// 移除所有 Web 请求任务。 + /// + /// 移除 Web 请求任务的数量。 + public int RemoveAllWebRequests() + { + return m_TaskPool.RemoveAllTasks(); + } + + private void OnWebRequestAgentStart(WebRequestAgent sender) + { + if (m_WebRequestStartEventHandler != null) + { + WebRequestStartEventArgs webRequestStartEventArgs = WebRequestStartEventArgs.Create(sender.Task.SerialId, sender.Task.WebRequestUri, sender.Task.UserData); + m_WebRequestStartEventHandler(this, webRequestStartEventArgs); + ReferencePool.Release(webRequestStartEventArgs); + } + } + + private void OnWebRequestAgentSuccess(WebRequestAgent sender, byte[] webResponseBytes) + { + if (m_WebRequestSuccessEventHandler != null) + { + WebRequestSuccessEventArgs webRequestSuccessEventArgs = WebRequestSuccessEventArgs.Create(sender.Task.SerialId, sender.Task.WebRequestUri, webResponseBytes, sender.Task.UserData); + m_WebRequestSuccessEventHandler(this, webRequestSuccessEventArgs); + ReferencePool.Release(webRequestSuccessEventArgs); + } + } + + private void OnWebRequestAgentFailure(WebRequestAgent sender, string errorMessage) + { + if (m_WebRequestFailureEventHandler != null) + { + WebRequestFailureEventArgs webRequestFailureEventArgs = WebRequestFailureEventArgs.Create(sender.Task.SerialId, sender.Task.WebRequestUri, errorMessage, sender.Task.UserData); + m_WebRequestFailureEventHandler(this, webRequestFailureEventArgs); + ReferencePool.Release(webRequestFailureEventArgs); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.cs.meta new file mode 100644 index 0000000..3f4df34 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 18f1579932f9d484799d6477eda0e890 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestStartEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestStartEventArgs.cs new file mode 100644 index 0000000..9490494 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestStartEventArgs.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.WebRequest +{ + /// + /// Web 请求开始事件。 + /// + public sealed class WebRequestStartEventArgs : GameFrameworkEventArgs + { + /// + /// 初始化 Web 请求开始事件的新实例。 + /// + public WebRequestStartEventArgs() + { + SerialId = 0; + WebRequestUri = null; + UserData = null; + } + + /// + /// 获取 Web 请求任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取 Web 请求地址。 + /// + public string WebRequestUri + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建 Web 请求开始事件。 + /// + /// Web 请求任务的序列编号。 + /// Web 请求地址。 + /// 用户自定义数据。 + /// 创建的 Web 请求开始事件。 + public static WebRequestStartEventArgs Create(int serialId, string webRequestUri, object userData) + { + WebRequestStartEventArgs webRequestStartEventArgs = ReferencePool.Acquire(); + webRequestStartEventArgs.SerialId = serialId; + webRequestStartEventArgs.WebRequestUri = webRequestUri; + webRequestStartEventArgs.UserData = userData; + return webRequestStartEventArgs; + } + + /// + /// 清理 Web 请求开始事件。 + /// + public override void Clear() + { + SerialId = 0; + WebRequestUri = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestStartEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestStartEventArgs.cs.meta new file mode 100644 index 0000000..880e59b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestStartEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f796d4bd94f207449a87f46891c7a1d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestSuccessEventArgs.cs new file mode 100644 index 0000000..28da3a5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestSuccessEventArgs.cs @@ -0,0 +1,93 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace GameFramework.WebRequest +{ + /// + /// Web 请求成功事件。 + /// + public sealed class WebRequestSuccessEventArgs : GameFrameworkEventArgs + { + private byte[] m_WebResponseBytes; + + /// + /// 初始化 Web 请求成功事件的新实例。 + /// + public WebRequestSuccessEventArgs() + { + SerialId = 0; + WebRequestUri = null; + m_WebResponseBytes = null; + UserData = null; + } + + /// + /// 获取 Web 请求任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取 Web 请求地址。 + /// + public string WebRequestUri + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建 Web 请求成功事件。 + /// + /// Web 请求任务的序列编号。 + /// Web 请求地址。 + /// Web 响应的数据流。 + /// 用户自定义数据。 + /// 创建的 Web 请求成功事件。 + public static WebRequestSuccessEventArgs Create(int serialId, string webRequestUri, byte[] webResponseBytes, object userData) + { + WebRequestSuccessEventArgs webRequestSuccessEventArgs = ReferencePool.Acquire(); + webRequestSuccessEventArgs.SerialId = serialId; + webRequestSuccessEventArgs.WebRequestUri = webRequestUri; + webRequestSuccessEventArgs.m_WebResponseBytes = webResponseBytes; + webRequestSuccessEventArgs.UserData = userData; + return webRequestSuccessEventArgs; + } + + /// + /// 清理 Web 请求成功事件。 + /// + public override void Clear() + { + SerialId = 0; + WebRequestUri = null; + m_WebResponseBytes = null; + UserData = null; + } + + /// + /// 获取 Web 响应的数据流。 + /// + /// Web 响应的数据流。 + public byte[] GetWebResponseBytes() + { + return m_WebResponseBytes; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestSuccessEventArgs.cs.meta new file mode 100644 index 0000000..3d69330 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/GameFramework/WebRequest/WebRequestSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9389b80a791ad9445bfbf6018e15831f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework.meta new file mode 100644 index 0000000..d680382 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1b441bec1c7b6aa4f9d91763d2f9ed39 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base.meta new file mode 100644 index 0000000..abcd272 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fef53289940cb524687e31ef870f5029 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/BaseComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/BaseComponent.cs new file mode 100644 index 0000000..4126f26 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/BaseComponent.cs @@ -0,0 +1,425 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Localization; +using GameFramework.Resource; +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 基础组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Base")] + public sealed class BaseComponent : GameFrameworkComponent + { + private const int DefaultDpi = 96; // default windows dpi + + private float m_GameSpeedBeforePause = 1f; + + [SerializeField] + private bool m_EditorResourceMode = true; + + [SerializeField] + private Language m_EditorLanguage = Language.Unspecified; + + [SerializeField] + private string m_TextHelperTypeName = "UnityGameFramework.Runtime.DefaultTextHelper"; + + [SerializeField] + private string m_VersionHelperTypeName = "UnityGameFramework.Runtime.DefaultVersionHelper"; + + [SerializeField] + private string m_LogHelperTypeName = "UnityGameFramework.Runtime.DefaultLogHelper"; + + [SerializeField] + private string m_CompressionHelperTypeName = "UnityGameFramework.Runtime.DefaultCompressionHelper"; + + [SerializeField] + private string m_JsonHelperTypeName = "UnityGameFramework.Runtime.DefaultJsonHelper"; + + [SerializeField] + private int m_FrameRate = 30; + + [SerializeField] + private float m_GameSpeed = 1f; + + [SerializeField] + private bool m_RunInBackground = true; + + [SerializeField] + private bool m_NeverSleep = true; + + /// + /// 获取或设置是否使用编辑器资源模式(仅编辑器内有效)。 + /// + public bool EditorResourceMode + { + get + { + return m_EditorResourceMode; + } + set + { + m_EditorResourceMode = value; + } + } + + /// + /// 获取或设置编辑器语言(仅编辑器内有效)。 + /// + public Language EditorLanguage + { + get + { + return m_EditorLanguage; + } + set + { + m_EditorLanguage = value; + } + } + + /// + /// 获取或设置编辑器资源辅助器。 + /// + public IResourceManager EditorResourceHelper + { + get; + set; + } + + /// + /// 获取或设置游戏帧率。 + /// + public int FrameRate + { + get + { + return m_FrameRate; + } + set + { + Application.targetFrameRate = m_FrameRate = value; + } + } + + /// + /// 获取或设置游戏速度。 + /// + public float GameSpeed + { + get + { + return m_GameSpeed; + } + set + { + Time.timeScale = m_GameSpeed = value >= 0f ? value : 0f; + } + } + + /// + /// 获取游戏是否暂停。 + /// + public bool IsGamePaused + { + get + { + return m_GameSpeed <= 0f; + } + } + + /// + /// 获取是否正常游戏速度。 + /// + public bool IsNormalGameSpeed + { + get + { + return m_GameSpeed == 1f; + } + } + + /// + /// 获取或设置是否允许后台运行。 + /// + public bool RunInBackground + { + get + { + return m_RunInBackground; + } + set + { + Application.runInBackground = m_RunInBackground = value; + } + } + + /// + /// 获取或设置是否禁止休眠。 + /// + public bool NeverSleep + { + get + { + return m_NeverSleep; + } + set + { + m_NeverSleep = value; + Screen.sleepTimeout = value ? SleepTimeout.NeverSleep : SleepTimeout.SystemSetting; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + InitTextHelper(); + InitVersionHelper(); + InitLogHelper(); + Log.Info("Game Framework Version: {0}", GameFramework.Version.GameFrameworkVersion); + Log.Info("Game Version: {0} ({1})", GameFramework.Version.GameVersion, GameFramework.Version.InternalGameVersion); + Log.Info("Unity Version: {0}", Application.unityVersion); + +#if UNITY_5_3_OR_NEWER || UNITY_5_3 + InitCompressionHelper(); + InitJsonHelper(); + + Utility.Converter.ScreenDpi = Screen.dpi; + if (Utility.Converter.ScreenDpi <= 0) + { + Utility.Converter.ScreenDpi = DefaultDpi; + } + + m_EditorResourceMode &= Application.isEditor; + if (m_EditorResourceMode) + { + Log.Info("During this run, Game Framework will use editor resource files, which you should validate first."); + } + + Application.targetFrameRate = m_FrameRate; + Time.timeScale = m_GameSpeed; + Application.runInBackground = m_RunInBackground; + Screen.sleepTimeout = m_NeverSleep ? SleepTimeout.NeverSleep : SleepTimeout.SystemSetting; +#else + Log.Error("Game Framework only applies with Unity 5.3 and above, but current Unity version is {0}.", Application.unityVersion); + GameEntry.Shutdown(ShutdownType.Quit); +#endif +#if UNITY_5_6_OR_NEWER + Application.lowMemory += OnLowMemory; +#endif + } + + private void Start() + { + } + + private void Update() + { + GameFrameworkEntry.Update(Time.deltaTime, Time.unscaledDeltaTime); + } + + private void OnApplicationQuit() + { +#if UNITY_5_6_OR_NEWER + Application.lowMemory -= OnLowMemory; +#endif + StopAllCoroutines(); + } + + private void OnDestroy() + { + GameFrameworkEntry.Shutdown(); + } + + /// + /// 暂停游戏。 + /// + public void PauseGame() + { + if (IsGamePaused) + { + return; + } + + m_GameSpeedBeforePause = GameSpeed; + GameSpeed = 0f; + } + + /// + /// 恢复游戏。 + /// + public void ResumeGame() + { + if (!IsGamePaused) + { + return; + } + + GameSpeed = m_GameSpeedBeforePause; + } + + /// + /// 重置为正常游戏速度。 + /// + public void ResetNormalGameSpeed() + { + if (IsNormalGameSpeed) + { + return; + } + + GameSpeed = 1f; + } + + internal void Shutdown() + { + Destroy(gameObject); + } + + private void InitTextHelper() + { + if (string.IsNullOrEmpty(m_TextHelperTypeName)) + { + return; + } + + Type textHelperType = Utility.Assembly.GetType(m_TextHelperTypeName); + if (textHelperType == null) + { + Log.Error("Can not find text helper type '{0}'.", m_TextHelperTypeName); + return; + } + + Utility.Text.ITextHelper textHelper = (Utility.Text.ITextHelper)Activator.CreateInstance(textHelperType); + if (textHelper == null) + { + Log.Error("Can not create text helper instance '{0}'.", m_TextHelperTypeName); + return; + } + + Utility.Text.SetTextHelper(textHelper); + } + + private void InitVersionHelper() + { + if (string.IsNullOrEmpty(m_VersionHelperTypeName)) + { + return; + } + + Type versionHelperType = Utility.Assembly.GetType(m_VersionHelperTypeName); + if (versionHelperType == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find version helper type '{0}'.", m_VersionHelperTypeName)); + } + + GameFramework.Version.IVersionHelper versionHelper = (GameFramework.Version.IVersionHelper)Activator.CreateInstance(versionHelperType); + if (versionHelper == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not create version helper instance '{0}'.", m_VersionHelperTypeName)); + } + + GameFramework.Version.SetVersionHelper(versionHelper); + } + + private void InitLogHelper() + { + if (string.IsNullOrEmpty(m_LogHelperTypeName)) + { + return; + } + + Type logHelperType = Utility.Assembly.GetType(m_LogHelperTypeName); + if (logHelperType == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not find log helper type '{0}'.", m_LogHelperTypeName)); + } + + GameFrameworkLog.ILogHelper logHelper = (GameFrameworkLog.ILogHelper)Activator.CreateInstance(logHelperType); + if (logHelper == null) + { + throw new GameFrameworkException(Utility.Text.Format("Can not create log helper instance '{0}'.", m_LogHelperTypeName)); + } + + GameFrameworkLog.SetLogHelper(logHelper); + } + + private void InitCompressionHelper() + { + if (string.IsNullOrEmpty(m_CompressionHelperTypeName)) + { + return; + } + + Type compressionHelperType = Utility.Assembly.GetType(m_CompressionHelperTypeName); + if (compressionHelperType == null) + { + Log.Error("Can not find compression helper type '{0}'.", m_CompressionHelperTypeName); + return; + } + + Utility.Compression.ICompressionHelper compressionHelper = (Utility.Compression.ICompressionHelper)Activator.CreateInstance(compressionHelperType); + if (compressionHelper == null) + { + Log.Error("Can not create compression helper instance '{0}'.", m_CompressionHelperTypeName); + return; + } + + Utility.Compression.SetCompressionHelper(compressionHelper); + } + + private void InitJsonHelper() + { + if (string.IsNullOrEmpty(m_JsonHelperTypeName)) + { + return; + } + + Type jsonHelperType = Utility.Assembly.GetType(m_JsonHelperTypeName); + if (jsonHelperType == null) + { + Log.Error("Can not find JSON helper type '{0}'.", m_JsonHelperTypeName); + return; + } + + Utility.Json.IJsonHelper jsonHelper = (Utility.Json.IJsonHelper)Activator.CreateInstance(jsonHelperType); + if (jsonHelper == null) + { + Log.Error("Can not create JSON helper instance '{0}'.", m_JsonHelperTypeName); + return; + } + + Utility.Json.SetJsonHelper(jsonHelper); + } + + private void OnLowMemory() + { + Log.Info("Low memory reported..."); + + ObjectPoolComponent objectPoolComponent = GameEntry.GetComponent(); + if (objectPoolComponent != null) + { + objectPoolComponent.ReleaseAllUnused(); + } + + ResourceComponent resourceCompoent = GameEntry.GetComponent(); + if (resourceCompoent != null) + { + resourceCompoent.ForceUnloadUnusedAssets(true); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/BaseComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/BaseComponent.cs.meta new file mode 100644 index 0000000..bbc27ae --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/BaseComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f98acd7d3bd2bf54dadf9644f60e5cb9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/GameEntry.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/GameEntry.cs new file mode 100644 index 0000000..81f3a7b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/GameEntry.cs @@ -0,0 +1,150 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace UnityGameFramework.Runtime +{ + /// + /// 游戏入口。 + /// + public static class GameEntry + { + private static readonly GameFrameworkLinkedList s_GameFrameworkComponents = new GameFrameworkLinkedList(); + + /// + /// 游戏框架所在的场景编号。 + /// + internal const int GameFrameworkSceneId = 0; + + /// + /// 获取游戏框架组件。 + /// + /// 要获取的游戏框架组件类型。 + /// 要获取的游戏框架组件。 + public static T GetComponent() where T : GameFrameworkComponent + { + return (T)GetComponent(typeof(T)); + } + + /// + /// 获取游戏框架组件。 + /// + /// 要获取的游戏框架组件类型。 + /// 要获取的游戏框架组件。 + public static GameFrameworkComponent GetComponent(Type type) + { + LinkedListNode current = s_GameFrameworkComponents.First; + while (current != null) + { + if (current.Value.GetType() == type) + { + return current.Value; + } + + current = current.Next; + } + + return null; + } + + /// + /// 获取游戏框架组件。 + /// + /// 要获取的游戏框架组件类型名称。 + /// 要获取的游戏框架组件。 + public static GameFrameworkComponent GetComponent(string typeName) + { + LinkedListNode current = s_GameFrameworkComponents.First; + while (current != null) + { + Type type = current.Value.GetType(); + if (type.FullName == typeName || type.Name == typeName) + { + return current.Value; + } + + current = current.Next; + } + + return null; + } + + /// + /// 关闭游戏框架。 + /// + /// 关闭游戏框架类型。 + public static void Shutdown(ShutdownType shutdownType) + { + Log.Info("Shutdown Game Framework ({0})...", shutdownType); + BaseComponent baseComponent = GetComponent(); + if (baseComponent != null) + { + baseComponent.Shutdown(); + baseComponent = null; + } + + s_GameFrameworkComponents.Clear(); + + if (shutdownType == ShutdownType.None) + { + return; + } + + if (shutdownType == ShutdownType.Restart) + { + SceneManager.LoadScene(GameFrameworkSceneId); + return; + } + + if (shutdownType == ShutdownType.Quit) + { + Application.Quit(); +#if UNITY_EDITOR + UnityEditor.EditorApplication.isPlaying = false; +#endif + return; + } + } + + /// + /// 注册游戏框架组件。 + /// + /// 要注册的游戏框架组件。 + internal static void RegisterComponent(GameFrameworkComponent gameFrameworkComponent) + { + //如果组件为空返回 + if (gameFrameworkComponent == null) + { + Log.Error("Game Framework component is invalid."); + return; + } + //获取组件类型 + Type type = gameFrameworkComponent.GetType(); + //获取链表第一个节点 + LinkedListNode current = s_GameFrameworkComponents.First; + //如果节点不为空 + while (current != null) + { + //如果类型相等返回 + if (current.Value.GetType() == type) + { + Log.Error("Game Framework component type '{0}' is already exist.", type.FullName); + return; + } + + current = current.Next; + } + //将组件类型加入链表 + s_GameFrameworkComponents.AddLast(gameFrameworkComponent); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/GameEntry.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/GameEntry.cs.meta new file mode 100644 index 0000000..8c6d5f1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/GameEntry.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dd346220e820e384b816477cdf1e1bb2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/GameFrameworkComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/GameFrameworkComponent.cs new file mode 100644 index 0000000..440a0c0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/GameFrameworkComponent.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 游戏框架组件抽象类。 + /// + public abstract class GameFrameworkComponent : MonoBehaviour + { + /// + /// 游戏框架组件初始化。 + /// + protected virtual void Awake() + { + GameEntry.RegisterComponent(this); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/GameFrameworkComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/GameFrameworkComponent.cs.meta new file mode 100644 index 0000000..2886464 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/GameFrameworkComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bbf5faef1b7b7d24c8375006438a0cd0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/ShutdownType.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/ShutdownType.cs new file mode 100644 index 0000000..9d7b5d6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/ShutdownType.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Runtime +{ + /// + /// 关闭游戏框架类型。 + /// + public enum ShutdownType : byte + { + /// + /// 仅关闭游戏框架。 + /// + None = 0, + + /// + /// 关闭游戏框架并重启游戏。 + /// + Restart, + + /// + /// 关闭游戏框架并退出游戏。 + /// + Quit, + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/ShutdownType.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/ShutdownType.cs.meta new file mode 100644 index 0000000..1e1b91d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Base/ShutdownType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6e19747752388e14bbe312e0f4c44e00 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config.meta new file mode 100644 index 0000000..c034904 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ff4afea74c892e04e984aa34aa089b89 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/ConfigComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/ConfigComponent.cs new file mode 100644 index 0000000..cf053b4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/ConfigComponent.cs @@ -0,0 +1,408 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Config; +using GameFramework.Resource; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 全局配置组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Config")] + public sealed class ConfigComponent : GameFrameworkComponent + { + private const int DefaultPriority = 0; + + private IConfigManager m_ConfigManager = null; + private EventComponent m_EventComponent = null; + + [SerializeField] + private bool m_EnableLoadConfigUpdateEvent = false; + + [SerializeField] + private bool m_EnableLoadConfigDependencyAssetEvent = false; + + [SerializeField] + private string m_ConfigHelperTypeName = "UnityGameFramework.Runtime.DefaultConfigHelper"; + + [SerializeField] + private ConfigHelperBase m_CustomConfigHelper = null; + + [SerializeField] + private int m_CachedBytesSize = 0; + + /// + /// 获取全局配置项数量。 + /// + public int Count + { + get + { + return m_ConfigManager.Count; + } + } + + /// + /// 获取缓冲二进制流的大小。 + /// + public int CachedBytesSize + { + get + { + return m_ConfigManager.CachedBytesSize; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_ConfigManager = GameFrameworkEntry.GetModule(); + if (m_ConfigManager == null) + { + Log.Fatal("Config manager is invalid."); + return; + } + + m_ConfigManager.ReadDataSuccess += OnReadDataSuccess; + m_ConfigManager.ReadDataFailure += OnReadDataFailure; + + if (m_EnableLoadConfigUpdateEvent) + { + m_ConfigManager.ReadDataUpdate += OnReadDataUpdate; + } + + if (m_EnableLoadConfigDependencyAssetEvent) + { + m_ConfigManager.ReadDataDependencyAsset += OnReadDataDependencyAsset; + } + } + + private void Start() + { + BaseComponent baseComponent = GameEntry.GetComponent(); + if (baseComponent == null) + { + Log.Fatal("Base component is invalid."); + return; + } + + m_EventComponent = GameEntry.GetComponent(); + if (m_EventComponent == null) + { + Log.Fatal("Event component is invalid."); + return; + } + + if (baseComponent.EditorResourceMode) + { + m_ConfigManager.SetResourceManager(baseComponent.EditorResourceHelper); + } + else + { + m_ConfigManager.SetResourceManager(GameFrameworkEntry.GetModule()); + } + + ConfigHelperBase configHelper = Helper.CreateHelper(m_ConfigHelperTypeName, m_CustomConfigHelper); + if (configHelper == null) + { + Log.Error("Can not create config helper."); + return; + } + + configHelper.name = "Config Helper"; + Transform transform = configHelper.transform; + transform.SetParent(this.transform); + transform.localScale = Vector3.one; + + m_ConfigManager.SetDataProviderHelper(configHelper); + m_ConfigManager.SetConfigHelper(configHelper); + if (m_CachedBytesSize > 0) + { + EnsureCachedBytesSize(m_CachedBytesSize); + } + } + + /// + /// 确保二进制流缓存分配足够大小的内存并缓存。 + /// + /// 要确保二进制流缓存分配内存的大小。 + public void EnsureCachedBytesSize(int ensureSize) + { + m_ConfigManager.EnsureCachedBytesSize(ensureSize); + } + + /// + /// 释放缓存的二进制流。 + /// + public void FreeCachedBytes() + { + m_ConfigManager.FreeCachedBytes(); + } + + /// + /// 读取全局配置。 + /// + /// 全局配置资源名称。 + public void ReadData(string configAssetName) + { + m_ConfigManager.ReadData(configAssetName); + } + + /// + /// 读取全局配置。 + /// + /// 全局配置资源名称。 + /// 加载全局配置资源的优先级。 + public void ReadData(string configAssetName, int priority) + { + m_ConfigManager.ReadData(configAssetName, priority); + } + + /// + /// 读取全局配置。 + /// + /// 全局配置资源名称。 + /// 用户自定义数据。 + public void ReadData(string configAssetName, object userData) + { + m_ConfigManager.ReadData(configAssetName, userData); + } + + /// + /// 读取全局配置。 + /// + /// 全局配置资源名称。 + /// 加载全局配置资源的优先级。 + /// 用户自定义数据。 + public void ReadData(string configAssetName, int priority, object userData) + { + m_ConfigManager.ReadData(configAssetName, priority, userData); + } + + /// + /// 解析全局配置。 + /// + /// 要解析的全局配置字符串。 + /// 是否解析全局配置成功。 + public bool ParseData(string configString) + { + return m_ConfigManager.ParseData(configString); + } + + /// + /// 解析全局配置。 + /// + /// 要解析的全局配置字符串。 + /// 用户自定义数据。 + /// 是否解析全局配置成功。 + public bool ParseData(string configString, object userData) + { + return m_ConfigManager.ParseData(configString, userData); + } + + /// + /// 解析全局配置。 + /// + /// 要解析的全局配置二进制流。 + /// 是否解析全局配置成功。 + public bool ParseData(byte[] configBytes) + { + return m_ConfigManager.ParseData(configBytes); + } + + /// + /// 解析全局配置。 + /// + /// 要解析的全局配置二进制流。 + /// 用户自定义数据。 + /// 是否解析全局配置成功。 + public bool ParseData(byte[] configBytes, object userData) + { + return m_ConfigManager.ParseData(configBytes, userData); + } + + /// + /// 解析全局配置。 + /// + /// 要解析的全局配置二进制流。 + /// 全局配置二进制流的起始位置。 + /// 全局配置二进制流的长度。 + /// 是否解析全局配置成功。 + public bool ParseData(byte[] configBytes, int startIndex, int length) + { + return m_ConfigManager.ParseData(configBytes, startIndex, length); + } + + /// + /// 解析全局配置。 + /// + /// 要解析的全局配置二进制流。 + /// 全局配置二进制流的起始位置。 + /// 全局配置二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析全局配置成功。 + public bool ParseData(byte[] configBytes, int startIndex, int length, object userData) + { + return m_ConfigManager.ParseData(configBytes, startIndex, length, userData); + } + + /// + /// 检查是否存在指定全局配置项。 + /// + /// 要检查全局配置项的名称。 + /// 指定的全局配置项是否存在。 + public bool HasConfig(string configName) + { + return m_ConfigManager.HasConfig(configName); + } + + /// + /// 从指定全局配置项中读取布尔值。 + /// + /// 要获取全局配置项的名称。 + /// 读取的布尔值。 + public bool GetBool(string configName) + { + return m_ConfigManager.GetBool(configName); + } + + /// + /// 从指定全局配置项中读取布尔值。 + /// + /// 要获取全局配置项的名称。 + /// 当指定的全局配置项不存在时,返回此默认值。 + /// 读取的布尔值。 + public bool GetBool(string configName, bool defaultValue) + { + return m_ConfigManager.GetBool(configName, defaultValue); + } + + /// + /// 从指定全局配置项中读取整数值。 + /// + /// 要获取全局配置项的名称。 + /// 读取的整数值。 + public int GetInt(string configName) + { + return m_ConfigManager.GetInt(configName); + } + + /// + /// 从指定全局配置项中读取整数值。 + /// + /// 要获取全局配置项的名称。 + /// 当指定的全局配置项不存在时,返回此默认值。 + /// 读取的整数值。 + public int GetInt(string configName, int defaultValue) + { + return m_ConfigManager.GetInt(configName, defaultValue); + } + + /// + /// 从指定全局配置项中读取浮点数值。 + /// + /// 要获取全局配置项的名称。 + /// 读取的浮点数值。 + public float GetFloat(string configName) + { + return m_ConfigManager.GetFloat(configName); + } + + /// + /// 从指定全局配置项中读取浮点数值。 + /// + /// 要获取全局配置项的名称。 + /// 当指定的全局配置项不存在时,返回此默认值。 + /// 读取的浮点数值。 + public float GetFloat(string configName, float defaultValue) + { + return m_ConfigManager.GetFloat(configName, defaultValue); + } + + /// + /// 从指定全局配置项中读取字符串值。 + /// + /// 要获取全局配置项的名称。 + /// 读取的字符串值。 + public string GetString(string configName) + { + return m_ConfigManager.GetString(configName); + } + + /// + /// 从指定全局配置项中读取字符串值。 + /// + /// 要获取全局配置项的名称。 + /// 当指定的全局配置项不存在时,返回此默认值。 + /// 读取的字符串值。 + public string GetString(string configName, string defaultValue) + { + return m_ConfigManager.GetString(configName, defaultValue); + } + + /// + /// 增加指定全局配置项。 + /// + /// 要增加全局配置项的名称。 + /// 全局配置项布尔值。 + /// 全局配置项整数值。 + /// 全局配置项浮点数值。 + /// 全局配置项字符串值。 + /// 是否增加全局配置项成功。 + public bool AddConfig(string configName, bool boolValue, int intValue, float floatValue, string stringValue) + { + return m_ConfigManager.AddConfig(configName, boolValue, intValue, floatValue, stringValue); + } + + /// + /// 移除指定全局配置项。 + /// + /// 要移除全局配置项的名称。 + /// 是否移除全局配置项成功。 + public bool RemoveConfig(string configName) + { + return m_ConfigManager.RemoveConfig(configName); + } + + /// + /// 清空所有全局配置项。 + /// + public void RemoveAllConfigs() + { + m_ConfigManager.RemoveAllConfigs(); + } + + private void OnReadDataSuccess(object sender, ReadDataSuccessEventArgs e) + { + m_EventComponent.Fire(this, LoadConfigSuccessEventArgs.Create(e)); + } + + private void OnReadDataFailure(object sender, ReadDataFailureEventArgs e) + { + Log.Warning("Load config failure, asset name '{0}', error message '{1}'.", e.DataAssetName, e.ErrorMessage); + m_EventComponent.Fire(this, LoadConfigFailureEventArgs.Create(e)); + } + + private void OnReadDataUpdate(object sender, ReadDataUpdateEventArgs e) + { + m_EventComponent.Fire(this, LoadConfigUpdateEventArgs.Create(e)); + } + + private void OnReadDataDependencyAsset(object sender, ReadDataDependencyAssetEventArgs e) + { + m_EventComponent.Fire(this, LoadConfigDependencyAssetEventArgs.Create(e)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/ConfigComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/ConfigComponent.cs.meta new file mode 100644 index 0000000..9f3efe1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/ConfigComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3e847b2b3e22e9b4792ca7ea6e1714c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/ConfigHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/ConfigHelperBase.cs new file mode 100644 index 0000000..a4ddd9c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/ConfigHelperBase.cs @@ -0,0 +1,68 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Config; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 全局配置辅助器基类。 + /// + public abstract class ConfigHelperBase : MonoBehaviour, IDataProviderHelper, IConfigHelper + { + /// + /// 读取全局配置。 + /// + /// 全局配置管理器。 + /// 全局配置资源名称。 + /// 全局配置资源。 + /// 用户自定义数据。 + /// 是否读取全局配置成功。 + public abstract bool ReadData(IConfigManager configManager, string configAssetName, object configAsset, object userData); + + /// + /// 读取全局配置。 + /// + /// 全局配置管理器。 + /// 全局配置资源名称。 + /// 全局配置二进制流。 + /// 全局配置二进制流的起始位置。 + /// 全局配置二进制流的长度。 + /// 用户自定义数据。 + /// 是否读取全局配置成功。 + public abstract bool ReadData(IConfigManager configManager, string configAssetName, byte[] configBytes, int startIndex, int length, object userData); + + /// + /// 解析全局配置。 + /// + /// 全局配置管理器。 + /// 要解析的全局配置字符串。 + /// 用户自定义数据。 + /// 是否解析全局配置成功。 + public abstract bool ParseData(IConfigManager configManager, string configString, object userData); + + /// + /// 解析全局配置。 + /// + /// 全局配置管理器。 + /// 要解析的全局配置二进制流。 + /// 全局配置二进制流的起始位置。 + /// 全局配置二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析全局配置成功。 + public abstract bool ParseData(IConfigManager configManager, byte[] configBytes, int startIndex, int length, object userData); + + /// + /// 释放全局配置资源。 + /// + /// 全局配置管理器。 + /// 要释放的全局配置资源。 + public abstract void ReleaseDataAsset(IConfigManager configManager, object configAsset); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/ConfigHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/ConfigHelperBase.cs.meta new file mode 100644 index 0000000..c1dc18c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/ConfigHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5588940f3b356ec4b9cee3c5b4a905f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/DefaultConfigHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/DefaultConfigHelper.cs new file mode 100644 index 0000000..f4c9271 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/DefaultConfigHelper.cs @@ -0,0 +1,181 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Config; +using System; +using System.IO; +using System.Text; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认全局配置辅助器。 + /// + public class DefaultConfigHelper : ConfigHelperBase + { + private static readonly string[] ColumnSplitSeparator = new string[] { "\t" }; + private static readonly string BytesAssetExtension = ".bytes"; + private const int ColumnCount = 4; + + private ResourceComponent m_ResourceComponent = null; + + /// + /// 读取全局配置。 + /// + /// 全局配置管理器。 + /// 全局配置资源名称。 + /// 全局配置资源。 + /// 用户自定义数据。 + /// 是否读取全局配置成功。 + public override bool ReadData(IConfigManager configManager, string configAssetName, object configAsset, object userData) + { + TextAsset configTextAsset = configAsset as TextAsset; + if (configTextAsset != null) + { + if (configAssetName.EndsWith(BytesAssetExtension, StringComparison.Ordinal)) + { + return configManager.ParseData(configTextAsset.bytes, userData); + } + else + { + return configManager.ParseData(configTextAsset.text, userData); + } + } + + Log.Warning("Config asset '{0}' is invalid.", configAssetName); + return false; + } + + /// + /// 读取全局配置。 + /// + /// 全局配置管理器。 + /// 全局配置资源名称。 + /// 全局配置二进制流。 + /// 全局配置二进制流的起始位置。 + /// 全局配置二进制流的长度。 + /// 用户自定义数据。 + /// 是否读取全局配置成功。 + public override bool ReadData(IConfigManager configManager, string configAssetName, byte[] configBytes, int startIndex, int length, object userData) + { + if (configAssetName.EndsWith(BytesAssetExtension, StringComparison.Ordinal)) + { + return configManager.ParseData(configBytes, startIndex, length, userData); + } + else + { + return configManager.ParseData(Utility.Converter.GetString(configBytes, startIndex, length), userData); + } + } + + /// + /// 解析全局配置。 + /// + /// 全局配置管理器。 + /// 要解析的全局配置字符串。 + /// 用户自定义数据。 + /// 是否解析全局配置成功。 + public override bool ParseData(IConfigManager configManager, string configString, object userData) + { + try + { + int position = 0; + string configLineString = null; + while ((configLineString = configString.ReadLine(ref position)) != null) + { + if (configLineString[0] == '#') + { + continue; + } + + string[] splitedLine = configLineString.Split(ColumnSplitSeparator, StringSplitOptions.None); + if (splitedLine.Length != ColumnCount) + { + Log.Warning("Can not parse config line string '{0}' which column count is invalid.", configLineString); + return false; + } + + string configName = splitedLine[1]; + string configValue = splitedLine[3]; + if (!configManager.AddConfig(configName, configValue)) + { + Log.Warning("Can not add config with config name '{0}' which may be invalid or duplicate.", configName); + return false; + } + } + + return true; + } + catch (Exception exception) + { + Log.Warning("Can not parse config string with exception '{0}'.", exception); + return false; + } + } + + /// + /// 解析全局配置。 + /// + /// 全局配置管理器。 + /// 要解析的全局配置二进制流。 + /// 全局配置二进制流的起始位置。 + /// 全局配置二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析全局配置成功。 + public override bool ParseData(IConfigManager configManager, byte[] configBytes, int startIndex, int length, object userData) + { + try + { + using (MemoryStream memoryStream = new MemoryStream(configBytes, startIndex, length, false)) + { + using (BinaryReader binaryReader = new BinaryReader(memoryStream, Encoding.UTF8)) + { + while (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length) + { + string configName = binaryReader.ReadString(); + string configValue = binaryReader.ReadString(); + if (!configManager.AddConfig(configName, configValue)) + { + Log.Warning("Can not add config with config name '{0}' which may be invalid or duplicate.", configName); + return false; + } + } + } + } + + return true; + } + catch (Exception exception) + { + Log.Warning("Can not parse config bytes with exception '{0}'.", exception); + return false; + } + } + + /// + /// 释放全局配置资源。 + /// + /// 全局配置管理器。 + /// 要释放的全局配置资源。 + public override void ReleaseDataAsset(IConfigManager configManager, object configAsset) + { + m_ResourceComponent.UnloadAsset(configAsset); + } + + private void Start() + { + m_ResourceComponent = GameEntry.GetComponent(); + if (m_ResourceComponent == null) + { + Log.Fatal("Resource component is invalid."); + return; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/DefaultConfigHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/DefaultConfigHelper.cs.meta new file mode 100644 index 0000000..ae700fa --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/DefaultConfigHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9c039b1ea5c75e24fa12a58ab3227ab7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigDependencyAssetEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigDependencyAssetEventArgs.cs new file mode 100644 index 0000000..b45f4a6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigDependencyAssetEventArgs.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载全局配置时加载依赖资源事件。 + /// + public sealed class LoadConfigDependencyAssetEventArgs : GameEventArgs + { + /// + /// 加载全局配置失败事件编号。 + /// + public static readonly int EventId = typeof(LoadConfigDependencyAssetEventArgs).GetHashCode(); + + /// + /// 初始化加载全局配置时加载依赖资源事件的新实例。 + /// + public LoadConfigDependencyAssetEventArgs() + { + ConfigAssetName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + + /// + /// 获取加载全局配置失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取全局配置资源名称。 + /// + public string ConfigAssetName + { + get; + private set; + } + + /// + /// 获取被加载的依赖资源名称。 + /// + public string DependencyAssetName + { + get; + private set; + } + + /// + /// 获取当前已加载依赖资源数量。 + /// + public int LoadedCount + { + get; + private set; + } + + /// + /// 获取总共加载依赖资源数量。 + /// + public int TotalCount + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载全局配置时加载依赖资源事件。 + /// + /// 内部事件。 + /// 创建的加载全局配置时加载依赖资源事件。 + public static LoadConfigDependencyAssetEventArgs Create(ReadDataDependencyAssetEventArgs e) + { + LoadConfigDependencyAssetEventArgs loadConfigDependencyAssetEventArgs = ReferencePool.Acquire(); + loadConfigDependencyAssetEventArgs.ConfigAssetName = e.DataAssetName; + loadConfigDependencyAssetEventArgs.DependencyAssetName = e.DependencyAssetName; + loadConfigDependencyAssetEventArgs.LoadedCount = e.LoadedCount; + loadConfigDependencyAssetEventArgs.TotalCount = e.TotalCount; + loadConfigDependencyAssetEventArgs.UserData = e.UserData; + return loadConfigDependencyAssetEventArgs; + } + + /// + /// 清理加载全局配置时加载依赖资源事件。 + /// + public override void Clear() + { + ConfigAssetName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigDependencyAssetEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigDependencyAssetEventArgs.cs.meta new file mode 100644 index 0000000..ebe3079 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigDependencyAssetEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 224a6c56bac19dc47b5a08f772e59af1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigFailureEventArgs.cs new file mode 100644 index 0000000..1fb51eb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigFailureEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载全局配置失败事件。 + /// + public sealed class LoadConfigFailureEventArgs : GameEventArgs + { + /// + /// 加载全局配置失败事件编号。 + /// + public static readonly int EventId = typeof(LoadConfigFailureEventArgs).GetHashCode(); + + /// + /// 初始化加载全局配置失败事件的新实例。 + /// + public LoadConfigFailureEventArgs() + { + ConfigAssetName = null; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取加载全局配置失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取全局配置资源名称。 + /// + public string ConfigAssetName + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载全局配置失败事件。 + /// + /// 内部事件。 + /// 创建的加载全局配置失败事件。 + public static LoadConfigFailureEventArgs Create(ReadDataFailureEventArgs e) + { + LoadConfigFailureEventArgs loadConfigFailureEventArgs = ReferencePool.Acquire(); + loadConfigFailureEventArgs.ConfigAssetName = e.DataAssetName; + loadConfigFailureEventArgs.ErrorMessage = e.ErrorMessage; + loadConfigFailureEventArgs.UserData = e.UserData; + return loadConfigFailureEventArgs; + } + + /// + /// 清理加载全局配置失败事件。 + /// + public override void Clear() + { + ConfigAssetName = null; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigFailureEventArgs.cs.meta new file mode 100644 index 0000000..650ab48 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ca7b842aaf795c6428b7a23287dec802 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigSuccessEventArgs.cs new file mode 100644 index 0000000..afbedde --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigSuccessEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载全局配置成功事件。 + /// + public sealed class LoadConfigSuccessEventArgs : GameEventArgs + { + /// + /// 加载全局配置成功事件编号。 + /// + public static readonly int EventId = typeof(LoadConfigSuccessEventArgs).GetHashCode(); + + /// + /// 初始化加载全局配置成功事件编号的新实例。 + /// + public LoadConfigSuccessEventArgs() + { + ConfigAssetName = null; + Duration = 0f; + UserData = null; + } + + /// + /// 获取加载全局配置成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取全局配置资源名称。 + /// + public string ConfigAssetName + { + get; + private set; + } + + /// + /// 获取加载持续时间。 + /// + public float Duration + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载全局配置成功事件。 + /// + /// 内部事件。 + /// 创建的加载全局配置成功事件。 + public static LoadConfigSuccessEventArgs Create(ReadDataSuccessEventArgs e) + { + LoadConfigSuccessEventArgs loadConfigSuccessEventArgs = ReferencePool.Acquire(); + loadConfigSuccessEventArgs.ConfigAssetName = e.DataAssetName; + loadConfigSuccessEventArgs.Duration = e.Duration; + loadConfigSuccessEventArgs.UserData = e.UserData; + return loadConfigSuccessEventArgs; + } + + /// + /// 清理加载全局配置成功事件。 + /// + public override void Clear() + { + ConfigAssetName = null; + Duration = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigSuccessEventArgs.cs.meta new file mode 100644 index 0000000..9e82ac2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8edee6cdf050d4f47ac48581f944d4ae +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigUpdateEventArgs.cs new file mode 100644 index 0000000..808aa30 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigUpdateEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载全局配置更新事件。 + /// + public sealed class LoadConfigUpdateEventArgs : GameEventArgs + { + /// + /// 加载全局配置失败事件编号。 + /// + public static readonly int EventId = typeof(LoadConfigUpdateEventArgs).GetHashCode(); + + /// + /// 初始化加载全局配置更新事件的新实例。 + /// + public LoadConfigUpdateEventArgs() + { + ConfigAssetName = null; + Progress = 0f; + UserData = null; + } + + /// + /// 获取加载全局配置失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取全局配置资源名称。 + /// + public string ConfigAssetName + { + get; + private set; + } + + /// + /// 获取加载全局配置进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载全局配置更新事件。 + /// + /// 内部事件。 + /// 创建的加载全局配置更新事件。 + public static LoadConfigUpdateEventArgs Create(ReadDataUpdateEventArgs e) + { + LoadConfigUpdateEventArgs loadConfigUpdateEventArgs = ReferencePool.Acquire(); + loadConfigUpdateEventArgs.ConfigAssetName = e.DataAssetName; + loadConfigUpdateEventArgs.Progress = e.Progress; + loadConfigUpdateEventArgs.UserData = e.UserData; + return loadConfigUpdateEventArgs; + } + + /// + /// 清理加载全局配置更新事件。 + /// + public override void Clear() + { + ConfigAssetName = null; + Progress = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigUpdateEventArgs.cs.meta new file mode 100644 index 0000000..2efb530 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Config/LoadConfigUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 07c976efcbda2464bb7ef36e80504f3a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataNode.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataNode.meta new file mode 100644 index 0000000..7bf2e7e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataNode.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f919642531f20564094b12cd52df111d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataNode/DataNodeComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataNode/DataNodeComponent.cs new file mode 100644 index 0000000..1ec03e8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataNode/DataNodeComponent.cs @@ -0,0 +1,210 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.DataNode; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 数据结点组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Data Node")] + public sealed class DataNodeComponent : GameFrameworkComponent + { + private IDataNodeManager m_DataNodeManager = null; + + /// + /// 获取根数据结点。 + /// + public IDataNode Root + { + get + { + return m_DataNodeManager.Root; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_DataNodeManager = GameFrameworkEntry.GetModule(); + if (m_DataNodeManager == null) + { + Log.Fatal("Data node manager is invalid."); + return; + } + } + + private void Start() + { + } + + /// + /// 根据类型获取数据结点的数据。 + /// + /// 要获取的数据类型。 + /// 相对于 node 的查找路径。 + /// 指定类型的数据。 + public T GetData(string path) where T : Variable + { + return m_DataNodeManager.GetData(path); + } + + /// + /// 获取数据结点的数据。 + /// + /// 相对于 node 的查找路径。 + /// 数据结点的数据。 + public Variable GetData(string path) + { + return m_DataNodeManager.GetData(path); + } + + /// + /// 根据类型获取数据结点的数据。 + /// + /// 要获取的数据类型。 + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + /// 指定类型的数据。 + public T GetData(string path, IDataNode node) where T : Variable + { + return m_DataNodeManager.GetData(path, node); + } + + /// + /// 获取数据结点的数据。 + /// + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + /// 数据结点的数据。 + public Variable GetData(string path, IDataNode node) + { + return m_DataNodeManager.GetData(path, node); + } + + /// + /// 设置数据结点的数据。 + /// + /// 要设置的数据类型。 + /// 相对于 node 的查找路径。 + /// 要设置的数据。 + public void SetData(string path, T data) where T : Variable + { + m_DataNodeManager.SetData(path, data); + } + + /// + /// 设置数据结点的数据。 + /// + /// 相对于 node 的查找路径。 + /// 要设置的数据。 + public void SetData(string path, Variable data) + { + m_DataNodeManager.SetData(path, data); + } + + /// + /// 设置数据结点的数据。 + /// + /// 要设置的数据类型。 + /// 相对于 node 的查找路径。 + /// 要设置的数据。 + /// 查找起始结点。 + public void SetData(string path, T data, IDataNode node) where T : Variable + { + m_DataNodeManager.SetData(path, data, node); + } + + /// + /// 设置数据结点的数据。 + /// + /// 相对于 node 的查找路径。 + /// 要设置的数据。 + /// 查找起始结点。 + public void SetData(string path, Variable data, IDataNode node) + { + m_DataNodeManager.SetData(path, data, node); + } + + /// + /// 获取数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 指定位置的数据结点,如果没有找到,则返回空。 + public IDataNode GetNode(string path) + { + return m_DataNodeManager.GetNode(path); + } + + /// + /// 获取数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + /// 指定位置的数据结点,如果没有找到,则返回空。 + public IDataNode GetNode(string path, IDataNode node) + { + return m_DataNodeManager.GetNode(path, node); + } + + /// + /// 获取或增加数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 指定位置的数据结点,如果没有找到,则增加相应的数据结点。 + public IDataNode GetOrAddNode(string path) + { + return m_DataNodeManager.GetOrAddNode(path); + } + + /// + /// 获取或增加数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + /// 指定位置的数据结点,如果没有找到,则增加相应的数据结点。 + public IDataNode GetOrAddNode(string path, IDataNode node) + { + return m_DataNodeManager.GetOrAddNode(path, node); + } + + /// + /// 移除数据结点。 + /// + /// 相对于 node 的查找路径。 + public void RemoveNode(string path) + { + m_DataNodeManager.RemoveNode(path); + } + + /// + /// 移除数据结点。 + /// + /// 相对于 node 的查找路径。 + /// 查找起始结点。 + public void RemoveNode(string path, IDataNode node) + { + m_DataNodeManager.RemoveNode(path, node); + } + + /// + /// 移除所有数据结点。 + /// + public void Clear() + { + m_DataNodeManager.Clear(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataNode/DataNodeComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataNode/DataNodeComponent.cs.meta new file mode 100644 index 0000000..73d7da2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataNode/DataNodeComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 67038fd9feefc894aa31ae3869a45b72 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable.meta new file mode 100644 index 0000000..84c817d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c37122151fcac7a4d82295f02039a322 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataRowBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataRowBase.cs new file mode 100644 index 0000000..2fc435f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataRowBase.cs @@ -0,0 +1,51 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.DataTable; + +namespace UnityGameFramework.Runtime +{ + /// + /// 数据表行基类。 + /// + public abstract class DataRowBase : IDataRow + { + /// + /// 获取数据表行的编号。 + /// + public abstract int Id + { + get; + } + + /// + /// 解析数据表行。 + /// + /// 要解析的数据表行字符串。 + /// 用户自定义数据。 + /// 是否解析数据表行成功。 + public virtual bool ParseDataRow(string dataRowString, object userData) + { + Log.Warning("Not implemented ParseDataRow(string dataRowString, object userData)."); + return false; + } + + /// + /// 解析数据表行。 + /// + /// 要解析的数据表行二进制流。 + /// 数据表行二进制流的起始位置。 + /// 数据表行二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析数据表行成功。 + public virtual bool ParseDataRow(byte[] dataRowBytes, int startIndex, int length, object userData) + { + Log.Warning("Not implemented ParseDataRow(byte[] dataRowBytes, int startIndex, int length, object userData)."); + return false; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataRowBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataRowBase.cs.meta new file mode 100644 index 0000000..83d9904 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataRowBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b2e51f0c2dffb5748b75e474971bbe09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataTableComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataTableComponent.cs new file mode 100644 index 0000000..5ead536 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataTableComponent.cs @@ -0,0 +1,399 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.DataTable; +using GameFramework.Resource; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 数据表组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Data Table")] + public sealed class DataTableComponent : GameFrameworkComponent + { + private const int DefaultPriority = 0; + + private IDataTableManager m_DataTableManager = null; + private EventComponent m_EventComponent = null; + + [SerializeField] + private bool m_EnableLoadDataTableUpdateEvent = false; + + [SerializeField] + private bool m_EnableLoadDataTableDependencyAssetEvent = false; + + [SerializeField] + private string m_DataTableHelperTypeName = "UnityGameFramework.Runtime.DefaultDataTableHelper"; + + [SerializeField] + private DataTableHelperBase m_CustomDataTableHelper = null; + + [SerializeField] + private int m_CachedBytesSize = 0; + + /// + /// 获取数据表数量。 + /// + public int Count + { + get + { + return m_DataTableManager.Count; + } + } + + /// + /// 获取缓冲二进制流的大小。 + /// + public int CachedBytesSize + { + get + { + return m_DataTableManager.CachedBytesSize; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_DataTableManager = GameFrameworkEntry.GetModule(); + if (m_DataTableManager == null) + { + Log.Fatal("Data table manager is invalid."); + return; + } + } + + private void Start() + { + BaseComponent baseComponent = GameEntry.GetComponent(); + if (baseComponent == null) + { + Log.Fatal("Base component is invalid."); + return; + } + + m_EventComponent = GameEntry.GetComponent(); + if (m_EventComponent == null) + { + Log.Fatal("Event component is invalid."); + return; + } + + if (baseComponent.EditorResourceMode) + { + m_DataTableManager.SetResourceManager(baseComponent.EditorResourceHelper); + } + else + { + m_DataTableManager.SetResourceManager(GameFrameworkEntry.GetModule()); + } + + DataTableHelperBase dataTableHelper = Helper.CreateHelper(m_DataTableHelperTypeName, m_CustomDataTableHelper); + if (dataTableHelper == null) + { + Log.Error("Can not create data table helper."); + return; + } + + dataTableHelper.name = "Data Table Helper"; + Transform transform = dataTableHelper.transform; + transform.SetParent(this.transform); + transform.localScale = Vector3.one; + + m_DataTableManager.SetDataProviderHelper(dataTableHelper); + m_DataTableManager.SetDataTableHelper(dataTableHelper); + if (m_CachedBytesSize > 0) + { + EnsureCachedBytesSize(m_CachedBytesSize); + } + } + + /// + /// 确保二进制流缓存分配足够大小的内存并缓存。 + /// + /// 要确保二进制流缓存分配内存的大小。 + public void EnsureCachedBytesSize(int ensureSize) + { + m_DataTableManager.EnsureCachedBytesSize(ensureSize); + } + + /// + /// 释放缓存的二进制流。 + /// + public void FreeCachedBytes() + { + m_DataTableManager.FreeCachedBytes(); + } + + /// + /// 是否存在数据表。 + /// + /// 数据表行的类型。 + /// 是否存在数据表。 + public bool HasDataTable() where T : IDataRow + { + return m_DataTableManager.HasDataTable(); + } + + /// + /// 是否存在数据表。 + /// + /// 数据表行的类型。 + /// 是否存在数据表。 + public bool HasDataTable(Type dataRowType) + { + return m_DataTableManager.HasDataTable(dataRowType); + } + + /// + /// 是否存在数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 是否存在数据表。 + public bool HasDataTable(string name) where T : IDataRow + { + return m_DataTableManager.HasDataTable(name); + } + + /// + /// 是否存在数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 是否存在数据表。 + public bool HasDataTable(Type dataRowType, string name) + { + return m_DataTableManager.HasDataTable(dataRowType, name); + } + + /// + /// 获取数据表。 + /// + /// 数据表行的类型。 + /// 要获取的数据表。 + public IDataTable GetDataTable() where T : IDataRow + { + return m_DataTableManager.GetDataTable(); + } + + /// + /// 获取数据表。 + /// + /// 数据表行的类型。 + /// 要获取的数据表。 + public DataTableBase GetDataTable(Type dataRowType) + { + return m_DataTableManager.GetDataTable(dataRowType); + } + + /// + /// 获取数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 要获取的数据表。 + public IDataTable GetDataTable(string name) where T : IDataRow + { + return m_DataTableManager.GetDataTable(name); + } + + /// + /// 获取数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 要获取的数据表。 + public DataTableBase GetDataTable(Type dataRowType, string name) + { + return m_DataTableManager.GetDataTable(dataRowType, name); + } + + /// + /// 获取所有数据表。 + /// + public DataTableBase[] GetAllDataTables() + { + return m_DataTableManager.GetAllDataTables(); + } + + /// + /// 获取所有数据表。 + /// + /// 所有数据表。 + public void GetAllDataTables(List results) + { + m_DataTableManager.GetAllDataTables(results); + } + + /// + /// 创建数据表。 + /// + /// 数据表行的类型。 + /// 要创建的数据表。 + public IDataTable CreateDataTable() where T : class, IDataRow, new() + { + return CreateDataTable(null); + } + + /// + /// 创建数据表。 + /// + /// 数据表行的类型。 + /// 要创建的数据表。 + public DataTableBase CreateDataTable(Type dataRowType) + { + return CreateDataTable(dataRowType, null); + } + + /// + /// 创建数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 要创建的数据表。 + public IDataTable CreateDataTable(string name) where T : class, IDataRow, new() + { + IDataTable dataTable = m_DataTableManager.CreateDataTable(name); + DataTableBase dataTableBase = (DataTableBase)dataTable; + dataTableBase.ReadDataSuccess += OnReadDataSuccess; + dataTableBase.ReadDataFailure += OnReadDataFailure; + + if (m_EnableLoadDataTableUpdateEvent) + { + dataTableBase.ReadDataUpdate += OnReadDataUpdate; + } + + if (m_EnableLoadDataTableDependencyAssetEvent) + { + dataTableBase.ReadDataDependencyAsset += OnReadDataDependencyAsset; + } + + return dataTable; + } + + /// + /// 创建数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 要创建的数据表。 + public DataTableBase CreateDataTable(Type dataRowType, string name) + { + DataTableBase dataTable = m_DataTableManager.CreateDataTable(dataRowType, name); + dataTable.ReadDataSuccess += OnReadDataSuccess; + dataTable.ReadDataFailure += OnReadDataFailure; + + if (m_EnableLoadDataTableUpdateEvent) + { + dataTable.ReadDataUpdate += OnReadDataUpdate; + } + + if (m_EnableLoadDataTableDependencyAssetEvent) + { + dataTable.ReadDataDependencyAsset += OnReadDataDependencyAsset; + } + + return dataTable; + } + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 是否销毁数据表成功。 + public bool DestroyDataTable() where T : IDataRow, new() + { + return m_DataTableManager.DestroyDataTable(); + } + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 是否销毁数据表成功。 + public bool DestroyDataTable(Type dataRowType) + { + return m_DataTableManager.DestroyDataTable(dataRowType); + } + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 是否销毁数据表成功。 + public bool DestroyDataTable(string name) where T : IDataRow + { + return m_DataTableManager.DestroyDataTable(name); + } + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 数据表名称。 + /// 是否销毁数据表成功。 + public bool DestroyDataTable(Type dataRowType, string name) + { + return m_DataTableManager.DestroyDataTable(dataRowType, name); + } + + /// + /// 销毁数据表。 + /// + /// 数据表行的类型。 + /// 要销毁的数据表。 + /// 是否销毁数据表成功。 + public bool DestroyDataTable(IDataTable dataTable) where T : IDataRow + { + return m_DataTableManager.DestroyDataTable(dataTable); + } + + /// + /// 销毁数据表。 + /// + /// 要销毁的数据表。 + /// 是否销毁数据表成功。 + public bool DestroyDataTable(DataTableBase dataTable) + { + return m_DataTableManager.DestroyDataTable(dataTable); + } + + private void OnReadDataSuccess(object sender, ReadDataSuccessEventArgs e) + { + m_EventComponent.Fire(this, LoadDataTableSuccessEventArgs.Create(e)); + } + + private void OnReadDataFailure(object sender, ReadDataFailureEventArgs e) + { + Log.Warning("Load data table failure, asset name '{0}', error message '{1}'.", e.DataAssetName, e.ErrorMessage); + m_EventComponent.Fire(this, LoadDataTableFailureEventArgs.Create(e)); + } + + private void OnReadDataUpdate(object sender, ReadDataUpdateEventArgs e) + { + m_EventComponent.Fire(this, LoadDataTableUpdateEventArgs.Create(e)); + } + + private void OnReadDataDependencyAsset(object sender, ReadDataDependencyAssetEventArgs e) + { + m_EventComponent.Fire(this, LoadDataTableDependencyAssetEventArgs.Create(e)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataTableComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataTableComponent.cs.meta new file mode 100644 index 0000000..2e0e4c6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataTableComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 54066418ab853614483ea44b531049f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataTableHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataTableHelperBase.cs new file mode 100644 index 0000000..43dd46d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataTableHelperBase.cs @@ -0,0 +1,68 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.DataTable; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 数据表辅助器基类。 + /// + public abstract class DataTableHelperBase : MonoBehaviour, IDataProviderHelper, IDataTableHelper + { + /// + /// 读取数据表。 + /// + /// 数据表。 + /// 数据表资源名称。 + /// 数据表资源。 + /// 用户自定义数据。 + /// 是否读取数据表成功。 + public abstract bool ReadData(DataTableBase dataTable, string dataTableAssetName, object dataTableAsset, object userData); + + /// + /// 读取数据表。 + /// + /// 数据表。 + /// 数据表资源名称。 + /// 数据表二进制流。 + /// 数据表二进制流的起始位置。 + /// 数据表二进制流的长度。 + /// 用户自定义数据。 + /// 是否读取数据表成功。 + public abstract bool ReadData(DataTableBase dataTable, string dataTableAssetName, byte[] dataTableBytes, int startIndex, int length, object userData); + + /// + /// 解析数据表。 + /// + /// 数据表。 + /// 要解析的数据表字符串。 + /// 用户自定义数据。 + /// 是否解析数据表成功。 + public abstract bool ParseData(DataTableBase dataTable, string dataTableString, object userData); + + /// + /// 解析数据表。 + /// + /// 数据表。 + /// 要解析的数据表二进制流。 + /// 数据表二进制流的起始位置。 + /// 数据表二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析数据表成功。 + public abstract bool ParseData(DataTableBase dataTable, byte[] dataTableBytes, int startIndex, int length, object userData); + + /// + /// 释放数据表资源。 + /// + /// 数据表。 + /// 要释放的数据表资源。 + public abstract void ReleaseDataAsset(DataTableBase dataTable, object dataTableAsset); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataTableHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataTableHelperBase.cs.meta new file mode 100644 index 0000000..f66377e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DataTableHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0c48521d647fac4408f41cca9820ec55 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DefaultDataTableHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DefaultDataTableHelper.cs new file mode 100644 index 0000000..3dd85d5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DefaultDataTableHelper.cs @@ -0,0 +1,171 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.DataTable; +using System; +using System.IO; +using System.Text; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认数据表辅助器。 + /// + public class DefaultDataTableHelper : DataTableHelperBase + { + private static readonly string BytesAssetExtension = ".bytes"; + + private ResourceComponent m_ResourceComponent = null; + + /// + /// 读取数据表。 + /// + /// 数据表。 + /// 数据表资源名称。 + /// 数据表资源。 + /// 用户自定义数据。 + /// 是否读取数据表成功。 + public override bool ReadData(DataTableBase dataTable, string dataTableAssetName, object dataTableAsset, object userData) + { + TextAsset dataTableTextAsset = dataTableAsset as TextAsset; + if (dataTableTextAsset != null) + { + if (dataTableAssetName.EndsWith(BytesAssetExtension, StringComparison.Ordinal)) + { + return dataTable.ParseData(dataTableTextAsset.bytes, userData); + } + else + { + return dataTable.ParseData(dataTableTextAsset.text, userData); + } + } + + Log.Warning("Data table asset '{0}' is invalid.", dataTableAssetName); + return false; + } + + /// + /// 读取数据表。 + /// + /// 数据表。 + /// 数据表资源名称。 + /// 数据表二进制流。 + /// 数据表二进制流的起始位置。 + /// 数据表二进制流的长度。 + /// 用户自定义数据。 + /// 是否读取数据表成功。 + public override bool ReadData(DataTableBase dataTable, string dataTableAssetName, byte[] dataTableBytes, int startIndex, int length, object userData) + { + if (dataTableAssetName.EndsWith(BytesAssetExtension, StringComparison.Ordinal)) + { + return dataTable.ParseData(dataTableBytes, startIndex, length, userData); + } + else + { + return dataTable.ParseData(Utility.Converter.GetString(dataTableBytes, startIndex, length), userData); + } + } + + /// + /// 解析数据表。 + /// + /// 数据表。 + /// 要解析的数据表字符串。 + /// 用户自定义数据。 + /// 是否解析数据表成功。 + public override bool ParseData(DataTableBase dataTable, string dataTableString, object userData) + { + try + { + int position = 0; + string dataRowString = null; + while ((dataRowString = dataTableString.ReadLine(ref position)) != null) + { + if (dataRowString[0] == '#') + { + continue; + } + + if (!dataTable.AddDataRow(dataRowString, userData)) + { + Log.Warning("Can not parse data row string '{0}'.", dataRowString); + return false; + } + } + + return true; + } + catch (Exception exception) + { + Log.Warning("Can not parse data table string with exception '{0}'.", exception); + return false; + } + } + + /// + /// 解析数据表。 + /// + /// 数据表。 + /// 要解析的数据表二进制流。 + /// 数据表二进制流的起始位置。 + /// 数据表二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析数据表成功。 + public override bool ParseData(DataTableBase dataTable, byte[] dataTableBytes, int startIndex, int length, object userData) + { + try + { + using (MemoryStream memoryStream = new MemoryStream(dataTableBytes, startIndex, length, false)) + { + using (BinaryReader binaryReader = new BinaryReader(memoryStream, Encoding.UTF8)) + { + while (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length) + { + int dataRowBytesLength = binaryReader.Read7BitEncodedInt32(); + if (!dataTable.AddDataRow(dataTableBytes, (int)binaryReader.BaseStream.Position, dataRowBytesLength, userData)) + { + Log.Warning("Can not parse data row bytes."); + return false; + } + + binaryReader.BaseStream.Position += dataRowBytesLength; + } + } + } + + return true; + } + catch (Exception exception) + { + Log.Warning("Can not parse dictionary bytes with exception '{0}'.", exception); + return false; + } + } + + /// + /// 释放数据表资源。 + /// + /// 数据表。 + /// 要释放的数据表资源。 + public override void ReleaseDataAsset(DataTableBase dataTable, object dataTableAsset) + { + m_ResourceComponent.UnloadAsset(dataTableAsset); + } + + private void Start() + { + m_ResourceComponent = GameEntry.GetComponent(); + if (m_ResourceComponent == null) + { + Log.Fatal("Resource component is invalid."); + return; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DefaultDataTableHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DefaultDataTableHelper.cs.meta new file mode 100644 index 0000000..536b3c6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/DefaultDataTableHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f6a52ac548bf3654a93c12610240a67d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableDependencyAssetEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableDependencyAssetEventArgs.cs new file mode 100644 index 0000000..7205de1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableDependencyAssetEventArgs.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载数据表时加载依赖资源事件。 + /// + public sealed class LoadDataTableDependencyAssetEventArgs : GameEventArgs + { + /// + /// 加载数据表时加载依赖资源事件编号。 + /// + public static readonly int EventId = typeof(LoadDataTableDependencyAssetEventArgs).GetHashCode(); + + /// + /// 初始化加载数据表时加载依赖资源事件的新实例。 + /// + public LoadDataTableDependencyAssetEventArgs() + { + DataTableAssetName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + + /// + /// 获取加载数据表时加载依赖资源事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取数据表资源名称。 + /// + public string DataTableAssetName + { + get; + private set; + } + + /// + /// 获取被加载的依赖资源名称。 + /// + public string DependencyAssetName + { + get; + private set; + } + + /// + /// 获取当前已加载依赖资源数量。 + /// + public int LoadedCount + { + get; + private set; + } + + /// + /// 获取总共加载依赖资源数量。 + /// + public int TotalCount + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载数据表时加载依赖资源事件。 + /// + /// 内部事件。 + /// 创建的加载数据表时加载依赖资源事件。 + public static LoadDataTableDependencyAssetEventArgs Create(ReadDataDependencyAssetEventArgs e) + { + LoadDataTableDependencyAssetEventArgs loadDataTableDependencyAssetEventArgs = ReferencePool.Acquire(); + loadDataTableDependencyAssetEventArgs.DataTableAssetName = e.DataAssetName; + loadDataTableDependencyAssetEventArgs.DependencyAssetName = e.DependencyAssetName; + loadDataTableDependencyAssetEventArgs.LoadedCount = e.LoadedCount; + loadDataTableDependencyAssetEventArgs.TotalCount = e.TotalCount; + loadDataTableDependencyAssetEventArgs.UserData = e.UserData; + return loadDataTableDependencyAssetEventArgs; + } + + /// + /// 清理加载数据表时加载依赖资源事件。 + /// + public override void Clear() + { + DataTableAssetName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableDependencyAssetEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableDependencyAssetEventArgs.cs.meta new file mode 100644 index 0000000..95e5ddc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableDependencyAssetEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d55700c511451364c85eca18f23c5e9e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableFailureEventArgs.cs new file mode 100644 index 0000000..e8477f4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableFailureEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载数据表失败事件。 + /// + public sealed class LoadDataTableFailureEventArgs : GameEventArgs + { + /// + /// 加载数据表失败事件编号。 + /// + public static readonly int EventId = typeof(LoadDataTableFailureEventArgs).GetHashCode(); + + /// + /// 初始化加载数据表失败事件的新实例。 + /// + public LoadDataTableFailureEventArgs() + { + DataTableAssetName = null; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取加载数据表失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取数据表资源名称。 + /// + public string DataTableAssetName + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载数据表失败事件。 + /// + /// 内部事件。 + /// 创建的加载数据表失败事件。 + public static LoadDataTableFailureEventArgs Create(ReadDataFailureEventArgs e) + { + LoadDataTableFailureEventArgs loadDataTableFailureEventArgs = ReferencePool.Acquire(); + loadDataTableFailureEventArgs.DataTableAssetName = e.DataAssetName; + loadDataTableFailureEventArgs.ErrorMessage = e.ErrorMessage; + loadDataTableFailureEventArgs.UserData = e.UserData; + return loadDataTableFailureEventArgs; + } + + /// + /// 清理加载数据表失败事件。 + /// + public override void Clear() + { + DataTableAssetName = null; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableFailureEventArgs.cs.meta new file mode 100644 index 0000000..5bb41e6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7196ee8c6ea2e0c4ebd4825fe6c9dcd1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableSuccessEventArgs.cs new file mode 100644 index 0000000..7c6687b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableSuccessEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载数据表成功事件。 + /// + public sealed class LoadDataTableSuccessEventArgs : GameEventArgs + { + /// + /// 加载数据表成功事件编号。 + /// + public static readonly int EventId = typeof(LoadDataTableSuccessEventArgs).GetHashCode(); + + /// + /// 初始化加载数据表成功事件的新实例。 + /// + public LoadDataTableSuccessEventArgs() + { + DataTableAssetName = null; + Duration = 0f; + UserData = null; + } + + /// + /// 获取加载数据表成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取数据表资源名称。 + /// + public string DataTableAssetName + { + get; + private set; + } + + /// + /// 获取加载持续时间。 + /// + public float Duration + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载数据表成功事件。 + /// + /// 内部事件。 + /// 创建的加载数据表成功事件。 + public static LoadDataTableSuccessEventArgs Create(ReadDataSuccessEventArgs e) + { + LoadDataTableSuccessEventArgs loadDataTableSuccessEventArgs = ReferencePool.Acquire(); + loadDataTableSuccessEventArgs.DataTableAssetName = e.DataAssetName; + loadDataTableSuccessEventArgs.Duration = e.Duration; + loadDataTableSuccessEventArgs.UserData = e.UserData; + return loadDataTableSuccessEventArgs; + } + + /// + /// 清理加载数据表成功事件。 + /// + public override void Clear() + { + DataTableAssetName = null; + Duration = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableSuccessEventArgs.cs.meta new file mode 100644 index 0000000..7c9f1e7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed41d1abe08b7754481956fece8dfba4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableUpdateEventArgs.cs new file mode 100644 index 0000000..0c65ac7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableUpdateEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载数据表更新事件。 + /// + public sealed class LoadDataTableUpdateEventArgs : GameEventArgs + { + /// + /// 加载数据表更新事件编号。 + /// + public static readonly int EventId = typeof(LoadDataTableUpdateEventArgs).GetHashCode(); + + /// + /// 初始化加载数据表更新事件的新实例。 + /// + public LoadDataTableUpdateEventArgs() + { + DataTableAssetName = null; + Progress = 0f; + UserData = null; + } + + /// + /// 获取加载数据表更新事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取数据表资源名称。 + /// + public string DataTableAssetName + { + get; + private set; + } + + /// + /// 获取加载数据表进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载数据表更新事件。 + /// + /// 内部事件。 + /// 创建的加载数据表更新事件。 + public static LoadDataTableUpdateEventArgs Create(ReadDataUpdateEventArgs e) + { + LoadDataTableUpdateEventArgs loadDataTableUpdateEventArgs = ReferencePool.Acquire(); + loadDataTableUpdateEventArgs.DataTableAssetName = e.DataAssetName; + loadDataTableUpdateEventArgs.Progress = e.Progress; + loadDataTableUpdateEventArgs.UserData = e.UserData; + return loadDataTableUpdateEventArgs; + } + + /// + /// 清理加载数据表更新事件。 + /// + public override void Clear() + { + DataTableAssetName = null; + Progress = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableUpdateEventArgs.cs.meta new file mode 100644 index 0000000..9d35c4a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/DataTable/LoadDataTableUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 35eba4a8a9ee9954392a0e99aa8111d6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger.meta new file mode 100644 index 0000000..4f7afab --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eadd5c8c1a8797c45b1c8a9635f8cf52 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerActiveWindowType.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerActiveWindowType.cs new file mode 100644 index 0000000..2a5fa6d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerActiveWindowType.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Runtime +{ + /// + /// 调试器激活窗口类型。 + /// + public enum DebuggerActiveWindowType : byte + { + /// + /// 总是打开。 + /// + AlwaysOpen = 0, + + /// + /// 仅在开发模式时打开。 + /// + OnlyOpenWhenDevelopment, + + /// + /// 仅在编辑器中打开。 + /// + OnlyOpenInEditor, + + /// + /// 总是关闭。 + /// + AlwaysClose, + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerActiveWindowType.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerActiveWindowType.cs.meta new file mode 100644 index 0000000..b73d304 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerActiveWindowType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d1baccfe5abb590428eb0322088bf4ce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ConsoleWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ConsoleWindow.cs new file mode 100644 index 0000000..8b66cae --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ConsoleWindow.cs @@ -0,0 +1,509 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Debugger; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + [Serializable] + private sealed class ConsoleWindow : IDebuggerWindow + { + private readonly Queue m_LogNodes = new Queue(); + + private SettingComponent m_SettingComponent = null; + private Vector2 m_LogScrollPosition = Vector2.zero; + private Vector2 m_StackScrollPosition = Vector2.zero; + private int m_InfoCount = 0; + private int m_WarningCount = 0; + private int m_ErrorCount = 0; + private int m_FatalCount = 0; + private LogNode m_SelectedNode = null; + private bool m_LastLockScroll = true; + private bool m_LastInfoFilter = true; + private bool m_LastWarningFilter = true; + private bool m_LastErrorFilter = true; + private bool m_LastFatalFilter = true; + + [SerializeField] + private bool m_LockScroll = true; + + [SerializeField] + private int m_MaxLine = 100; + + [SerializeField] + private bool m_InfoFilter = true; + + [SerializeField] + private bool m_WarningFilter = true; + + [SerializeField] + private bool m_ErrorFilter = true; + + [SerializeField] + private bool m_FatalFilter = true; + + [SerializeField] + private Color32 m_InfoColor = Color.white; + + [SerializeField] + private Color32 m_WarningColor = Color.yellow; + + [SerializeField] + private Color32 m_ErrorColor = Color.red; + + [SerializeField] + private Color32 m_FatalColor = new Color(0.7f, 0.2f, 0.2f); + + public bool LockScroll + { + get + { + return m_LockScroll; + } + set + { + m_LockScroll = value; + } + } + + public int MaxLine + { + get + { + return m_MaxLine; + } + set + { + m_MaxLine = value; + } + } + + public bool InfoFilter + { + get + { + return m_InfoFilter; + } + set + { + m_InfoFilter = value; + } + } + + public bool WarningFilter + { + get + { + return m_WarningFilter; + } + set + { + m_WarningFilter = value; + } + } + + public bool ErrorFilter + { + get + { + return m_ErrorFilter; + } + set + { + m_ErrorFilter = value; + } + } + + public bool FatalFilter + { + get + { + return m_FatalFilter; + } + set + { + m_FatalFilter = value; + } + } + + public int InfoCount + { + get + { + return m_InfoCount; + } + } + + public int WarningCount + { + get + { + return m_WarningCount; + } + } + + public int ErrorCount + { + get + { + return m_ErrorCount; + } + } + + public int FatalCount + { + get + { + return m_FatalCount; + } + } + + public Color32 InfoColor + { + get + { + return m_InfoColor; + } + set + { + m_InfoColor = value; + } + } + + public Color32 WarningColor + { + get + { + return m_WarningColor; + } + set + { + m_WarningColor = value; + } + } + + public Color32 ErrorColor + { + get + { + return m_ErrorColor; + } + set + { + m_ErrorColor = value; + } + } + + public Color32 FatalColor + { + get + { + return m_FatalColor; + } + set + { + m_FatalColor = value; + } + } + + public void Initialize(params object[] args) + { + m_SettingComponent = GameEntry.GetComponent(); + if (m_SettingComponent == null) + { + Log.Fatal("Setting component is invalid."); + return; + } + + Application.logMessageReceived += OnLogMessageReceived; + m_LockScroll = m_LastLockScroll = m_SettingComponent.GetBool("Debugger.Console.LockScroll", true); + m_InfoFilter = m_LastInfoFilter = m_SettingComponent.GetBool("Debugger.Console.InfoFilter", true); + m_WarningFilter = m_LastWarningFilter = m_SettingComponent.GetBool("Debugger.Console.WarningFilter", true); + m_ErrorFilter = m_LastErrorFilter = m_SettingComponent.GetBool("Debugger.Console.ErrorFilter", true); + m_FatalFilter = m_LastFatalFilter = m_SettingComponent.GetBool("Debugger.Console.FatalFilter", true); + } + + public void Shutdown() + { + Application.logMessageReceived -= OnLogMessageReceived; + Clear(); + } + + public void OnEnter() + { + } + + public void OnLeave() + { + } + + public void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + if (m_LastLockScroll != m_LockScroll) + { + m_LastLockScroll = m_LockScroll; + m_SettingComponent.SetBool("Debugger.Console.LockScroll", m_LockScroll); + } + + if (m_LastInfoFilter != m_InfoFilter) + { + m_LastInfoFilter = m_InfoFilter; + m_SettingComponent.SetBool("Debugger.Console.InfoFilter", m_InfoFilter); + } + + if (m_LastWarningFilter != m_WarningFilter) + { + m_LastWarningFilter = m_WarningFilter; + m_SettingComponent.SetBool("Debugger.Console.WarningFilter", m_WarningFilter); + } + + if (m_LastErrorFilter != m_ErrorFilter) + { + m_LastErrorFilter = m_ErrorFilter; + m_SettingComponent.SetBool("Debugger.Console.ErrorFilter", m_ErrorFilter); + } + + if (m_LastFatalFilter != m_FatalFilter) + { + m_LastFatalFilter = m_FatalFilter; + m_SettingComponent.SetBool("Debugger.Console.FatalFilter", m_FatalFilter); + } + } + + public void OnDraw() + { + RefreshCount(); + + GUILayout.BeginHorizontal(); + { + if (GUILayout.Button("Clear All", GUILayout.Width(100f))) + { + Clear(); + } + m_LockScroll = GUILayout.Toggle(m_LockScroll, "Lock Scroll", GUILayout.Width(90f)); + GUILayout.FlexibleSpace(); + m_InfoFilter = GUILayout.Toggle(m_InfoFilter, Utility.Text.Format("Info ({0})", m_InfoCount), GUILayout.Width(90f)); + m_WarningFilter = GUILayout.Toggle(m_WarningFilter, Utility.Text.Format("Warning ({0})", m_WarningCount), GUILayout.Width(90f)); + m_ErrorFilter = GUILayout.Toggle(m_ErrorFilter, Utility.Text.Format("Error ({0})", m_ErrorCount), GUILayout.Width(90f)); + m_FatalFilter = GUILayout.Toggle(m_FatalFilter, Utility.Text.Format("Fatal ({0})", m_FatalCount), GUILayout.Width(90f)); + } + GUILayout.EndHorizontal(); + + GUILayout.BeginVertical("box"); + { + if (m_LockScroll) + { + m_LogScrollPosition.y = float.MaxValue; + } + + m_LogScrollPosition = GUILayout.BeginScrollView(m_LogScrollPosition); + { + bool selected = false; + foreach (LogNode logNode in m_LogNodes) + { + switch (logNode.LogType) + { + case LogType.Log: + if (!m_InfoFilter) + { + continue; + } + break; + + case LogType.Warning: + if (!m_WarningFilter) + { + continue; + } + break; + + case LogType.Error: + if (!m_ErrorFilter) + { + continue; + } + break; + + case LogType.Exception: + if (!m_FatalFilter) + { + continue; + } + break; + } + if (GUILayout.Toggle(m_SelectedNode == logNode, GetLogString(logNode))) + { + selected = true; + if (m_SelectedNode != logNode) + { + m_SelectedNode = logNode; + m_StackScrollPosition = Vector2.zero; + } + } + } + if (!selected) + { + m_SelectedNode = null; + } + } + GUILayout.EndScrollView(); + } + GUILayout.EndVertical(); + + GUILayout.BeginVertical("box"); + { + m_StackScrollPosition = GUILayout.BeginScrollView(m_StackScrollPosition, GUILayout.Height(100f)); + { + if (m_SelectedNode != null) + { + Color32 color = GetLogStringColor(m_SelectedNode.LogType); + if (GUILayout.Button(Utility.Text.Format("{4}{6}{6}{5}", color.r, color.g, color.b, color.a, m_SelectedNode.LogMessage, m_SelectedNode.StackTrack, Environment.NewLine), "label")) + { + CopyToClipboard(Utility.Text.Format("{0}{2}{2}{1}", m_SelectedNode.LogMessage, m_SelectedNode.StackTrack, Environment.NewLine)); + } + } + } + GUILayout.EndScrollView(); + } + GUILayout.EndVertical(); + } + + private void Clear() + { + m_LogNodes.Clear(); + } + + public void RefreshCount() + { + m_InfoCount = 0; + m_WarningCount = 0; + m_ErrorCount = 0; + m_FatalCount = 0; + foreach (LogNode logNode in m_LogNodes) + { + switch (logNode.LogType) + { + case LogType.Log: + m_InfoCount++; + break; + + case LogType.Warning: + m_WarningCount++; + break; + + case LogType.Error: + m_ErrorCount++; + break; + + case LogType.Exception: + m_FatalCount++; + break; + } + } + } + + public void GetRecentLogs(List results) + { + if (results == null) + { + Log.Error("Results is invalid."); + return; + } + + results.Clear(); + foreach (LogNode logNode in m_LogNodes) + { + results.Add(logNode); + } + } + + public void GetRecentLogs(List results, int count) + { + if (results == null) + { + Log.Error("Results is invalid."); + return; + } + + if (count <= 0) + { + Log.Error("Count is invalid."); + return; + } + + int position = m_LogNodes.Count - count; + if (position < 0) + { + position = 0; + } + + int index = 0; + results.Clear(); + foreach (LogNode logNode in m_LogNodes) + { + if (index++ < position) + { + continue; + } + + results.Add(logNode); + } + } + + private void OnLogMessageReceived(string logMessage, string stackTrace, LogType logType) + { + if (logType == LogType.Assert) + { + logType = LogType.Error; + } + + m_LogNodes.Enqueue(LogNode.Create(logType, logMessage, stackTrace)); + while (m_LogNodes.Count > m_MaxLine) + { + ReferencePool.Release(m_LogNodes.Dequeue()); + } + } + + private string GetLogString(LogNode logNode) + { + Color32 color = GetLogStringColor(logNode.LogType); + return Utility.Text.Format("[{4:HH:mm:ss.fff}][{5}] {6}", color.r, color.g, color.b, color.a, logNode.LogTime.ToLocalTime(), logNode.LogFrameCount, logNode.LogMessage); + } + + internal Color32 GetLogStringColor(LogType logType) + { + Color32 color = Color.white; + switch (logType) + { + case LogType.Log: + color = m_InfoColor; + break; + + case LogType.Warning: + color = m_WarningColor; + break; + + case LogType.Error: + color = m_ErrorColor; + break; + + case LogType.Exception: + color = m_FatalColor; + break; + } + + return color; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ConsoleWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ConsoleWindow.cs.meta new file mode 100644 index 0000000..8bfcbe3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ConsoleWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4a47e2730f999784eb1bbeefab72ef11 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.EnvironmentInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.EnvironmentInformationWindow.cs new file mode 100644 index 0000000..ff5b6ba --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.EnvironmentInformationWindow.cs @@ -0,0 +1,96 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; +#if UNITY_5_5_OR_NEWER +using UnityEngine.Rendering; +#endif + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class EnvironmentInformationWindow : ScrollableDebuggerWindowBase + { + private BaseComponent m_BaseComponent = null; + private ResourceComponent m_ResourceComponent = null; + + public override void Initialize(params object[] args) + { + m_BaseComponent = GameEntry.GetComponent(); + if (m_BaseComponent == null) + { + Log.Fatal("Base component is invalid."); + return; + } + + m_ResourceComponent = GameEntry.GetComponent(); + if (m_ResourceComponent == null) + { + Log.Fatal("Resource component is invalid."); + return; + } + } + + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Environment Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Product Name", Application.productName); + DrawItem("Company Name", Application.companyName); +#if UNITY_5_6_OR_NEWER + DrawItem("Game Identifier", Application.identifier); +#else + DrawItem("Game Identifier", Application.bundleIdentifier); +#endif + DrawItem("Game Framework Version", Version.GameFrameworkVersion); + DrawItem("Game Version", Utility.Text.Format("{0} ({1})", Version.GameVersion, Version.InternalGameVersion)); + DrawItem("Resource Version", m_BaseComponent.EditorResourceMode ? "Unavailable in editor resource mode" : (string.IsNullOrEmpty(m_ResourceComponent.ApplicableGameVersion) ? "Unknown" : Utility.Text.Format("{0} ({1})", m_ResourceComponent.ApplicableGameVersion, m_ResourceComponent.InternalResourceVersion))); + DrawItem("Application Version", Application.version); + DrawItem("Unity Version", Application.unityVersion); + DrawItem("Platform", Application.platform.ToString()); + DrawItem("System Language", Application.systemLanguage.ToString()); + DrawItem("Cloud Project Id", Application.cloudProjectId); +#if UNITY_5_6_OR_NEWER + DrawItem("Build Guid", Application.buildGUID); +#endif + DrawItem("Target Frame Rate", Application.targetFrameRate.ToString()); + DrawItem("Internet Reachability", Application.internetReachability.ToString()); + DrawItem("Background Loading Priority", Application.backgroundLoadingPriority.ToString()); + DrawItem("Is Playing", Application.isPlaying.ToString()); +#if UNITY_5_5_OR_NEWER + DrawItem("Splash Screen Is Finished", SplashScreen.isFinished.ToString()); +#else + DrawItem("Is Showing Splash Screen", Application.isShowingSplashScreen.ToString()); +#endif + DrawItem("Run In Background", Application.runInBackground.ToString()); +#if UNITY_5_5_OR_NEWER + DrawItem("Install Name", Application.installerName); +#endif + DrawItem("Install Mode", Application.installMode.ToString()); + DrawItem("Sandbox Type", Application.sandboxType.ToString()); + DrawItem("Is Mobile Platform", Application.isMobilePlatform.ToString()); + DrawItem("Is Console Platform", Application.isConsolePlatform.ToString()); + DrawItem("Is Editor", Application.isEditor.ToString()); + DrawItem("Is Debug Build", Debug.isDebugBuild.ToString()); +#if UNITY_5_6_OR_NEWER + DrawItem("Is Focused", Application.isFocused.ToString()); +#endif +#if UNITY_2018_2_OR_NEWER + DrawItem("Is Batch Mode", Application.isBatchMode.ToString()); +#endif +#if UNITY_5_3 + DrawItem("Stack Trace Log Type", Application.stackTraceLogType.ToString()); +#endif + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.EnvironmentInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.EnvironmentInformationWindow.cs.meta new file mode 100644 index 0000000..6fea0ee --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.EnvironmentInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c52c8dc8849c5fb429c50b45975a599b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.FpsCounter.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.FpsCounter.cs new file mode 100644 index 0000000..87d24bd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.FpsCounter.cs @@ -0,0 +1,83 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class FpsCounter + { + private float m_UpdateInterval; + private float m_CurrentFps; + private int m_Frames; + private float m_Accumulator; + private float m_TimeLeft; + + public FpsCounter(float updateInterval) + { + if (updateInterval <= 0f) + { + Log.Error("Update interval is invalid."); + return; + } + + m_UpdateInterval = updateInterval; + Reset(); + } + + public float UpdateInterval + { + get + { + return m_UpdateInterval; + } + set + { + if (value <= 0f) + { + Log.Error("Update interval is invalid."); + return; + } + + m_UpdateInterval = value; + Reset(); + } + } + + public float CurrentFps + { + get + { + return m_CurrentFps; + } + } + + public void Update(float elapseSeconds, float realElapseSeconds) + { + m_Frames++; + m_Accumulator += realElapseSeconds; + m_TimeLeft -= realElapseSeconds; + + if (m_TimeLeft <= 0f) + { + m_CurrentFps = m_Accumulator > 0f ? m_Frames / m_Accumulator : 0f; + m_Frames = 0; + m_Accumulator = 0f; + m_TimeLeft += m_UpdateInterval; + } + } + + private void Reset() + { + m_CurrentFps = 0f; + m_Frames = 0; + m_Accumulator = 0f; + m_TimeLeft = 0f; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.FpsCounter.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.FpsCounter.cs.meta new file mode 100644 index 0000000..6c6467c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.FpsCounter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4f24c805ead515d4286d3c03cd50f750 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.GraphicsInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.GraphicsInformationWindow.cs new file mode 100644 index 0000000..9f6bed8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.GraphicsInformationWindow.cs @@ -0,0 +1,170 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class GraphicsInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Graphics Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Device ID", SystemInfo.graphicsDeviceID.ToString()); + DrawItem("Device Name", SystemInfo.graphicsDeviceName); + DrawItem("Device Vendor ID", SystemInfo.graphicsDeviceVendorID.ToString()); + DrawItem("Device Vendor", SystemInfo.graphicsDeviceVendor); + DrawItem("Device Type", SystemInfo.graphicsDeviceType.ToString()); + DrawItem("Device Version", SystemInfo.graphicsDeviceVersion); + DrawItem("Memory Size", Utility.Text.Format("{0} MB", SystemInfo.graphicsMemorySize)); + DrawItem("Multi Threaded", SystemInfo.graphicsMultiThreaded.ToString()); +#if UNITY_2019_3_OR_NEWER + DrawItem("Rendering Threading Mode", SystemInfo.renderingThreadingMode.ToString()); +#endif +#if UNITY_2020_1_OR_NEWER + DrawItem("HRD Display Support Flags", SystemInfo.hdrDisplaySupportFlags.ToString()); +#endif + DrawItem("Shader Level", GetShaderLevelString(SystemInfo.graphicsShaderLevel)); + DrawItem("Global Maximum LOD", Shader.globalMaximumLOD.ToString()); +#if UNITY_5_6_OR_NEWER + DrawItem("Global Render Pipeline", Shader.globalRenderPipeline); +#endif +#if UNITY_2020_2_OR_NEWER + DrawItem("Min OpenGLES Version", Graphics.minOpenGLESVersion.ToString()); +#endif +#if UNITY_5_5_OR_NEWER + DrawItem("Active Tier", Graphics.activeTier.ToString()); +#endif +#if UNITY_2017_2_OR_NEWER + DrawItem("Active Color Gamut", Graphics.activeColorGamut.ToString()); +#endif +#if UNITY_2019_2_OR_NEWER + DrawItem("Preserve Frame Buffer Alpha", Graphics.preserveFramebufferAlpha.ToString()); +#endif + DrawItem("NPOT Support", SystemInfo.npotSupport.ToString()); + DrawItem("Max Texture Size", SystemInfo.maxTextureSize.ToString()); + DrawItem("Supported Render Target Count", SystemInfo.supportedRenderTargetCount.ToString()); +#if UNITY_2019_3_OR_NEWER + DrawItem("Supported Random Write Target Count", SystemInfo.supportedRandomWriteTargetCount.ToString()); +#endif +#if UNITY_5_4_OR_NEWER + DrawItem("Copy Texture Support", SystemInfo.copyTextureSupport.ToString()); +#endif +#if UNITY_5_5_OR_NEWER + DrawItem("Uses Reversed ZBuffer", SystemInfo.usesReversedZBuffer.ToString()); +#endif +#if UNITY_5_6_OR_NEWER + DrawItem("Max Cubemap Size", SystemInfo.maxCubemapSize.ToString()); + DrawItem("Graphics UV Starts At Top", SystemInfo.graphicsUVStartsAtTop.ToString()); +#endif +#if UNITY_2020_2_OR_NEWER + DrawItem("Constant Buffer Offset Alignment", SystemInfo.constantBufferOffsetAlignment.ToString()); +#elif UNITY_2019_1_OR_NEWER + DrawItem("Min Constant Buffer Offset Alignment", SystemInfo.minConstantBufferOffsetAlignment.ToString()); +#endif +#if UNITY_2018_3_OR_NEWER + DrawItem("Has Hidden Surface Removal On GPU", SystemInfo.hasHiddenSurfaceRemovalOnGPU.ToString()); + DrawItem("Has Dynamic Uniform Array Indexing In Fragment Shaders", SystemInfo.hasDynamicUniformArrayIndexingInFragmentShaders.ToString()); +#endif +#if UNITY_2019_2_OR_NEWER + DrawItem("Has Mip Max Level", SystemInfo.hasMipMaxLevel.ToString()); +#endif +#if UNITY_2019_3_OR_NEWER + DrawItem("Uses Load Store Actions", SystemInfo.usesLoadStoreActions.ToString()); + DrawItem("Max Compute Buffer Inputs Compute", SystemInfo.maxComputeBufferInputsCompute.ToString()); + DrawItem("Max Compute Buffer Inputs Domain", SystemInfo.maxComputeBufferInputsDomain.ToString()); + DrawItem("Max Compute Buffer Inputs Fragment", SystemInfo.maxComputeBufferInputsFragment.ToString()); + DrawItem("Max Compute Buffer Inputs Geometry", SystemInfo.maxComputeBufferInputsGeometry.ToString()); + DrawItem("Max Compute Buffer Inputs Hull", SystemInfo.maxComputeBufferInputsHull.ToString()); + DrawItem("Max Compute Buffer Inputs Vertex", SystemInfo.maxComputeBufferInputsVertex.ToString()); + DrawItem("Max Compute Work Group Size", SystemInfo.maxComputeWorkGroupSize.ToString()); + DrawItem("Max Compute Work Group Size X", SystemInfo.maxComputeWorkGroupSizeX.ToString()); + DrawItem("Max Compute Work Group Size Y", SystemInfo.maxComputeWorkGroupSizeY.ToString()); + DrawItem("Max Compute Work Group Size Z", SystemInfo.maxComputeWorkGroupSizeZ.ToString()); +#endif +#if UNITY_5_3 || UNITY_5_4 + DrawItem("Supports Stencil", SystemInfo.supportsStencil.ToString()); + DrawItem("Supports Render Textures", SystemInfo.supportsRenderTextures.ToString()); +#endif + DrawItem("Supports Sparse Textures", SystemInfo.supportsSparseTextures.ToString()); + DrawItem("Supports 3D Textures", SystemInfo.supports3DTextures.ToString()); + DrawItem("Supports Shadows", SystemInfo.supportsShadows.ToString()); + DrawItem("Supports Raw Shadow Depth Sampling", SystemInfo.supportsRawShadowDepthSampling.ToString()); +#if !UNITY_2019_1_OR_NEWER + DrawItem("Supports Render To Cubemap", SystemInfo.supportsRenderToCubemap.ToString()); + DrawItem("Supports Image Effects", SystemInfo.supportsImageEffects.ToString()); +#endif + DrawItem("Supports Compute Shader", SystemInfo.supportsComputeShaders.ToString()); + DrawItem("Supports Instancing", SystemInfo.supportsInstancing.ToString()); +#if UNITY_5_4_OR_NEWER + DrawItem("Supports 2D Array Textures", SystemInfo.supports2DArrayTextures.ToString()); + DrawItem("Supports Motion Vectors", SystemInfo.supportsMotionVectors.ToString()); +#endif +#if UNITY_5_5_OR_NEWER + DrawItem("Supports Cubemap Array Textures", SystemInfo.supportsCubemapArrayTextures.ToString()); +#endif +#if UNITY_5_6_OR_NEWER + DrawItem("Supports 3D Render Textures", SystemInfo.supports3DRenderTextures.ToString()); +#endif +#if UNITY_2017_2_OR_NEWER && !UNITY_2017_2_0 || UNITY_2017_1_4 + DrawItem("Supports Texture Wrap Mirror Once", SystemInfo.supportsTextureWrapMirrorOnce.ToString()); +#endif +#if UNITY_2019_1_OR_NEWER + DrawItem("Supports Graphics Fence", SystemInfo.supportsGraphicsFence.ToString()); +#elif UNITY_2017_3_OR_NEWER + DrawItem("Supports GPU Fence", SystemInfo.supportsGPUFence.ToString()); +#endif +#if UNITY_2017_3_OR_NEWER + DrawItem("Supports Async Compute", SystemInfo.supportsAsyncCompute.ToString()); + DrawItem("Supports Multi-sampled Textures", SystemInfo.supportsMultisampledTextures.ToString()); +#endif +#if UNITY_2018_1_OR_NEWER + DrawItem("Supports Async GPU Readback", SystemInfo.supportsAsyncGPUReadback.ToString()); + DrawItem("Supports 32bits Index Buffer", SystemInfo.supports32bitsIndexBuffer.ToString()); + DrawItem("Supports Hardware Quad Topology", SystemInfo.supportsHardwareQuadTopology.ToString()); +#endif +#if UNITY_2018_2_OR_NEWER + DrawItem("Supports Mip Streaming", SystemInfo.supportsMipStreaming.ToString()); + DrawItem("Supports Multi-sample Auto Resolve", SystemInfo.supportsMultisampleAutoResolve.ToString()); +#endif +#if UNITY_2018_3_OR_NEWER + DrawItem("Supports Separated Render Targets Blend", SystemInfo.supportsSeparatedRenderTargetsBlend.ToString()); +#endif +#if UNITY_2019_1_OR_NEWER + DrawItem("Supports Set Constant Buffer", SystemInfo.supportsSetConstantBuffer.ToString()); +#endif +#if UNITY_2019_3_OR_NEWER + DrawItem("Supports Geometry Shaders", SystemInfo.supportsGeometryShaders.ToString()); + DrawItem("Supports Ray Tracing", SystemInfo.supportsRayTracing.ToString()); + DrawItem("Supports Tessellation Shaders", SystemInfo.supportsTessellationShaders.ToString()); +#endif +#if UNITY_2020_1_OR_NEWER + DrawItem("Supports Compressed 3D Textures", SystemInfo.supportsCompressed3DTextures.ToString()); + DrawItem("Supports Conservative Raster", SystemInfo.supportsConservativeRaster.ToString()); + DrawItem("Supports GPU Recorder", SystemInfo.supportsGpuRecorder.ToString()); +#endif +#if UNITY_2020_2_OR_NEWER + DrawItem("Supports Multi-sampled 2D Array Textures", SystemInfo.supportsMultisampled2DArrayTextures.ToString()); + DrawItem("Supports Multiview", SystemInfo.supportsMultiview.ToString()); + DrawItem("Supports Render Target Array Index From Vertex Shader", SystemInfo.supportsRenderTargetArrayIndexFromVertexShader.ToString()); +#endif + } + GUILayout.EndVertical(); + } + + private string GetShaderLevelString(int shaderLevel) + { + return Utility.Text.Format("Shader Model {0}.{1}", shaderLevel / 10, shaderLevel % 10); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.GraphicsInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.GraphicsInformationWindow.cs.meta new file mode 100644 index 0000000..ffd1618 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.GraphicsInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1342573add002c41b3bb1a8abb8ef3a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputAccelerationInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputAccelerationInformationWindow.cs new file mode 100644 index 0000000..1bd087f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputAccelerationInformationWindow.cs @@ -0,0 +1,46 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class InputAccelerationInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Input Acceleration Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Acceleration", Input.acceleration.ToString()); + DrawItem("Acceleration Event Count", Input.accelerationEventCount.ToString()); + DrawItem("Acceleration Events", GetAccelerationEventsString(Input.accelerationEvents)); + } + GUILayout.EndVertical(); + } + + private string GetAccelerationEventString(AccelerationEvent accelerationEvent) + { + return Utility.Text.Format("{0}, {1}", accelerationEvent.acceleration, accelerationEvent.deltaTime); + } + + private string GetAccelerationEventsString(AccelerationEvent[] accelerationEvents) + { + string[] accelerationEventStrings = new string[accelerationEvents.Length]; + for (int i = 0; i < accelerationEvents.Length; i++) + { + accelerationEventStrings[i] = GetAccelerationEventString(accelerationEvents[i]); + } + + return string.Join("; ", accelerationEventStrings); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputAccelerationInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputAccelerationInformationWindow.cs.meta new file mode 100644 index 0000000..e74c151 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputAccelerationInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 99bd178c0d097a24d9e04fe1522bca60 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputCompassInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputCompassInformationWindow.cs new file mode 100644 index 0000000..9b3d4de --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputCompassInformationWindow.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class InputCompassInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Input Compass Information"); + GUILayout.BeginVertical("box"); + { + GUILayout.BeginHorizontal(); + { + if (GUILayout.Button("Enable", GUILayout.Height(30f))) + { + Input.compass.enabled = true; + } + if (GUILayout.Button("Disable", GUILayout.Height(30f))) + { + Input.compass.enabled = false; + } + } + GUILayout.EndHorizontal(); + + DrawItem("Enabled", Input.compass.enabled.ToString()); + if (Input.compass.enabled) + { + DrawItem("Heading Accuracy", Input.compass.headingAccuracy.ToString()); + DrawItem("Magnetic Heading", Input.compass.magneticHeading.ToString()); + DrawItem("Raw Vector", Input.compass.rawVector.ToString()); + DrawItem("Timestamp", Input.compass.timestamp.ToString()); + DrawItem("True Heading", Input.compass.trueHeading.ToString()); + } + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputCompassInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputCompassInformationWindow.cs.meta new file mode 100644 index 0000000..81d4090 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputCompassInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a8e33bb9948f7f54d988d80a6ae6a24a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputGyroscopeInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputGyroscopeInformationWindow.cs new file mode 100644 index 0000000..4c0de69 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputGyroscopeInformationWindow.cs @@ -0,0 +1,49 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class InputGyroscopeInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Input Gyroscope Information"); + GUILayout.BeginVertical("box"); + { + GUILayout.BeginHorizontal(); + { + if (GUILayout.Button("Enable", GUILayout.Height(30f))) + { + Input.gyro.enabled = true; + } + if (GUILayout.Button("Disable", GUILayout.Height(30f))) + { + Input.gyro.enabled = false; + } + } + GUILayout.EndHorizontal(); + + DrawItem("Enabled", Input.gyro.enabled.ToString()); + if (Input.gyro.enabled) + { + DrawItem("Update Interval", Input.gyro.updateInterval.ToString()); + DrawItem("Attitude", Input.gyro.attitude.eulerAngles.ToString()); + DrawItem("Gravity", Input.gyro.gravity.ToString()); + DrawItem("Rotation Rate", Input.gyro.rotationRate.ToString()); + DrawItem("Rotation Rate Unbiased", Input.gyro.rotationRateUnbiased.ToString()); + DrawItem("User Acceleration", Input.gyro.userAcceleration.ToString()); + } + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputGyroscopeInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputGyroscopeInformationWindow.cs.meta new file mode 100644 index 0000000..613ca98 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputGyroscopeInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 709450f452a296b44b4aa939cf37f37c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputLocationInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputLocationInformationWindow.cs new file mode 100644 index 0000000..a001784 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputLocationInformationWindow.cs @@ -0,0 +1,50 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class InputLocationInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Input Location Information"); + GUILayout.BeginVertical("box"); + { + GUILayout.BeginHorizontal(); + { + if (GUILayout.Button("Enable", GUILayout.Height(30f))) + { + Input.location.Start(); + } + if (GUILayout.Button("Disable", GUILayout.Height(30f))) + { + Input.location.Stop(); + } + } + GUILayout.EndHorizontal(); + + DrawItem("Is Enabled By User", Input.location.isEnabledByUser.ToString()); + DrawItem("Status", Input.location.status.ToString()); + if (Input.location.status == LocationServiceStatus.Running) + { + DrawItem("Horizontal Accuracy", Input.location.lastData.horizontalAccuracy.ToString()); + DrawItem("Vertical Accuracy", Input.location.lastData.verticalAccuracy.ToString()); + DrawItem("Longitude", Input.location.lastData.longitude.ToString()); + DrawItem("Latitude", Input.location.lastData.latitude.ToString()); + DrawItem("Altitude", Input.location.lastData.altitude.ToString()); + DrawItem("Timestamp", Input.location.lastData.timestamp.ToString()); + } + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputLocationInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputLocationInformationWindow.cs.meta new file mode 100644 index 0000000..85e0c9f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputLocationInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 74c5698b7ee786442b28b64003f564fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputSummaryInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputSummaryInformationWindow.cs new file mode 100644 index 0000000..4ab1e5f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputSummaryInformationWindow.cs @@ -0,0 +1,39 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class InputSummaryInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Input Summary Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Back Button Leaves App", Input.backButtonLeavesApp.ToString()); + DrawItem("Device Orientation", Input.deviceOrientation.ToString()); + DrawItem("Mouse Present", Input.mousePresent.ToString()); + DrawItem("Mouse Position", Input.mousePosition.ToString()); + DrawItem("Mouse Scroll Delta", Input.mouseScrollDelta.ToString()); + DrawItem("Any Key", Input.anyKey.ToString()); + DrawItem("Any Key Down", Input.anyKeyDown.ToString()); + DrawItem("Input String", Input.inputString); + DrawItem("IME Is Selected", Input.imeIsSelected.ToString()); + DrawItem("IME Composition Mode", Input.imeCompositionMode.ToString()); + DrawItem("Compensate Sensors", Input.compensateSensors.ToString()); + DrawItem("Composition Cursor Position", Input.compositionCursorPos.ToString()); + DrawItem("Composition String", Input.compositionString); + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputSummaryInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputSummaryInformationWindow.cs.meta new file mode 100644 index 0000000..10a2fc3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputSummaryInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a2756ce9647dc6a49a66c75437edef8b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputTouchInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputTouchInformationWindow.cs new file mode 100644 index 0000000..8f1449c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputTouchInformationWindow.cs @@ -0,0 +1,50 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class InputTouchInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Input Touch Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Touch Supported", Input.touchSupported.ToString()); + DrawItem("Touch Pressure Supported", Input.touchPressureSupported.ToString()); + DrawItem("Stylus Touch Supported", Input.stylusTouchSupported.ToString()); + DrawItem("Simulate Mouse With Touches", Input.simulateMouseWithTouches.ToString()); + DrawItem("Multi Touch Enabled", Input.multiTouchEnabled.ToString()); + DrawItem("Touch Count", Input.touchCount.ToString()); + DrawItem("Touches", GetTouchesString(Input.touches)); + } + GUILayout.EndVertical(); + } + + private string GetTouchString(Touch touch) + { + return Utility.Text.Format("{0}, {1}, {2}, {3}, {4}", touch.position, touch.deltaPosition, touch.rawPosition, touch.pressure, touch.phase); + } + + private string GetTouchesString(Touch[] touches) + { + string[] touchStrings = new string[touches.Length]; + for (int i = 0; i < touches.Length; i++) + { + touchStrings[i] = GetTouchString(touches[i]); + } + + return string.Join("; ", touchStrings); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputTouchInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputTouchInformationWindow.cs.meta new file mode 100644 index 0000000..413d7ac --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.InputTouchInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6a76aa41d893e994f9630028d5e3001d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.LogNode.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.LogNode.cs new file mode 100644 index 0000000..b0e8d44 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.LogNode.cs @@ -0,0 +1,125 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + /// + /// 日志记录结点。 + /// + public sealed class LogNode : IReference + { + private DateTime m_LogTime; + private int m_LogFrameCount; + private LogType m_LogType; + private string m_LogMessage; + private string m_StackTrack; + + /// + /// 初始化日志记录结点的新实例。 + /// + public LogNode() + { + m_LogTime = default(DateTime); + m_LogFrameCount = 0; + m_LogType = LogType.Error; + m_LogMessage = null; + m_StackTrack = null; + } + + /// + /// 获取日志时间。 + /// + public DateTime LogTime + { + get + { + return m_LogTime; + } + } + + /// + /// 获取日志帧计数。 + /// + public int LogFrameCount + { + get + { + return m_LogFrameCount; + } + } + + /// + /// 获取日志类型。 + /// + public LogType LogType + { + get + { + return m_LogType; + } + } + + /// + /// 获取日志内容。 + /// + public string LogMessage + { + get + { + return m_LogMessage; + } + } + + /// + /// 获取日志堆栈信息。 + /// + public string StackTrack + { + get + { + return m_StackTrack; + } + } + + /// + /// 创建日志记录结点。 + /// + /// 日志类型。 + /// 日志内容。 + /// 日志堆栈信息。 + /// 创建的日志记录结点。 + public static LogNode Create(LogType logType, string logMessage, string stackTrack) + { + LogNode logNode = ReferencePool.Acquire(); + logNode.m_LogTime = DateTime.UtcNow; + logNode.m_LogFrameCount = Time.frameCount; + logNode.m_LogType = logType; + logNode.m_LogMessage = logMessage; + logNode.m_StackTrack = stackTrack; + return logNode; + } + + /// + /// 清理日志记录结点。 + /// + public void Clear() + { + m_LogTime = default(DateTime); + m_LogFrameCount = 0; + m_LogType = LogType.Error; + m_LogMessage = null; + m_StackTrack = null; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.LogNode.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.LogNode.cs.meta new file mode 100644 index 0000000..a9cd9bb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.LogNode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 168b4dfdd72224e4bbc5fb606eec23dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.NetworkInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.NetworkInformationWindow.cs new file mode 100644 index 0000000..565a63e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.NetworkInformationWindow.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Network; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class NetworkInformationWindow : ScrollableDebuggerWindowBase + { + private NetworkComponent m_NetworkComponent = null; + + public override void Initialize(params object[] args) + { + m_NetworkComponent = GameEntry.GetComponent(); + if (m_NetworkComponent == null) + { + Log.Fatal("Network component is invalid."); + return; + } + } + + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Network Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Network Channel Count", m_NetworkComponent.NetworkChannelCount.ToString()); + } + GUILayout.EndVertical(); + INetworkChannel[] networkChannels = m_NetworkComponent.GetAllNetworkChannels(); + for (int i = 0; i < networkChannels.Length; i++) + { + DrawNetworkChannel(networkChannels[i]); + } + } + + private void DrawNetworkChannel(INetworkChannel networkChannel) + { + GUILayout.Label(Utility.Text.Format("Network Channel: {0} ({1})", networkChannel.Name, networkChannel.Connected ? "Connected" : "Disconnected")); + GUILayout.BeginVertical("box"); + { + DrawItem("Service Type", networkChannel.ServiceType.ToString()); + DrawItem("Address Family", networkChannel.AddressFamily.ToString()); + DrawItem("Local Address", networkChannel.Connected ? networkChannel.Socket.LocalEndPoint.ToString() : "Unavailable"); + DrawItem("Remote Address", networkChannel.Connected ? networkChannel.Socket.RemoteEndPoint.ToString() : "Unavailable"); + DrawItem("Send Packet", Utility.Text.Format("{0} / {1}", networkChannel.SendPacketCount, networkChannel.SentPacketCount)); + DrawItem("Receive Packet", Utility.Text.Format("{0} / {1}", networkChannel.ReceivePacketCount, networkChannel.ReceivedPacketCount)); + DrawItem("Miss Heart Beat Count", networkChannel.MissHeartBeatCount.ToString()); + DrawItem("Heart Beat", Utility.Text.Format("{0:F2} / {1:F2}", networkChannel.HeartBeatElapseSeconds, networkChannel.HeartBeatInterval)); + if (networkChannel.Connected) + { + if (GUILayout.Button("Disconnect", GUILayout.Height(30f))) + { + networkChannel.Close(); + } + } + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.NetworkInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.NetworkInformationWindow.cs.meta new file mode 100644 index 0000000..c62b961 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.NetworkInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 51d087cb976f4944487629d900a5c057 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ObjectPoolInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ObjectPoolInformationWindow.cs new file mode 100644 index 0000000..4af307e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ObjectPoolInformationWindow.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.ObjectPool; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class ObjectPoolInformationWindow : ScrollableDebuggerWindowBase + { + private ObjectPoolComponent m_ObjectPoolComponent = null; + + public override void Initialize(params object[] args) + { + m_ObjectPoolComponent = GameEntry.GetComponent(); + if (m_ObjectPoolComponent == null) + { + Log.Fatal("Object pool component is invalid."); + return; + } + } + + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Object Pool Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Object Pool Count", m_ObjectPoolComponent.Count.ToString()); + } + GUILayout.EndVertical(); + ObjectPoolBase[] objectPools = m_ObjectPoolComponent.GetAllObjectPools(true); + for (int i = 0; i < objectPools.Length; i++) + { + DrawObjectPool(objectPools[i]); + } + } + + private void DrawObjectPool(ObjectPoolBase objectPool) + { + GUILayout.Label(Utility.Text.Format("Object Pool: {0}", objectPool.FullName)); + GUILayout.BeginVertical("box"); + { + DrawItem("Name", objectPool.Name); + DrawItem("Type", objectPool.ObjectType.FullName); + DrawItem("Auto Release Interval", objectPool.AutoReleaseInterval.ToString()); + DrawItem("Capacity", objectPool.Capacity.ToString()); + DrawItem("Used Count", objectPool.Count.ToString()); + DrawItem("Can Release Count", objectPool.CanReleaseCount.ToString()); + DrawItem("Expire Time", objectPool.ExpireTime.ToString()); + DrawItem("Priority", objectPool.Priority.ToString()); + ObjectInfo[] objectInfos = objectPool.GetAllObjectInfos(); + GUILayout.BeginHorizontal(); + { + GUILayout.Label("Name"); + GUILayout.Label("Locked", GUILayout.Width(60f)); + GUILayout.Label(objectPool.AllowMultiSpawn ? "Count" : "In Use", GUILayout.Width(60f)); + GUILayout.Label("Flag", GUILayout.Width(60f)); + GUILayout.Label("Priority", GUILayout.Width(60f)); + GUILayout.Label("Last Use Time", GUILayout.Width(120f)); + } + GUILayout.EndHorizontal(); + + if (objectInfos.Length > 0) + { + for (int i = 0; i < objectInfos.Length; i++) + { + GUILayout.BeginHorizontal(); + { + GUILayout.Label(string.IsNullOrEmpty(objectInfos[i].Name) ? "" : objectInfos[i].Name); + GUILayout.Label(objectInfos[i].Locked.ToString(), GUILayout.Width(60f)); + GUILayout.Label(objectPool.AllowMultiSpawn ? objectInfos[i].SpawnCount.ToString() : objectInfos[i].IsInUse.ToString(), GUILayout.Width(60f)); + GUILayout.Label(objectInfos[i].CustomCanReleaseFlag.ToString(), GUILayout.Width(60f)); + GUILayout.Label(objectInfos[i].Priority.ToString(), GUILayout.Width(60f)); + GUILayout.Label(objectInfos[i].LastUseTime.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"), GUILayout.Width(120f)); + } + GUILayout.EndHorizontal(); + } + } + else + { + GUILayout.Label("Object Pool is Empty ..."); + } + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ObjectPoolInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ObjectPoolInformationWindow.cs.meta new file mode 100644 index 0000000..03ba5f0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ObjectPoolInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5898a6ad35652924590c863ef4bc6341 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.OperationsWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.OperationsWindow.cs new file mode 100644 index 0000000..1adb7bb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.OperationsWindow.cs @@ -0,0 +1,66 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class OperationsWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Operations"); + GUILayout.BeginVertical("box"); + { + ObjectPoolComponent objectPoolComponent = GameEntry.GetComponent(); + if (objectPoolComponent != null) + { + if (GUILayout.Button("Object Pool Release", GUILayout.Height(30f))) + { + objectPoolComponent.Release(); + } + + if (GUILayout.Button("Object Pool Release All Unused", GUILayout.Height(30f))) + { + objectPoolComponent.ReleaseAllUnused(); + } + } + + ResourceComponent resourceCompoent = GameEntry.GetComponent(); + if (resourceCompoent != null) + { + if (GUILayout.Button("Unload Unused Assets", GUILayout.Height(30f))) + { + resourceCompoent.ForceUnloadUnusedAssets(false); + } + + if (GUILayout.Button("Unload Unused Assets and Garbage Collect", GUILayout.Height(30f))) + { + resourceCompoent.ForceUnloadUnusedAssets(true); + } + } + + if (GUILayout.Button("Shutdown Game Framework (None)", GUILayout.Height(30f))) + { + GameEntry.Shutdown(ShutdownType.None); + } + if (GUILayout.Button("Shutdown Game Framework (Restart)", GUILayout.Height(30f))) + { + GameEntry.Shutdown(ShutdownType.Restart); + } + if (GUILayout.Button("Shutdown Game Framework (Quit)", GUILayout.Height(30f))) + { + GameEntry.Shutdown(ShutdownType.Quit); + } + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.OperationsWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.OperationsWindow.cs.meta new file mode 100644 index 0000000..ac4e910 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.OperationsWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a695dd87b92d7374fbe3790f5a25e9d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.PathInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.PathInformationWindow.cs new file mode 100644 index 0000000..8bb0258 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.PathInformationWindow.cs @@ -0,0 +1,36 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class PathInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Path Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Current Directory", Utility.Path.GetRegularPath(Environment.CurrentDirectory)); + DrawItem("Data Path", Utility.Path.GetRegularPath(Application.dataPath)); + DrawItem("Persistent Data Path", Utility.Path.GetRegularPath(Application.persistentDataPath)); + DrawItem("Streaming Assets Path", Utility.Path.GetRegularPath(Application.streamingAssetsPath)); + DrawItem("Temporary Cache Path", Utility.Path.GetRegularPath(Application.temporaryCachePath)); +#if UNITY_2018_3_OR_NEWER + DrawItem("Console Log Path", Utility.Path.GetRegularPath(Application.consoleLogPath)); +#endif + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.PathInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.PathInformationWindow.cs.meta new file mode 100644 index 0000000..1597ff4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.PathInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e86b5be349fea7b46bf4c9cff62cf940 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ProfilerInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ProfilerInformationWindow.cs new file mode 100644 index 0000000..b14d3b7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ProfilerInformationWindow.cs @@ -0,0 +1,67 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; +#if UNITY_5_5_OR_NEWER +using UnityEngine.Profiling; +#endif + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class ProfilerInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Profiler Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Supported", Profiler.supported.ToString()); + DrawItem("Enabled", Profiler.enabled.ToString()); + DrawItem("Enable Binary Log", Profiler.enableBinaryLog ? Utility.Text.Format("True, {0}", Profiler.logFile) : "False"); +#if UNITY_2019_3_OR_NEWER + DrawItem("Enable Allocation Callstacks", Profiler.enableAllocationCallstacks.ToString()); +#endif +#if UNITY_2018_3_OR_NEWER + DrawItem("Area Count", Profiler.areaCount.ToString()); +#endif +#if UNITY_5_3 || UNITY_5_4 + DrawItem("Max Samples Number Per Frame", Profiler.maxNumberOfSamplesPerFrame.ToString()); +#endif +#if UNITY_2018_3_OR_NEWER + DrawItem("Max Used Memory", GetByteLengthString(Profiler.maxUsedMemory)); +#endif +#if UNITY_5_6_OR_NEWER + DrawItem("Mono Used Size", GetByteLengthString(Profiler.GetMonoUsedSizeLong())); + DrawItem("Mono Heap Size", GetByteLengthString(Profiler.GetMonoHeapSizeLong())); + DrawItem("Used Heap Size", GetByteLengthString(Profiler.usedHeapSizeLong)); + DrawItem("Total Allocated Memory", GetByteLengthString(Profiler.GetTotalAllocatedMemoryLong())); + DrawItem("Total Reserved Memory", GetByteLengthString(Profiler.GetTotalReservedMemoryLong())); + DrawItem("Total Unused Reserved Memory", GetByteLengthString(Profiler.GetTotalUnusedReservedMemoryLong())); +#else + DrawItem("Mono Used Size", GetByteLengthString(Profiler.GetMonoUsedSize())); + DrawItem("Mono Heap Size", GetByteLengthString(Profiler.GetMonoHeapSize())); + DrawItem("Used Heap Size", GetByteLengthString(Profiler.usedHeapSize)); + DrawItem("Total Allocated Memory", GetByteLengthString(Profiler.GetTotalAllocatedMemory())); + DrawItem("Total Reserved Memory", GetByteLengthString(Profiler.GetTotalReservedMemory())); + DrawItem("Total Unused Reserved Memory", GetByteLengthString(Profiler.GetTotalUnusedReservedMemory())); +#endif +#if UNITY_2018_1_OR_NEWER + DrawItem("Allocated Memory For Graphics Driver", GetByteLengthString(Profiler.GetAllocatedMemoryForGraphicsDriver())); +#endif +#if UNITY_5_5_OR_NEWER + DrawItem("Temp Allocator Size", GetByteLengthString(Profiler.GetTempAllocatorSize())); +#endif + DrawItem("Marshal Cached HGlobal Size", GetByteLengthString(Utility.Marshal.CachedHGlobalSize)); + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ProfilerInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ProfilerInformationWindow.cs.meta new file mode 100644 index 0000000..0e72fe2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ProfilerInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 73fd64cd790a9564d9e49d13ed0742c7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.QualityInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.QualityInformationWindow.cs new file mode 100644 index 0000000..e672251 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.QualityInformationWindow.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class QualityInformationWindow : ScrollableDebuggerWindowBase + { + private bool m_ApplyExpensiveChanges = false; + + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Quality Level"); + GUILayout.BeginVertical("box"); + { + int currentQualityLevel = QualitySettings.GetQualityLevel(); + + DrawItem("Current Quality Level", QualitySettings.names[currentQualityLevel]); + m_ApplyExpensiveChanges = GUILayout.Toggle(m_ApplyExpensiveChanges, "Apply expensive changes on quality level change."); + + int newQualityLevel = GUILayout.SelectionGrid(currentQualityLevel, QualitySettings.names, 3, "toggle"); + if (newQualityLevel != currentQualityLevel) + { + QualitySettings.SetQualityLevel(newQualityLevel, m_ApplyExpensiveChanges); + } + } + GUILayout.EndVertical(); + + GUILayout.Label("Rendering Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Active Color Space", QualitySettings.activeColorSpace.ToString()); + DrawItem("Desired Color Space", QualitySettings.desiredColorSpace.ToString()); + DrawItem("Max Queued Frames", QualitySettings.maxQueuedFrames.ToString()); + DrawItem("Pixel Light Count", QualitySettings.pixelLightCount.ToString()); + DrawItem("Master Texture Limit", QualitySettings.globalTextureMipmapLimit.ToString()); + DrawItem("Anisotropic Filtering", QualitySettings.anisotropicFiltering.ToString()); + DrawItem("Anti Aliasing", QualitySettings.antiAliasing.ToString()); +#if UNITY_5_5_OR_NEWER + DrawItem("Soft Particles", QualitySettings.softParticles.ToString()); +#endif + DrawItem("Soft Vegetation", QualitySettings.softVegetation.ToString()); + DrawItem("Realtime Reflection Probes", QualitySettings.realtimeReflectionProbes.ToString()); + DrawItem("Billboards Face Camera Position", QualitySettings.billboardsFaceCameraPosition.ToString()); +#if UNITY_2017_1_OR_NEWER + DrawItem("Resolution Scaling Fixed DPI Factor", QualitySettings.resolutionScalingFixedDPIFactor.ToString()); +#endif +#if UNITY_2018_2_OR_NEWER + DrawItem("Texture Streaming Enabled", QualitySettings.streamingMipmapsActive.ToString()); + DrawItem("Texture Streaming Add All Cameras", QualitySettings.streamingMipmapsAddAllCameras.ToString()); + DrawItem("Texture Streaming Memory Budget", QualitySettings.streamingMipmapsMemoryBudget.ToString()); + DrawItem("Texture Streaming Renderers Per Frame", QualitySettings.streamingMipmapsRenderersPerFrame.ToString()); + DrawItem("Texture Streaming Max Level Reduction", QualitySettings.streamingMipmapsMaxLevelReduction.ToString()); + DrawItem("Texture Streaming Max File IO Requests", QualitySettings.streamingMipmapsMaxFileIORequests.ToString()); +#endif + } + GUILayout.EndVertical(); + + GUILayout.Label("Shadows Information"); + GUILayout.BeginVertical("box"); + { +#if UNITY_2017_1_OR_NEWER + DrawItem("Shadowmask Mode", QualitySettings.shadowmaskMode.ToString()); +#endif +#if UNITY_5_5_OR_NEWER + DrawItem("Shadow Quality", QualitySettings.shadows.ToString()); +#endif +#if UNITY_5_4_OR_NEWER + DrawItem("Shadow Resolution", QualitySettings.shadowResolution.ToString()); +#endif + DrawItem("Shadow Projection", QualitySettings.shadowProjection.ToString()); + DrawItem("Shadow Distance", QualitySettings.shadowDistance.ToString()); + DrawItem("Shadow Near Plane Offset", QualitySettings.shadowNearPlaneOffset.ToString()); + DrawItem("Shadow Cascades", QualitySettings.shadowCascades.ToString()); + DrawItem("Shadow Cascade 2 Split", QualitySettings.shadowCascade2Split.ToString()); + DrawItem("Shadow Cascade 4 Split", QualitySettings.shadowCascade4Split.ToString()); + } + GUILayout.EndVertical(); + + GUILayout.Label("Other Information"); + GUILayout.BeginVertical("box"); + { +#if UNITY_2019_1_OR_NEWER + DrawItem("Skin Weights", QualitySettings.skinWeights.ToString()); +#else + DrawItem("Blend Weights", QualitySettings.blendWeights.ToString()); +#endif + DrawItem("VSync Count", QualitySettings.vSyncCount.ToString()); + DrawItem("LOD Bias", QualitySettings.lodBias.ToString()); + DrawItem("Maximum LOD Level", QualitySettings.maximumLODLevel.ToString()); + DrawItem("Particle Raycast Budget", QualitySettings.particleRaycastBudget.ToString()); + DrawItem("Async Upload Time Slice", Utility.Text.Format("{0} ms", QualitySettings.asyncUploadTimeSlice)); + DrawItem("Async Upload Buffer Size", Utility.Text.Format("{0} MB", QualitySettings.asyncUploadBufferSize)); +#if UNITY_2018_3_OR_NEWER + DrawItem("Async Upload Persistent Buffer", QualitySettings.asyncUploadPersistentBuffer.ToString()); +#endif + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.QualityInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.QualityInformationWindow.cs.meta new file mode 100644 index 0000000..64b22d8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.QualityInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc21c02fdf159d840a5254513a44c065 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ReferencePoolInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ReferencePoolInformationWindow.cs new file mode 100644 index 0000000..be83f29 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ReferencePoolInformationWindow.cs @@ -0,0 +1,114 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class ReferencePoolInformationWindow : ScrollableDebuggerWindowBase + { + private readonly Dictionary> m_ReferencePoolInfos = new Dictionary>(StringComparer.Ordinal); + private readonly Comparison m_NormalClassNameComparer = NormalClassNameComparer; + private readonly Comparison m_FullClassNameComparer = FullClassNameComparer; + private bool m_ShowFullClassName = false; + + public override void Initialize(params object[] args) + { + } + + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Reference Pool Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Enable Strict Check", ReferencePool.EnableStrictCheck.ToString()); + DrawItem("Reference Pool Count", ReferencePool.Count.ToString()); + } + GUILayout.EndVertical(); + + m_ShowFullClassName = GUILayout.Toggle(m_ShowFullClassName, "Show Full Class Name"); + m_ReferencePoolInfos.Clear(); + ReferencePoolInfo[] referencePoolInfos = ReferencePool.GetAllReferencePoolInfos(); + foreach (ReferencePoolInfo referencePoolInfo in referencePoolInfos) + { + string assemblyName = referencePoolInfo.Type.Assembly.GetName().Name; + List results = null; + if (!m_ReferencePoolInfos.TryGetValue(assemblyName, out results)) + { + results = new List(); + m_ReferencePoolInfos.Add(assemblyName, results); + } + + results.Add(referencePoolInfo); + } + + foreach (KeyValuePair> assemblyReferencePoolInfo in m_ReferencePoolInfos) + { + GUILayout.Label(Utility.Text.Format("Assembly: {0}", assemblyReferencePoolInfo.Key)); + GUILayout.BeginVertical("box"); + { + GUILayout.BeginHorizontal(); + { + GUILayout.Label(m_ShowFullClassName ? "Full Class Name" : "Class Name"); + GUILayout.Label("Unused", GUILayout.Width(60f)); + GUILayout.Label("Using", GUILayout.Width(60f)); + GUILayout.Label("Acquire", GUILayout.Width(60f)); + GUILayout.Label("Release", GUILayout.Width(60f)); + GUILayout.Label("Add", GUILayout.Width(60f)); + GUILayout.Label("Remove", GUILayout.Width(60f)); + } + GUILayout.EndHorizontal(); + + if (assemblyReferencePoolInfo.Value.Count > 0) + { + assemblyReferencePoolInfo.Value.Sort(m_ShowFullClassName ? m_FullClassNameComparer : m_NormalClassNameComparer); + foreach (ReferencePoolInfo referencePoolInfo in assemblyReferencePoolInfo.Value) + { + DrawReferencePoolInfo(referencePoolInfo); + } + } + else + { + GUILayout.Label("Reference Pool is Empty ..."); + } + } + GUILayout.EndVertical(); + } + } + + private void DrawReferencePoolInfo(ReferencePoolInfo referencePoolInfo) + { + GUILayout.BeginHorizontal(); + { + GUILayout.Label(m_ShowFullClassName ? referencePoolInfo.Type.FullName : referencePoolInfo.Type.Name); + GUILayout.Label(referencePoolInfo.UnusedReferenceCount.ToString(), GUILayout.Width(60f)); + GUILayout.Label(referencePoolInfo.UsingReferenceCount.ToString(), GUILayout.Width(60f)); + GUILayout.Label(referencePoolInfo.AcquireReferenceCount.ToString(), GUILayout.Width(60f)); + GUILayout.Label(referencePoolInfo.ReleaseReferenceCount.ToString(), GUILayout.Width(60f)); + GUILayout.Label(referencePoolInfo.AddReferenceCount.ToString(), GUILayout.Width(60f)); + GUILayout.Label(referencePoolInfo.RemoveReferenceCount.ToString(), GUILayout.Width(60f)); + } + GUILayout.EndHorizontal(); + } + + private static int NormalClassNameComparer(ReferencePoolInfo a, ReferencePoolInfo b) + { + return a.Type.Name.CompareTo(b.Type.Name); + } + + private static int FullClassNameComparer(ReferencePoolInfo a, ReferencePoolInfo b) + { + return a.Type.FullName.CompareTo(b.Type.FullName); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ReferencePoolInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ReferencePoolInformationWindow.cs.meta new file mode 100644 index 0000000..9f4f2a1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ReferencePoolInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 33068d0a27ec5684e994545a7995a17c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemoryInformationWindow.Sample.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemoryInformationWindow.Sample.cs new file mode 100644 index 0000000..12eead5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemoryInformationWindow.Sample.cs @@ -0,0 +1,67 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed partial class RuntimeMemoryInformationWindow : ScrollableDebuggerWindowBase where T : UnityEngine.Object + { + private sealed class Sample + { + private readonly string m_Name; + private readonly string m_Type; + private readonly long m_Size; + private bool m_Highlight; + + public Sample(string name, string type, long size) + { + m_Name = name; + m_Type = type; + m_Size = size; + m_Highlight = false; + } + + public string Name + { + get + { + return m_Name; + } + } + + public string Type + { + get + { + return m_Type; + } + } + + public long Size + { + get + { + return m_Size; + } + } + + public bool Highlight + { + get + { + return m_Highlight; + } + set + { + m_Highlight = value; + } + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemoryInformationWindow.Sample.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemoryInformationWindow.Sample.cs.meta new file mode 100644 index 0000000..3bc4594 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemoryInformationWindow.Sample.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0da72213ab82f43458578c3ce477a57c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemoryInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemoryInformationWindow.cs new file mode 100644 index 0000000..7f85916 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemoryInformationWindow.cs @@ -0,0 +1,142 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Collections.Generic; +using UnityEngine; +#if UNITY_5_5_OR_NEWER +using UnityEngine.Profiling; +#endif + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed partial class RuntimeMemoryInformationWindow : ScrollableDebuggerWindowBase where T : UnityEngine.Object + { + private const int ShowSampleCount = 300; + + private readonly List m_Samples = new List(); + private readonly Comparison m_SampleComparer = SampleComparer; + private DateTime m_SampleTime = DateTime.MinValue; + private long m_SampleSize = 0L; + private long m_DuplicateSampleSize = 0L; + private int m_DuplicateSimpleCount = 0; + + protected override void OnDrawScrollableWindow() + { + string typeName = typeof(T).Name; + GUILayout.Label(Utility.Text.Format("{0} Runtime Memory Information", typeName)); + GUILayout.BeginVertical("box"); + { + if (GUILayout.Button(Utility.Text.Format("Take Sample for {0}", typeName), GUILayout.Height(30f))) + { + TakeSample(); + } + + if (m_SampleTime <= DateTime.MinValue) + { + GUILayout.Label(Utility.Text.Format("Please take sample for {0} first.", typeName)); + } + else + { + if (m_DuplicateSimpleCount > 0) + { + GUILayout.Label(Utility.Text.Format("{0} {1}s ({2}) obtained at {3:yyyy-MM-dd HH:mm:ss}, while {4} {1}s ({5}) might be duplicated.", m_Samples.Count, typeName, GetByteLengthString(m_SampleSize), m_SampleTime.ToLocalTime(), m_DuplicateSimpleCount, GetByteLengthString(m_DuplicateSampleSize))); + } + else + { + GUILayout.Label(Utility.Text.Format("{0} {1}s ({2}) obtained at {3:yyyy-MM-dd HH:mm:ss}.", m_Samples.Count, typeName, GetByteLengthString(m_SampleSize), m_SampleTime.ToLocalTime())); + } + + if (m_Samples.Count > 0) + { + GUILayout.BeginHorizontal(); + { + GUILayout.Label(Utility.Text.Format("{0} Name", typeName)); + GUILayout.Label("Type", GUILayout.Width(240f)); + GUILayout.Label("Size", GUILayout.Width(80f)); + } + GUILayout.EndHorizontal(); + } + + int count = 0; + for (int i = 0; i < m_Samples.Count; i++) + { + GUILayout.BeginHorizontal(); + { + GUILayout.Label(m_Samples[i].Highlight ? Utility.Text.Format("{0}", m_Samples[i].Name) : m_Samples[i].Name); + GUILayout.Label(m_Samples[i].Highlight ? Utility.Text.Format("{0}", m_Samples[i].Type) : m_Samples[i].Type, GUILayout.Width(240f)); + GUILayout.Label(m_Samples[i].Highlight ? Utility.Text.Format("{0}", GetByteLengthString(m_Samples[i].Size)) : GetByteLengthString(m_Samples[i].Size), GUILayout.Width(80f)); + } + GUILayout.EndHorizontal(); + + count++; + if (count >= ShowSampleCount) + { + break; + } + } + } + } + GUILayout.EndVertical(); + } + + private void TakeSample() + { + m_SampleTime = DateTime.UtcNow; + m_SampleSize = 0L; + m_DuplicateSampleSize = 0L; + m_DuplicateSimpleCount = 0; + m_Samples.Clear(); + + T[] samples = Resources.FindObjectsOfTypeAll(); + for (int i = 0; i < samples.Length; i++) + { + long sampleSize = 0L; +#if UNITY_5_6_OR_NEWER + sampleSize = Profiler.GetRuntimeMemorySizeLong(samples[i]); +#else + sampleSize = Profiler.GetRuntimeMemorySize(samples[i]); +#endif + m_SampleSize += sampleSize; + m_Samples.Add(new Sample(samples[i].name, samples[i].GetType().Name, sampleSize)); + } + + m_Samples.Sort(m_SampleComparer); + + for (int i = 1; i < m_Samples.Count; i++) + { + if (m_Samples[i].Name == m_Samples[i - 1].Name && m_Samples[i].Type == m_Samples[i - 1].Type && m_Samples[i].Size == m_Samples[i - 1].Size) + { + m_Samples[i].Highlight = true; + m_DuplicateSampleSize += m_Samples[i].Size; + m_DuplicateSimpleCount++; + } + } + } + + private static int SampleComparer(Sample a, Sample b) + { + int result = b.Size.CompareTo(a.Size); + if (result != 0) + { + return result; + } + + result = a.Type.CompareTo(b.Type); + if (result != 0) + { + return result; + } + + return a.Name.CompareTo(b.Name); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemoryInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemoryInformationWindow.cs.meta new file mode 100644 index 0000000..a8bb068 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemoryInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 21007b3290d97754ea3ab4d9f46900e6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemorySummaryWindow.Record.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemorySummaryWindow.Record.cs new file mode 100644 index 0000000..737e22a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemorySummaryWindow.Record.cs @@ -0,0 +1,61 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed partial class RuntimeMemorySummaryWindow : ScrollableDebuggerWindowBase + { + private sealed class Record + { + private readonly string m_Name; + private int m_Count; + private long m_Size; + + public Record(string name) + { + m_Name = name; + m_Count = 0; + m_Size = 0L; + } + + public string Name + { + get + { + return m_Name; + } + } + + public int Count + { + get + { + return m_Count; + } + set + { + m_Count = value; + } + } + + public long Size + { + get + { + return m_Size; + } + set + { + m_Size = value; + } + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemorySummaryWindow.Record.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemorySummaryWindow.Record.cs.meta new file mode 100644 index 0000000..6fc6cfb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemorySummaryWindow.Record.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 468bbdd114a04de429a6bd97b202c891 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemorySummaryWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemorySummaryWindow.cs new file mode 100644 index 0000000..07b58a8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemorySummaryWindow.cs @@ -0,0 +1,130 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Collections.Generic; +using UnityEngine; +#if UNITY_5_5_OR_NEWER +using UnityEngine.Profiling; +#endif + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed partial class RuntimeMemorySummaryWindow : ScrollableDebuggerWindowBase + { + private readonly List m_Records = new List(); + private readonly Comparison m_RecordComparer = RecordComparer; + private DateTime m_SampleTime = DateTime.MinValue; + private int m_SampleCount = 0; + private long m_SampleSize = 0L; + + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Runtime Memory Summary"); + GUILayout.BeginVertical("box"); + { + if (GUILayout.Button("Take Sample", GUILayout.Height(30f))) + { + TakeSample(); + } + + if (m_SampleTime <= DateTime.MinValue) + { + GUILayout.Label("Please take sample first."); + } + else + { + GUILayout.Label(Utility.Text.Format("{0} Objects ({1}) obtained at {2:yyyy-MM-dd HH:mm:ss}.", m_SampleCount, GetByteLengthString(m_SampleSize), m_SampleTime.ToLocalTime())); + + GUILayout.BeginHorizontal(); + { + GUILayout.Label("Type"); + GUILayout.Label("Count", GUILayout.Width(120f)); + GUILayout.Label("Size", GUILayout.Width(120f)); + } + GUILayout.EndHorizontal(); + + for (int i = 0; i < m_Records.Count; i++) + { + GUILayout.BeginHorizontal(); + { + GUILayout.Label(m_Records[i].Name); + GUILayout.Label(m_Records[i].Count.ToString(), GUILayout.Width(120f)); + GUILayout.Label(GetByteLengthString(m_Records[i].Size), GUILayout.Width(120f)); + } + GUILayout.EndHorizontal(); + } + } + } + GUILayout.EndVertical(); + } + + private void TakeSample() + { + m_Records.Clear(); + m_SampleTime = DateTime.UtcNow; + m_SampleCount = 0; + m_SampleSize = 0L; + + UnityEngine.Object[] samples = Resources.FindObjectsOfTypeAll(); + for (int i = 0; i < samples.Length; i++) + { + long sampleSize = 0L; +#if UNITY_5_6_OR_NEWER + sampleSize = Profiler.GetRuntimeMemorySizeLong(samples[i]); +#else + sampleSize = Profiler.GetRuntimeMemorySize(samples[i]); +#endif + string name = samples[i].GetType().Name; + m_SampleCount++; + m_SampleSize += sampleSize; + + Record record = null; + foreach (Record r in m_Records) + { + if (r.Name == name) + { + record = r; + break; + } + } + + if (record == null) + { + record = new Record(name); + m_Records.Add(record); + } + + record.Count++; + record.Size += sampleSize; + } + + m_Records.Sort(m_RecordComparer); + } + + private static int RecordComparer(Record a, Record b) + { + int result = b.Size.CompareTo(a.Size); + if (result != 0) + { + return result; + } + + result = a.Count.CompareTo(b.Count); + if (result != 0) + { + return result; + } + + return a.Name.CompareTo(b.Name); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemorySummaryWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemorySummaryWindow.cs.meta new file mode 100644 index 0000000..df2dac1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.RuntimeMemorySummaryWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45a9f76b48e192d44b0de0eac60975b2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SceneInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SceneInformationWindow.cs new file mode 100644 index 0000000..7b0b143 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SceneInformationWindow.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class SceneInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Scene Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Scene Count", SceneManager.sceneCount.ToString()); + DrawItem("Scene Count In Build Settings", SceneManager.sceneCountInBuildSettings.ToString()); + + Scene activeScene = SceneManager.GetActiveScene(); +#if UNITY_2018_3_OR_NEWER + DrawItem("Active Scene Handle", activeScene.handle.ToString()); +#endif + DrawItem("Active Scene Name", activeScene.name); + DrawItem("Active Scene Path", activeScene.path); + DrawItem("Active Scene Build Index", activeScene.buildIndex.ToString()); + DrawItem("Active Scene Is Dirty", activeScene.isDirty.ToString()); + DrawItem("Active Scene Is Loaded", activeScene.isLoaded.ToString()); + DrawItem("Active Scene Is Valid", activeScene.IsValid().ToString()); + DrawItem("Active Scene Root Count", activeScene.rootCount.ToString()); +#if UNITY_2019_1_OR_NEWER + DrawItem("Active Scene Is Sub Scene", activeScene.isSubScene.ToString()); +#endif + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SceneInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SceneInformationWindow.cs.meta new file mode 100644 index 0000000..9a51a2d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SceneInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0c5471e8b14eef444a96f1e1cb4b6987 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ScreenInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ScreenInformationWindow.cs new file mode 100644 index 0000000..5f8b614 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ScreenInformationWindow.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class ScreenInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Screen Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Current Resolution", GetResolutionString(Screen.currentResolution)); + DrawItem("Screen Width", Utility.Text.Format("{0} px / {1:F2} in / {2:F2} cm", Screen.width, Utility.Converter.GetInchesFromPixels(Screen.width), Utility.Converter.GetCentimetersFromPixels(Screen.width))); + DrawItem("Screen Height", Utility.Text.Format("{0} px / {1:F2} in / {2:F2} cm", Screen.height, Utility.Converter.GetInchesFromPixels(Screen.height), Utility.Converter.GetCentimetersFromPixels(Screen.height))); + DrawItem("Screen DPI", Screen.dpi.ToString("F2")); + DrawItem("Screen Orientation", Screen.orientation.ToString()); + DrawItem("Is Full Screen", Screen.fullScreen.ToString()); +#if UNITY_2018_1_OR_NEWER + DrawItem("Full Screen Mode", Screen.fullScreenMode.ToString()); +#endif + DrawItem("Sleep Timeout", GetSleepTimeoutDescription(Screen.sleepTimeout)); +#if UNITY_2019_2_OR_NEWER + DrawItem("Brightness", Screen.brightness.ToString("F2")); +#endif + DrawItem("Cursor Visible", Cursor.visible.ToString()); + DrawItem("Cursor Lock State", Cursor.lockState.ToString()); + DrawItem("Auto Landscape Left", Screen.autorotateToLandscapeLeft.ToString()); + DrawItem("Auto Landscape Right", Screen.autorotateToLandscapeRight.ToString()); + DrawItem("Auto Portrait", Screen.autorotateToPortrait.ToString()); + DrawItem("Auto Portrait Upside Down", Screen.autorotateToPortraitUpsideDown.ToString()); +#if UNITY_2017_2_OR_NEWER && !UNITY_2017_2_0 + DrawItem("Safe Area", Screen.safeArea.ToString()); +#endif +#if UNITY_2019_2_OR_NEWER + DrawItem("Cutouts", GetCutoutsString(Screen.cutouts)); +#endif + DrawItem("Support Resolutions", GetResolutionsString(Screen.resolutions)); + } + GUILayout.EndVertical(); + } + + private string GetSleepTimeoutDescription(int sleepTimeout) + { + if (sleepTimeout == SleepTimeout.NeverSleep) + { + return "Never Sleep"; + } + + if (sleepTimeout == SleepTimeout.SystemSetting) + { + return "System Setting"; + } + + return sleepTimeout.ToString(); + } + + private string GetResolutionString(Resolution resolution) + { + return Utility.Text.Format("{0} x {1} @ {2}Hz", resolution.width, resolution.height, resolution.refreshRateRatio); + } + + private string GetCutoutsString(Rect[] cutouts) + { + string[] cutoutStrings = new string[cutouts.Length]; + for (int i = 0; i < cutouts.Length; i++) + { + cutoutStrings[i] = cutouts[i].ToString(); + } + + return string.Join("; ", cutoutStrings); + } + + private string GetResolutionsString(Resolution[] resolutions) + { + string[] resolutionStrings = new string[resolutions.Length]; + for (int i = 0; i < resolutions.Length; i++) + { + resolutionStrings[i] = GetResolutionString(resolutions[i]); + } + + return string.Join("; ", resolutionStrings); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ScreenInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ScreenInformationWindow.cs.meta new file mode 100644 index 0000000..d8bcd4e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ScreenInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc352756f31513048a46e56ad2900db7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ScrollableDebuggerWindowBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ScrollableDebuggerWindowBase.cs new file mode 100644 index 0000000..dc2e122 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ScrollableDebuggerWindowBase.cs @@ -0,0 +1,101 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Debugger; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private abstract class ScrollableDebuggerWindowBase : IDebuggerWindow + { + private const float TitleWidth = 240f; + private Vector2 m_ScrollPosition = Vector2.zero; + + public virtual void Initialize(params object[] args) + { + } + + public virtual void Shutdown() + { + } + + public virtual void OnEnter() + { + } + + public virtual void OnLeave() + { + } + + public virtual void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + } + + public void OnDraw() + { + m_ScrollPosition = GUILayout.BeginScrollView(m_ScrollPosition); + { + OnDrawScrollableWindow(); + } + GUILayout.EndScrollView(); + } + + protected abstract void OnDrawScrollableWindow(); + + protected static void DrawItem(string title, string content) + { + GUILayout.BeginHorizontal(); + { + GUILayout.Label(title, GUILayout.Width(TitleWidth)); + if (GUILayout.Button(content, "label")) + { + CopyToClipboard(content); + } + } + GUILayout.EndHorizontal(); + } + + protected static string GetByteLengthString(long byteLength) + { + if (byteLength < 1024L) // 2 ^ 10 + { + return Utility.Text.Format("{0} Bytes", byteLength); + } + + if (byteLength < 1048576L) // 2 ^ 20 + { + return Utility.Text.Format("{0:F2} KB", byteLength / 1024f); + } + + if (byteLength < 1073741824L) // 2 ^ 30 + { + return Utility.Text.Format("{0:F2} MB", byteLength / 1048576f); + } + + if (byteLength < 1099511627776L) // 2 ^ 40 + { + return Utility.Text.Format("{0:F2} GB", byteLength / 1073741824f); + } + + if (byteLength < 1125899906842624L) // 2 ^ 50 + { + return Utility.Text.Format("{0:F2} TB", byteLength / 1099511627776f); + } + + if (byteLength < 1152921504606846976L) // 2 ^ 60 + { + return Utility.Text.Format("{0:F2} PB", byteLength / 1125899906842624f); + } + + return Utility.Text.Format("{0:F2} EB", byteLength / 1152921504606846976f); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ScrollableDebuggerWindowBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ScrollableDebuggerWindowBase.cs.meta new file mode 100644 index 0000000..c00e15b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.ScrollableDebuggerWindowBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1af7b258c93df0341a163adfdd378f8a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SettingsWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SettingsWindow.cs new file mode 100644 index 0000000..0803054 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SettingsWindow.cs @@ -0,0 +1,219 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class SettingsWindow : ScrollableDebuggerWindowBase + { + private DebuggerComponent m_DebuggerComponent = null; + private SettingComponent m_SettingComponent = null; + private float m_LastIconX = 0f; + private float m_LastIconY = 0f; + private float m_LastWindowX = 0f; + private float m_LastWindowY = 0f; + private float m_LastWindowWidth = 0f; + private float m_LastWindowHeight = 0f; + private float m_LastWindowScale = 0f; + + public override void Initialize(params object[] args) + { + m_DebuggerComponent = GameEntry.GetComponent(); + if (m_DebuggerComponent == null) + { + Log.Fatal("Debugger component is invalid."); + return; + } + + m_SettingComponent = GameEntry.GetComponent(); + if (m_SettingComponent == null) + { + Log.Fatal("Setting component is invalid."); + return; + } + + m_LastIconX = m_SettingComponent.GetFloat("Debugger.Icon.X", DefaultIconRect.x); + m_LastIconY = m_SettingComponent.GetFloat("Debugger.Icon.Y", DefaultIconRect.y); + m_LastWindowX = m_SettingComponent.GetFloat("Debugger.Window.X", DefaultWindowRect.x); + m_LastWindowY = m_SettingComponent.GetFloat("Debugger.Window.Y", DefaultWindowRect.y); + m_LastWindowWidth = m_SettingComponent.GetFloat("Debugger.Window.Width", DefaultWindowRect.width); + m_LastWindowHeight = m_SettingComponent.GetFloat("Debugger.Window.Height", DefaultWindowRect.height); + m_DebuggerComponent.WindowScale = m_LastWindowScale = m_SettingComponent.GetFloat("Debugger.Window.Scale", DefaultWindowScale); + m_DebuggerComponent.IconRect = new Rect(m_LastIconX, m_LastIconY, DefaultIconRect.width, DefaultIconRect.height); + m_DebuggerComponent.WindowRect = new Rect(m_LastWindowX, m_LastWindowY, m_LastWindowWidth, m_LastWindowHeight); + } + + public override void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + if (m_LastIconX != m_DebuggerComponent.IconRect.x) + { + m_LastIconX = m_DebuggerComponent.IconRect.x; + m_SettingComponent.SetFloat("Debugger.Icon.X", m_DebuggerComponent.IconRect.x); + } + + if (m_LastIconY != m_DebuggerComponent.IconRect.y) + { + m_LastIconY = m_DebuggerComponent.IconRect.y; + m_SettingComponent.SetFloat("Debugger.Icon.Y", m_DebuggerComponent.IconRect.y); + } + + if (m_LastWindowX != m_DebuggerComponent.WindowRect.x) + { + m_LastWindowX = m_DebuggerComponent.WindowRect.x; + m_SettingComponent.SetFloat("Debugger.Window.X", m_DebuggerComponent.WindowRect.x); + } + + if (m_LastWindowY != m_DebuggerComponent.WindowRect.y) + { + m_LastWindowY = m_DebuggerComponent.WindowRect.y; + m_SettingComponent.SetFloat("Debugger.Window.Y", m_DebuggerComponent.WindowRect.y); + } + + if (m_LastWindowWidth != m_DebuggerComponent.WindowRect.width) + { + m_LastWindowWidth = m_DebuggerComponent.WindowRect.width; + m_SettingComponent.SetFloat("Debugger.Window.Width", m_DebuggerComponent.WindowRect.width); + } + + if (m_LastWindowHeight != m_DebuggerComponent.WindowRect.height) + { + m_LastWindowHeight = m_DebuggerComponent.WindowRect.height; + m_SettingComponent.SetFloat("Debugger.Window.Height", m_DebuggerComponent.WindowRect.height); + } + + if (m_LastWindowScale != m_DebuggerComponent.WindowScale) + { + m_LastWindowScale = m_DebuggerComponent.WindowScale; + m_SettingComponent.SetFloat("Debugger.Window.Scale", m_DebuggerComponent.WindowScale); + } + } + + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Window Settings"); + GUILayout.BeginVertical("box"); + { + GUILayout.BeginHorizontal(); + { + GUILayout.Label("Position:", GUILayout.Width(60f)); + GUILayout.Label("Drag window caption to move position."); + } + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + { + float width = m_DebuggerComponent.WindowRect.width; + GUILayout.Label("Width:", GUILayout.Width(60f)); + if (GUILayout.RepeatButton("-", GUILayout.Width(30f))) + { + width--; + } + width = GUILayout.HorizontalSlider(width, 100f, Screen.width - 20f); + if (GUILayout.RepeatButton("+", GUILayout.Width(30f))) + { + width++; + } + width = Mathf.Clamp(width, 100f, Screen.width - 20f); + if (width != m_DebuggerComponent.WindowRect.width) + { + m_DebuggerComponent.WindowRect = new Rect(m_DebuggerComponent.WindowRect.x, m_DebuggerComponent.WindowRect.y, width, m_DebuggerComponent.WindowRect.height); + } + } + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + { + float height = m_DebuggerComponent.WindowRect.height; + GUILayout.Label("Height:", GUILayout.Width(60f)); + if (GUILayout.RepeatButton("-", GUILayout.Width(30f))) + { + height--; + } + height = GUILayout.HorizontalSlider(height, 100f, Screen.height - 20f); + if (GUILayout.RepeatButton("+", GUILayout.Width(30f))) + { + height++; + } + height = Mathf.Clamp(height, 100f, Screen.height - 20f); + if (height != m_DebuggerComponent.WindowRect.height) + { + m_DebuggerComponent.WindowRect = new Rect(m_DebuggerComponent.WindowRect.x, m_DebuggerComponent.WindowRect.y, m_DebuggerComponent.WindowRect.width, height); + } + } + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + { + float scale = m_DebuggerComponent.WindowScale; + GUILayout.Label("Scale:", GUILayout.Width(60f)); + if (GUILayout.RepeatButton("-", GUILayout.Width(30f))) + { + scale -= 0.01f; + } + scale = GUILayout.HorizontalSlider(scale, 0.5f, 4f); + if (GUILayout.RepeatButton("+", GUILayout.Width(30f))) + { + scale += 0.01f; + } + scale = Mathf.Clamp(scale, 0.5f, 4f); + if (scale != m_DebuggerComponent.WindowScale) + { + m_DebuggerComponent.WindowScale = scale; + } + } + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + { + if (GUILayout.Button("0.5x", GUILayout.Height(60f))) + { + m_DebuggerComponent.WindowScale = 0.5f; + } + if (GUILayout.Button("1.0x", GUILayout.Height(60f))) + { + m_DebuggerComponent.WindowScale = 1f; + } + if (GUILayout.Button("1.5x", GUILayout.Height(60f))) + { + m_DebuggerComponent.WindowScale = 1.5f; + } + if (GUILayout.Button("2.0x", GUILayout.Height(60f))) + { + m_DebuggerComponent.WindowScale = 2f; + } + if (GUILayout.Button("2.5x", GUILayout.Height(60f))) + { + m_DebuggerComponent.WindowScale = 2.5f; + } + if (GUILayout.Button("3.0x", GUILayout.Height(60f))) + { + m_DebuggerComponent.WindowScale = 3f; + } + if (GUILayout.Button("3.5x", GUILayout.Height(60f))) + { + m_DebuggerComponent.WindowScale = 3.5f; + } + if (GUILayout.Button("4.0x", GUILayout.Height(60f))) + { + m_DebuggerComponent.WindowScale = 4f; + } + } + GUILayout.EndHorizontal(); + + if (GUILayout.Button("Reset Layout", GUILayout.Height(30f))) + { + m_DebuggerComponent.ResetLayout(); + } + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SettingsWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SettingsWindow.cs.meta new file mode 100644 index 0000000..e73c3d9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SettingsWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b4a36d102b4e1a648810a983c2101967 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SystemInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SystemInformationWindow.cs new file mode 100644 index 0000000..6ade6bd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SystemInformationWindow.cs @@ -0,0 +1,62 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class SystemInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("System Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Device Unique ID", SystemInfo.deviceUniqueIdentifier); + DrawItem("Device Name", SystemInfo.deviceName); + DrawItem("Device Type", SystemInfo.deviceType.ToString()); + DrawItem("Device Model", SystemInfo.deviceModel); + DrawItem("Processor Type", SystemInfo.processorType); + DrawItem("Processor Count", SystemInfo.processorCount.ToString()); + DrawItem("Processor Frequency", Utility.Text.Format("{0} MHz", SystemInfo.processorFrequency)); + DrawItem("System Memory Size", Utility.Text.Format("{0} MB", SystemInfo.systemMemorySize)); +#if UNITY_5_5_OR_NEWER + DrawItem("Operating System Family", SystemInfo.operatingSystemFamily.ToString()); +#endif + DrawItem("Operating System", SystemInfo.operatingSystem); +#if UNITY_5_6_OR_NEWER + DrawItem("Battery Status", SystemInfo.batteryStatus.ToString()); + DrawItem("Battery Level", GetBatteryLevelString(SystemInfo.batteryLevel)); +#endif +#if UNITY_5_4_OR_NEWER + DrawItem("Supports Audio", SystemInfo.supportsAudio.ToString()); +#endif + DrawItem("Supports Location Service", SystemInfo.supportsLocationService.ToString()); + DrawItem("Supports Accelerometer", SystemInfo.supportsAccelerometer.ToString()); + DrawItem("Supports Gyroscope", SystemInfo.supportsGyroscope.ToString()); + DrawItem("Supports Vibration", SystemInfo.supportsVibration.ToString()); + DrawItem("Genuine", Application.genuine.ToString()); + DrawItem("Genuine Check Available", Application.genuineCheckAvailable.ToString()); + } + GUILayout.EndVertical(); + } + + private string GetBatteryLevelString(float batteryLevel) + { + if (batteryLevel < 0f) + { + return "Unavailable"; + } + + return batteryLevel.ToString("P0"); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SystemInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SystemInformationWindow.cs.meta new file mode 100644 index 0000000..b8505c5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.SystemInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 788d38477d0fde741b8939db86e6a083 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.TimeInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.TimeInformationWindow.cs new file mode 100644 index 0000000..d1a9409 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.TimeInformationWindow.cs @@ -0,0 +1,76 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class TimeInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Time Information"); + GUILayout.BeginVertical("box"); + { + DrawItem("Time Scale", Utility.Text.Format("{0} [{1}]", Time.timeScale, GetTimeScaleDescription(Time.timeScale))); + DrawItem("Realtime Since Startup", Time.realtimeSinceStartup.ToString()); + DrawItem("Time Since Level Load", Time.timeSinceLevelLoad.ToString()); + DrawItem("Time", Time.time.ToString()); + DrawItem("Fixed Time", Time.fixedTime.ToString()); + DrawItem("Unscaled Time", Time.unscaledTime.ToString()); +#if UNITY_5_6_OR_NEWER + DrawItem("Fixed Unscaled Time", Time.fixedUnscaledTime.ToString()); +#endif + DrawItem("Delta Time", Time.deltaTime.ToString()); + DrawItem("Fixed Delta Time", Time.fixedDeltaTime.ToString()); + DrawItem("Unscaled Delta Time", Time.unscaledDeltaTime.ToString()); +#if UNITY_5_6_OR_NEWER + DrawItem("Fixed Unscaled Delta Time", Time.fixedUnscaledDeltaTime.ToString()); +#endif + DrawItem("Smooth Delta Time", Time.smoothDeltaTime.ToString()); + DrawItem("Maximum Delta Time", Time.maximumDeltaTime.ToString()); +#if UNITY_5_5_OR_NEWER + DrawItem("Maximum Particle Delta Time", Time.maximumParticleDeltaTime.ToString()); +#endif + DrawItem("Frame Count", Time.frameCount.ToString()); + DrawItem("Rendered Frame Count", Time.renderedFrameCount.ToString()); + DrawItem("Capture Framerate", Time.captureFramerate.ToString()); +#if UNITY_2019_2_OR_NEWER + DrawItem("Capture Delta Time", Time.captureDeltaTime.ToString()); +#endif +#if UNITY_5_6_OR_NEWER + DrawItem("In Fixed Time Step", Time.inFixedTimeStep.ToString()); +#endif + } + GUILayout.EndVertical(); + } + + private string GetTimeScaleDescription(float timeScale) + { + if (timeScale <= 0f) + { + return "Pause"; + } + + if (timeScale < 1f) + { + return "Slower"; + } + + if (timeScale > 1f) + { + return "Faster"; + } + + return "Normal"; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.TimeInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.TimeInformationWindow.cs.meta new file mode 100644 index 0000000..fd67ff3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.TimeInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e8bdf40da7ffdc94ab9e39ba8daeaa3a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.WebPlayerInformationWindow.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.WebPlayerInformationWindow.cs new file mode 100644 index 0000000..fce2e5f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.WebPlayerInformationWindow.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + private sealed class WebPlayerInformationWindow : ScrollableDebuggerWindowBase + { + protected override void OnDrawScrollableWindow() + { + GUILayout.Label("Web Player Information"); + GUILayout.BeginVertical("box"); + { +#if !UNITY_2017_2_OR_NEWER + DrawItem("Is Web Player", Application.isWebPlayer.ToString()); +#endif + DrawItem("Absolute URL", Application.absoluteURL); +#if !UNITY_2017_2_OR_NEWER + DrawItem("Source Value", Application.srcValue); +#endif +#if !UNITY_2018_2_OR_NEWER + DrawItem("Streamed Bytes", Application.streamedBytes.ToString()); +#endif +#if UNITY_5_3 || UNITY_5_4 + DrawItem("Web Security Enabled", Application.webSecurityEnabled.ToString()); + DrawItem("Web Security Host URL", Application.webSecurityHostUrl.ToString()); +#endif + } + GUILayout.EndVertical(); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.WebPlayerInformationWindow.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.WebPlayerInformationWindow.cs.meta new file mode 100644 index 0000000..a194fac --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.WebPlayerInformationWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: eea52d2ddd7a8804f956d4b9a2d67e8f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.cs new file mode 100644 index 0000000..9c95be0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.cs @@ -0,0 +1,437 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Debugger; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 调试器组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Debugger")] + public sealed partial class DebuggerComponent : GameFrameworkComponent + { + /// + /// 默认调试器漂浮框大小。 + /// + internal static readonly Rect DefaultIconRect = new Rect(10f, 10f, 60f, 60f); + + /// + /// 默认调试器窗口大小。 + /// + internal static readonly Rect DefaultWindowRect = new Rect(10f, 10f, 640f, 480f); + + /// + /// 默认调试器窗口缩放比例。 + /// + internal static readonly float DefaultWindowScale = 1f; + + private static TextEditor s_TextEditor; + private IDebuggerManager m_DebuggerManager = null; + private Rect m_DragRect = new Rect(0f, 0f, float.MaxValue, 25f); + private Rect m_IconRect = DefaultIconRect; + private Rect m_WindowRect = DefaultWindowRect; + private float m_WindowScale = DefaultWindowScale; + + [SerializeField] + private GUISkin m_Skin = null; + + [SerializeField] + private DebuggerActiveWindowType m_ActiveWindow = DebuggerActiveWindowType.AlwaysOpen; + + [SerializeField] + private bool m_ShowFullWindow = false; + + [SerializeField] + private ConsoleWindow m_ConsoleWindow = new ConsoleWindow(); + + private SystemInformationWindow m_SystemInformationWindow = new SystemInformationWindow(); + private EnvironmentInformationWindow m_EnvironmentInformationWindow = new EnvironmentInformationWindow(); + private ScreenInformationWindow m_ScreenInformationWindow = new ScreenInformationWindow(); + private GraphicsInformationWindow m_GraphicsInformationWindow = new GraphicsInformationWindow(); + private InputSummaryInformationWindow m_InputSummaryInformationWindow = new InputSummaryInformationWindow(); + private InputTouchInformationWindow m_InputTouchInformationWindow = new InputTouchInformationWindow(); + private InputLocationInformationWindow m_InputLocationInformationWindow = new InputLocationInformationWindow(); + private InputAccelerationInformationWindow m_InputAccelerationInformationWindow = new InputAccelerationInformationWindow(); + private InputGyroscopeInformationWindow m_InputGyroscopeInformationWindow = new InputGyroscopeInformationWindow(); + private InputCompassInformationWindow m_InputCompassInformationWindow = new InputCompassInformationWindow(); + private PathInformationWindow m_PathInformationWindow = new PathInformationWindow(); + private SceneInformationWindow m_SceneInformationWindow = new SceneInformationWindow(); + private TimeInformationWindow m_TimeInformationWindow = new TimeInformationWindow(); + private QualityInformationWindow m_QualityInformationWindow = new QualityInformationWindow(); + private ProfilerInformationWindow m_ProfilerInformationWindow = new ProfilerInformationWindow(); + private WebPlayerInformationWindow m_WebPlayerInformationWindow = new WebPlayerInformationWindow(); + private RuntimeMemorySummaryWindow m_RuntimeMemorySummaryWindow = new RuntimeMemorySummaryWindow(); + private RuntimeMemoryInformationWindow m_RuntimeMemoryAllInformationWindow = new RuntimeMemoryInformationWindow(); + private RuntimeMemoryInformationWindow m_RuntimeMemoryTextureInformationWindow = new RuntimeMemoryInformationWindow(); + private RuntimeMemoryInformationWindow m_RuntimeMemoryMeshInformationWindow = new RuntimeMemoryInformationWindow(); + private RuntimeMemoryInformationWindow m_RuntimeMemoryMaterialInformationWindow = new RuntimeMemoryInformationWindow(); + private RuntimeMemoryInformationWindow m_RuntimeMemoryShaderInformationWindow = new RuntimeMemoryInformationWindow(); + private RuntimeMemoryInformationWindow m_RuntimeMemoryAnimationClipInformationWindow = new RuntimeMemoryInformationWindow(); + private RuntimeMemoryInformationWindow m_RuntimeMemoryAudioClipInformationWindow = new RuntimeMemoryInformationWindow(); + private RuntimeMemoryInformationWindow m_RuntimeMemoryFontInformationWindow = new RuntimeMemoryInformationWindow(); + private RuntimeMemoryInformationWindow m_RuntimeMemoryTextAssetInformationWindow = new RuntimeMemoryInformationWindow(); + private RuntimeMemoryInformationWindow m_RuntimeMemoryScriptableObjectInformationWindow = new RuntimeMemoryInformationWindow(); + private ObjectPoolInformationWindow m_ObjectPoolInformationWindow = new ObjectPoolInformationWindow(); + private ReferencePoolInformationWindow m_ReferencePoolInformationWindow = new ReferencePoolInformationWindow(); + private NetworkInformationWindow m_NetworkInformationWindow = new NetworkInformationWindow(); + private SettingsWindow m_SettingsWindow = new SettingsWindow(); + private OperationsWindow m_OperationsWindow = new OperationsWindow(); + + private FpsCounter m_FpsCounter = null; + + /// + /// 获取或设置调试器窗口是否激活。 + /// + public bool ActiveWindow + { + get + { + return m_DebuggerManager.ActiveWindow; + } + set + { + m_DebuggerManager.ActiveWindow = value; + enabled = value; + } + } + + /// + /// 获取或设置是否显示完整调试器界面。 + /// + public bool ShowFullWindow + { + get + { + return m_ShowFullWindow; + } + set + { + m_ShowFullWindow = value; + } + } + + /// + /// 获取或设置调试器漂浮框大小。 + /// + public Rect IconRect + { + get + { + return m_IconRect; + } + set + { + m_IconRect = value; + } + } + + /// + /// 获取或设置调试器窗口大小。 + /// + public Rect WindowRect + { + get + { + return m_WindowRect; + } + set + { + m_WindowRect = value; + } + } + + /// + /// 获取或设置调试器窗口缩放比例。 + /// + public float WindowScale + { + get + { + return m_WindowScale; + } + set + { + m_WindowScale = value; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + if(s_TextEditor == null) + { + s_TextEditor = new TextEditor(); + } + + m_DebuggerManager = GameFrameworkEntry.GetModule(); + if (m_DebuggerManager == null) + { + Log.Fatal("Debugger manager is invalid."); + return; + } + + m_FpsCounter = new FpsCounter(0.5f); + } + + private void Start() + { + RegisterDebuggerWindow("Console", m_ConsoleWindow); + RegisterDebuggerWindow("Information/System", m_SystemInformationWindow); + RegisterDebuggerWindow("Information/Environment", m_EnvironmentInformationWindow); + RegisterDebuggerWindow("Information/Screen", m_ScreenInformationWindow); + RegisterDebuggerWindow("Information/Graphics", m_GraphicsInformationWindow); + RegisterDebuggerWindow("Information/Input/Summary", m_InputSummaryInformationWindow); + RegisterDebuggerWindow("Information/Input/Touch", m_InputTouchInformationWindow); + RegisterDebuggerWindow("Information/Input/Location", m_InputLocationInformationWindow); + RegisterDebuggerWindow("Information/Input/Acceleration", m_InputAccelerationInformationWindow); + RegisterDebuggerWindow("Information/Input/Gyroscope", m_InputGyroscopeInformationWindow); + RegisterDebuggerWindow("Information/Input/Compass", m_InputCompassInformationWindow); + RegisterDebuggerWindow("Information/Other/Scene", m_SceneInformationWindow); + RegisterDebuggerWindow("Information/Other/Path", m_PathInformationWindow); + RegisterDebuggerWindow("Information/Other/Time", m_TimeInformationWindow); + RegisterDebuggerWindow("Information/Other/Quality", m_QualityInformationWindow); + RegisterDebuggerWindow("Information/Other/Web Player", m_WebPlayerInformationWindow); + RegisterDebuggerWindow("Profiler/Summary", m_ProfilerInformationWindow); + RegisterDebuggerWindow("Profiler/Memory/Summary", m_RuntimeMemorySummaryWindow); + RegisterDebuggerWindow("Profiler/Memory/All", m_RuntimeMemoryAllInformationWindow); + RegisterDebuggerWindow("Profiler/Memory/Texture", m_RuntimeMemoryTextureInformationWindow); + RegisterDebuggerWindow("Profiler/Memory/Mesh", m_RuntimeMemoryMeshInformationWindow); + RegisterDebuggerWindow("Profiler/Memory/Material", m_RuntimeMemoryMaterialInformationWindow); + RegisterDebuggerWindow("Profiler/Memory/Shader", m_RuntimeMemoryShaderInformationWindow); + RegisterDebuggerWindow("Profiler/Memory/AnimationClip", m_RuntimeMemoryAnimationClipInformationWindow); + RegisterDebuggerWindow("Profiler/Memory/AudioClip", m_RuntimeMemoryAudioClipInformationWindow); + RegisterDebuggerWindow("Profiler/Memory/Font", m_RuntimeMemoryFontInformationWindow); + RegisterDebuggerWindow("Profiler/Memory/TextAsset", m_RuntimeMemoryTextAssetInformationWindow); + RegisterDebuggerWindow("Profiler/Memory/ScriptableObject", m_RuntimeMemoryScriptableObjectInformationWindow); + RegisterDebuggerWindow("Profiler/Object Pool", m_ObjectPoolInformationWindow); + RegisterDebuggerWindow("Profiler/Reference Pool", m_ReferencePoolInformationWindow); + RegisterDebuggerWindow("Profiler/Network", m_NetworkInformationWindow); + RegisterDebuggerWindow("Other/Settings", m_SettingsWindow); + RegisterDebuggerWindow("Other/Operations", m_OperationsWindow); + + switch (m_ActiveWindow) + { + case DebuggerActiveWindowType.AlwaysOpen: + ActiveWindow = true; + break; + + case DebuggerActiveWindowType.OnlyOpenWhenDevelopment: + ActiveWindow = Debug.isDebugBuild; + break; + + case DebuggerActiveWindowType.OnlyOpenInEditor: + ActiveWindow = Application.isEditor; + break; + + default: + ActiveWindow = false; + break; + } + } + + private void Update() + { + m_FpsCounter.Update(Time.deltaTime, Time.unscaledDeltaTime); + } + + private void OnGUI() + { + if (m_DebuggerManager == null || !m_DebuggerManager.ActiveWindow) + { + return; + } + + GUISkin cachedGuiSkin = GUI.skin; + Matrix4x4 cachedMatrix = GUI.matrix; + + GUI.skin = m_Skin; + GUI.matrix = Matrix4x4.Scale(new Vector3(m_WindowScale, m_WindowScale, 1f)); + + if (m_ShowFullWindow) + { + m_WindowRect = GUILayout.Window(0, m_WindowRect, DrawWindow, "GAME FRAMEWORK DEBUGGER"); + } + else + { + m_IconRect = GUILayout.Window(0, m_IconRect, DrawDebuggerWindowIcon, "DEBUGGER"); + } + + GUI.matrix = cachedMatrix; + GUI.skin = cachedGuiSkin; + } + + /// + /// 注册调试器窗口。 + /// + /// 调试器窗口路径。 + /// 要注册的调试器窗口。 + /// 初始化调试器窗口参数。 + public void RegisterDebuggerWindow(string path, IDebuggerWindow debuggerWindow, params object[] args) + { + m_DebuggerManager.RegisterDebuggerWindow(path, debuggerWindow, args); + } + + /// + /// 解除注册调试器窗口。 + /// + /// 调试器窗口路径。 + /// 是否解除注册调试器窗口成功。 + public bool UnregisterDebuggerWindow(string path) + { + return m_DebuggerManager.UnregisterDebuggerWindow(path); + } + + /// + /// 获取调试器窗口。 + /// + /// 调试器窗口路径。 + /// 要获取的调试器窗口。 + public IDebuggerWindow GetDebuggerWindow(string path) + { + return m_DebuggerManager.GetDebuggerWindow(path); + } + + /// + /// 选中调试器窗口。 + /// + /// 调试器窗口路径。 + /// 是否成功选中调试器窗口。 + public bool SelectDebuggerWindow(string path) + { + return m_DebuggerManager.SelectDebuggerWindow(path); + } + + /// + /// 还原调试器窗口布局。 + /// + public void ResetLayout() + { + IconRect = DefaultIconRect; + WindowRect = DefaultWindowRect; + WindowScale = DefaultWindowScale; + } + + /// + /// 获取记录的所有日志。 + /// + /// 要获取的日志。 + public void GetRecentLogs(List results) + { + m_ConsoleWindow.GetRecentLogs(results); + } + + /// + /// 获取记录的最近日志。 + /// + /// 要获取的日志。 + /// 要获取最近日志的数量。 + public void GetRecentLogs(List results, int count) + { + m_ConsoleWindow.GetRecentLogs(results, count); + } + + private void DrawWindow(int windowId) + { + GUI.DragWindow(m_DragRect); + DrawDebuggerWindowGroup(m_DebuggerManager.DebuggerWindowRoot); + } + + private void DrawDebuggerWindowGroup(IDebuggerWindowGroup debuggerWindowGroup) + { + if (debuggerWindowGroup == null) + { + return; + } + + List names = new List(); + string[] debuggerWindowNames = debuggerWindowGroup.GetDebuggerWindowNames(); + for (int i = 0; i < debuggerWindowNames.Length; i++) + { + names.Add(Utility.Text.Format("{0}", debuggerWindowNames[i])); + } + + if (debuggerWindowGroup == m_DebuggerManager.DebuggerWindowRoot) + { + names.Add("Close"); + } + + int toolbarIndex = GUILayout.Toolbar(debuggerWindowGroup.SelectedIndex, names.ToArray(), GUILayout.Height(30f), GUILayout.MaxWidth(Screen.width)); + if (toolbarIndex >= debuggerWindowGroup.DebuggerWindowCount) + { + m_ShowFullWindow = false; + return; + } + + if (debuggerWindowGroup.SelectedWindow == null) + { + return; + } + + if (debuggerWindowGroup.SelectedIndex != toolbarIndex) + { + debuggerWindowGroup.SelectedWindow.OnLeave(); + debuggerWindowGroup.SelectedIndex = toolbarIndex; + debuggerWindowGroup.SelectedWindow.OnEnter(); + } + + IDebuggerWindowGroup subDebuggerWindowGroup = debuggerWindowGroup.SelectedWindow as IDebuggerWindowGroup; + if (subDebuggerWindowGroup != null) + { + DrawDebuggerWindowGroup(subDebuggerWindowGroup); + } + + debuggerWindowGroup.SelectedWindow.OnDraw(); + } + + private void DrawDebuggerWindowIcon(int windowId) + { + GUI.DragWindow(m_DragRect); + GUILayout.Space(5); + Color32 color = Color.white; + m_ConsoleWindow.RefreshCount(); + if (m_ConsoleWindow.FatalCount > 0) + { + color = m_ConsoleWindow.GetLogStringColor(LogType.Exception); + } + else if (m_ConsoleWindow.ErrorCount > 0) + { + color = m_ConsoleWindow.GetLogStringColor(LogType.Error); + } + else if (m_ConsoleWindow.WarningCount > 0) + { + color = m_ConsoleWindow.GetLogStringColor(LogType.Warning); + } + else + { + color = m_ConsoleWindow.GetLogStringColor(LogType.Log); + } + + string title = Utility.Text.Format("FPS: {4:F2}", color.r, color.g, color.b, color.a, m_FpsCounter.CurrentFps); + if (GUILayout.Button(title, GUILayout.Width(100f), GUILayout.Height(40f))) + { + m_ShowFullWindow = true; + } + } + + private static void CopyToClipboard(string content) + { + s_TextEditor.text = content; + s_TextEditor.OnFocus(); + s_TextEditor.Copy(); + s_TextEditor.text = string.Empty; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.cs.meta new file mode 100644 index 0000000..6288f5d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Debugger/DebuggerComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f05eaceeebe870a4595e51f998ed518b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download.meta new file mode 100644 index 0000000..f8c7788 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 565ef4330c482724588a750b62d2c533 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadAgentHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadAgentHelperBase.cs new file mode 100644 index 0000000..423c9dc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadAgentHelperBase.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Download; +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 下载代理辅助器基类。 + /// + public abstract class DownloadAgentHelperBase : MonoBehaviour, IDownloadAgentHelper + { + /// + /// 范围不适用错误码。 + /// + protected const int RangeNotSatisfiableErrorCode = 416; + + /// + /// 下载代理辅助器更新数据流事件。 + /// + public abstract event EventHandler DownloadAgentHelperUpdateBytes; + + /// + /// 下载代理辅助器更新数据大小事件。 + /// + public abstract event EventHandler DownloadAgentHelperUpdateLength; + + /// + /// 下载代理辅助器完成事件。 + /// + public abstract event EventHandler DownloadAgentHelperComplete; + + /// + /// 下载代理辅助器错误事件。 + /// + public abstract event EventHandler DownloadAgentHelperError; + + /// + /// 通过下载代理辅助器下载指定地址的数据。 + /// + /// 下载地址。 + /// 用户自定义数据。 + public abstract void Download(string downloadUri, object userData); + + /// + /// 通过下载代理辅助器下载指定地址的数据。 + /// + /// 下载地址。 + /// 下载数据起始位置。 + /// 用户自定义数据。 + public abstract void Download(string downloadUri, long fromPosition, object userData); + + /// + /// 通过下载代理辅助器下载指定地址的数据。 + /// + /// 下载地址。 + /// 下载数据起始位置。 + /// 下载数据结束位置。 + /// 用户自定义数据。 + public abstract void Download(string downloadUri, long fromPosition, long toPosition, object userData); + + /// + /// 重置下载代理辅助器。 + /// + public abstract void Reset(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadAgentHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadAgentHelperBase.cs.meta new file mode 100644 index 0000000..9fd9a0e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadAgentHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0c6e60daac172714dba741765e1fdd97 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadComponent.cs new file mode 100644 index 0000000..cf633d7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadComponent.cs @@ -0,0 +1,409 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Download; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 下载组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Download")] + public sealed class DownloadComponent : GameFrameworkComponent + { + private const int DefaultPriority = 0; + private const int OneMegaBytes = 1024 * 1024; + + private IDownloadManager m_DownloadManager = null; + private EventComponent m_EventComponent = null; + + [SerializeField] + private Transform m_InstanceRoot = null; + + [SerializeField] + private string m_DownloadAgentHelperTypeName = "UnityGameFramework.Runtime.UnityWebRequestDownloadAgentHelper"; + + [SerializeField] + private DownloadAgentHelperBase m_CustomDownloadAgentHelper = null; + + [SerializeField] + private int m_DownloadAgentHelperCount = 3; + + [SerializeField] + private float m_Timeout = 30f; + + [SerializeField] + private int m_FlushSize = OneMegaBytes; + + /// + /// 获取或设置下载是否被暂停。 + /// + public bool Paused + { + get + { + return m_DownloadManager.Paused; + } + set + { + m_DownloadManager.Paused = value; + } + } + + /// + /// 获取下载代理总数量。 + /// + public int TotalAgentCount + { + get + { + return m_DownloadManager.TotalAgentCount; + } + } + + /// + /// 获取可用下载代理数量。 + /// + public int FreeAgentCount + { + get + { + return m_DownloadManager.FreeAgentCount; + } + } + + /// + /// 获取工作中下载代理数量。 + /// + public int WorkingAgentCount + { + get + { + return m_DownloadManager.WorkingAgentCount; + } + } + + /// + /// 获取等待下载任务数量。 + /// + public int WaitingTaskCount + { + get + { + return m_DownloadManager.WaitingTaskCount; + } + } + + /// + /// 获取或设置下载超时时长,以秒为单位。 + /// + public float Timeout + { + get + { + return m_DownloadManager.Timeout; + } + set + { + m_DownloadManager.Timeout = m_Timeout = value; + } + } + + /// + /// 获取或设置将缓冲区写入磁盘的临界大小,仅当开启断点续传时有效。 + /// + public int FlushSize + { + get + { + return m_DownloadManager.FlushSize; + } + set + { + m_DownloadManager.FlushSize = m_FlushSize = value; + } + } + + /// + /// 获取当前下载速度。 + /// + public float CurrentSpeed + { + get + { + return m_DownloadManager.CurrentSpeed; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_DownloadManager = GameFrameworkEntry.GetModule(); + if (m_DownloadManager == null) + { + Log.Fatal("Download manager is invalid."); + return; + } + + m_DownloadManager.DownloadStart += OnDownloadStart; + m_DownloadManager.DownloadUpdate += OnDownloadUpdate; + m_DownloadManager.DownloadSuccess += OnDownloadSuccess; + m_DownloadManager.DownloadFailure += OnDownloadFailure; + m_DownloadManager.FlushSize = m_FlushSize; + m_DownloadManager.Timeout = m_Timeout; + } + + private void Start() + { + m_EventComponent = GameEntry.GetComponent(); + if (m_EventComponent == null) + { + Log.Fatal("Event component is invalid."); + return; + } + + if (m_InstanceRoot == null) + { + m_InstanceRoot = new GameObject("Download Agent Instances").transform; + m_InstanceRoot.SetParent(gameObject.transform); + m_InstanceRoot.localScale = Vector3.one; + } + + for (int i = 0; i < m_DownloadAgentHelperCount; i++) + { + AddDownloadAgentHelper(i); + } + } + + /// + /// 根据下载任务的序列编号获取下载任务的信息。 + /// + /// 要获取信息的下载任务的序列编号。 + /// 下载任务的信息。 + public TaskInfo GetDownloadInfo(int serialId) + { + return m_DownloadManager.GetDownloadInfo(serialId); + } + + /// + /// 根据下载任务的标签获取下载任务的信息。 + /// + /// 要获取信息的下载任务的标签。 + /// 下载任务的信息。 + public TaskInfo[] GetDownloadInfos(string tag) + { + return m_DownloadManager.GetDownloadInfos(tag); + } + + /// + /// 根据下载任务的标签获取下载任务的信息。 + /// + /// 要获取信息的下载任务的标签。 + /// 下载任务的信息。 + public void GetDownloadInfos(string tag, List results) + { + m_DownloadManager.GetDownloadInfos(tag, results); + } + + /// + /// 获取所有下载任务的信息。 + /// + /// 所有下载任务的信息。 + public TaskInfo[] GetAllDownloadInfos() + { + return m_DownloadManager.GetAllDownloadInfos(); + } + + /// + /// 获取所有下载任务的信息。 + /// + /// 所有下载任务的信息。 + public void GetAllDownloadInfos(List results) + { + m_DownloadManager.GetAllDownloadInfos(results); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri) + { + return AddDownload(downloadPath, downloadUri, null, DefaultPriority, null); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, string tag) + { + return AddDownload(downloadPath, downloadUri, tag, DefaultPriority, null); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的优先级。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, int priority) + { + return AddDownload(downloadPath, downloadUri, null, priority, null); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 用户自定义数据。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, object userData) + { + return AddDownload(downloadPath, downloadUri, null, DefaultPriority, userData); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 下载任务的优先级。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, string tag, int priority) + { + return AddDownload(downloadPath, downloadUri, tag, priority, null); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 用户自定义数据。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, string tag, object userData) + { + return AddDownload(downloadPath, downloadUri, tag, DefaultPriority, userData); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的优先级。 + /// 用户自定义数据。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, int priority, object userData) + { + return AddDownload(downloadPath, downloadUri, null, priority, userData); + } + + /// + /// 增加下载任务。 + /// + /// 下载后存放路径。 + /// 原始下载地址。 + /// 下载任务的标签。 + /// 下载任务的优先级。 + /// 用户自定义数据。 + /// 新增下载任务的序列编号。 + public int AddDownload(string downloadPath, string downloadUri, string tag, int priority, object userData) + { + return m_DownloadManager.AddDownload(downloadPath, downloadUri, tag, priority, userData); + } + + /// + /// 根据下载任务的序列编号移除下载任务。 + /// + /// 要移除下载任务的序列编号。 + /// 是否移除下载任务成功。 + public bool RemoveDownload(int serialId) + { + return m_DownloadManager.RemoveDownload(serialId); + } + + /// + /// 根据下载任务的标签移除下载任务。 + /// + /// 要移除下载任务的标签。 + /// 移除下载任务的数量。 + public int RemoveDownloads(string tag) + { + return m_DownloadManager.RemoveDownloads(tag); + } + + /// + /// 移除所有下载任务。 + /// + /// 移除下载任务的数量。 + public int RemoveAllDownloads() + { + return m_DownloadManager.RemoveAllDownloads(); + } + + /// + /// 增加下载代理辅助器。 + /// + /// 下载代理辅助器索引。 + private void AddDownloadAgentHelper(int index) + { + DownloadAgentHelperBase downloadAgentHelper = Helper.CreateHelper(m_DownloadAgentHelperTypeName, m_CustomDownloadAgentHelper, index); + if (downloadAgentHelper == null) + { + Log.Error("Can not create download agent helper."); + return; + } + + downloadAgentHelper.name = Utility.Text.Format("Download Agent Helper - {0}", index); + Transform transform = downloadAgentHelper.transform; + transform.SetParent(m_InstanceRoot); + transform.localScale = Vector3.one; + + m_DownloadManager.AddDownloadAgentHelper(downloadAgentHelper); + } + + private void OnDownloadStart(object sender, GameFramework.Download.DownloadStartEventArgs e) + { + m_EventComponent.Fire(this, DownloadStartEventArgs.Create(e)); + } + + private void OnDownloadUpdate(object sender, GameFramework.Download.DownloadUpdateEventArgs e) + { + m_EventComponent.Fire(this, DownloadUpdateEventArgs.Create(e)); + } + + private void OnDownloadSuccess(object sender, GameFramework.Download.DownloadSuccessEventArgs e) + { + m_EventComponent.Fire(this, DownloadSuccessEventArgs.Create(e)); + } + + private void OnDownloadFailure(object sender, GameFramework.Download.DownloadFailureEventArgs e) + { + Log.Warning("Download failure, download serial id '{0}', download path '{1}', download uri '{2}', error message '{3}'.", e.SerialId, e.DownloadPath, e.DownloadUri, e.ErrorMessage); + m_EventComponent.Fire(this, DownloadFailureEventArgs.Create(e)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadComponent.cs.meta new file mode 100644 index 0000000..7460354 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9259de0854ba2624aa59aca15c6af063 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadFailureEventArgs.cs new file mode 100644 index 0000000..f9cbbec --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadFailureEventArgs.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 下载失败事件。 + /// + public sealed class DownloadFailureEventArgs : GameEventArgs + { + /// + /// 下载失败事件编号。 + /// + public static readonly int EventId = typeof(DownloadFailureEventArgs).GetHashCode(); + + /// + /// 初始化下载失败事件的新实例。 + /// + public DownloadFailureEventArgs() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取下载失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取下载任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建下载失败事件。 + /// + /// 内部事件。 + /// 创建的下载失败事件。 + public static DownloadFailureEventArgs Create(GameFramework.Download.DownloadFailureEventArgs e) + { + DownloadFailureEventArgs downloadFailureEventArgs = ReferencePool.Acquire(); + downloadFailureEventArgs.SerialId = e.SerialId; + downloadFailureEventArgs.DownloadPath = e.DownloadPath; + downloadFailureEventArgs.DownloadUri = e.DownloadUri; + downloadFailureEventArgs.ErrorMessage = e.ErrorMessage; + downloadFailureEventArgs.UserData = e.UserData; + return downloadFailureEventArgs; + } + + /// + /// 清理下载失败事件。 + /// + public override void Clear() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadFailureEventArgs.cs.meta new file mode 100644 index 0000000..1500aa8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b3227ba2aea8444397bb69d11e667fb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadStartEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadStartEventArgs.cs new file mode 100644 index 0000000..6acfed8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadStartEventArgs.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 下载开始事件。 + /// + public sealed class DownloadStartEventArgs : GameEventArgs + { + /// + /// 下载开始事件编号。 + /// + public static readonly int EventId = typeof(DownloadStartEventArgs).GetHashCode(); + + /// + /// 初始化下载开始事件的新实例。 + /// + public DownloadStartEventArgs() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0L; + UserData = null; + } + + /// + /// 获取下载开始事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取下载任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取当前大小。 + /// + public long CurrentLength + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建下载开始事件。 + /// + /// 内部事件。 + /// 创建的下载开始事件。 + public static DownloadStartEventArgs Create(GameFramework.Download.DownloadStartEventArgs e) + { + DownloadStartEventArgs downloadStartEventArgs = ReferencePool.Acquire(); + downloadStartEventArgs.SerialId = e.SerialId; + downloadStartEventArgs.DownloadPath = e.DownloadPath; + downloadStartEventArgs.DownloadUri = e.DownloadUri; + downloadStartEventArgs.CurrentLength = e.CurrentLength; + downloadStartEventArgs.UserData = e.UserData; + return downloadStartEventArgs; + } + + /// + /// 清理下载开始事件。 + /// + public override void Clear() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0L; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadStartEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadStartEventArgs.cs.meta new file mode 100644 index 0000000..78ad77f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadStartEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ee21721798f32c7459a235204468db6c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadSuccessEventArgs.cs new file mode 100644 index 0000000..6db89e6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadSuccessEventArgs.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 下载成功事件。 + /// + public sealed class DownloadSuccessEventArgs : GameEventArgs + { + /// + /// 下载成功事件编号。 + /// + public static readonly int EventId = typeof(DownloadSuccessEventArgs).GetHashCode(); + + /// + /// 初始化下载成功事件的新实例。 + /// + public DownloadSuccessEventArgs() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0L; + UserData = null; + } + + /// + /// 获取下载成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取下载任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取当前大小。 + /// + public long CurrentLength + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建下载成功事件。 + /// + /// 内部事件。 + /// 创建的下载成功事件。 + public static DownloadSuccessEventArgs Create(GameFramework.Download.DownloadSuccessEventArgs e) + { + DownloadSuccessEventArgs downloadSuccessEventArgs = ReferencePool.Acquire(); + downloadSuccessEventArgs.SerialId = e.SerialId; + downloadSuccessEventArgs.DownloadPath = e.DownloadPath; + downloadSuccessEventArgs.DownloadUri = e.DownloadUri; + downloadSuccessEventArgs.CurrentLength = e.CurrentLength; + downloadSuccessEventArgs.UserData = e.UserData; + return downloadSuccessEventArgs; + } + + /// + /// 清理下载成功事件。 + /// + public override void Clear() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0L; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadSuccessEventArgs.cs.meta new file mode 100644 index 0000000..3500639 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b0d6ca8ee116c7c43b319992b5a4cdbf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadUpdateEventArgs.cs new file mode 100644 index 0000000..6e35ab9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadUpdateEventArgs.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 下载更新事件。 + /// + public sealed class DownloadUpdateEventArgs : GameEventArgs + { + /// + /// 下载更新事件编号。 + /// + public static readonly int EventId = typeof(DownloadUpdateEventArgs).GetHashCode(); + + /// + /// 初始化下载更新事件的新实例。 + /// + public DownloadUpdateEventArgs() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0L; + UserData = null; + } + + /// + /// 获取下载更新事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取下载任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取当前大小。 + /// + public long CurrentLength + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建下载更新事件。 + /// + /// 内部事件。 + /// 创建的下载更新事件。 + public static DownloadUpdateEventArgs Create(GameFramework.Download.DownloadUpdateEventArgs e) + { + DownloadUpdateEventArgs downloadUpdateEventArgs = ReferencePool.Acquire(); + downloadUpdateEventArgs.SerialId = e.SerialId; + downloadUpdateEventArgs.DownloadPath = e.DownloadPath; + downloadUpdateEventArgs.DownloadUri = e.DownloadUri; + downloadUpdateEventArgs.CurrentLength = e.CurrentLength; + downloadUpdateEventArgs.UserData = e.UserData; + return downloadUpdateEventArgs; + } + + /// + /// 清理下载更新事件。 + /// + public override void Clear() + { + SerialId = 0; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0L; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadUpdateEventArgs.cs.meta new file mode 100644 index 0000000..9e7eb8e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/DownloadUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: da30c910f3da16f4cb29770ee035496b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/UnityWebRequestDownloadAgentHelper.DownloadHandler.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/UnityWebRequestDownloadAgentHelper.DownloadHandler.cs new file mode 100644 index 0000000..060c332 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/UnityWebRequestDownloadAgentHelper.DownloadHandler.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Download; +using System; +#if UNITY_5_4_OR_NEWER +using UnityEngine.Networking; +#else +using UnityEngine.Experimental.Networking; +#endif + +namespace UnityGameFramework.Runtime +{ + public partial class UnityWebRequestDownloadAgentHelper : DownloadAgentHelperBase, IDisposable + { + private sealed class DownloadHandler : DownloadHandlerScript + { + private readonly UnityWebRequestDownloadAgentHelper m_Owner; + + public DownloadHandler(UnityWebRequestDownloadAgentHelper owner) + : base(owner.m_CachedBytes) + { + m_Owner = owner; + } + + protected override bool ReceiveData(byte[] data, int dataLength) + { + if (m_Owner != null && m_Owner.m_UnityWebRequest != null && dataLength > 0) + { + DownloadAgentHelperUpdateBytesEventArgs downloadAgentHelperUpdateBytesEventArgs = DownloadAgentHelperUpdateBytesEventArgs.Create(data, 0, dataLength); + m_Owner.m_DownloadAgentHelperUpdateBytesEventHandler(this, downloadAgentHelperUpdateBytesEventArgs); + ReferencePool.Release(downloadAgentHelperUpdateBytesEventArgs); + + DownloadAgentHelperUpdateLengthEventArgs downloadAgentHelperUpdateLengthEventArgs = DownloadAgentHelperUpdateLengthEventArgs.Create(dataLength); + m_Owner.m_DownloadAgentHelperUpdateLengthEventHandler(this, downloadAgentHelperUpdateLengthEventArgs); + ReferencePool.Release(downloadAgentHelperUpdateLengthEventArgs); + } + + return base.ReceiveData(data, dataLength); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/UnityWebRequestDownloadAgentHelper.DownloadHandler.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/UnityWebRequestDownloadAgentHelper.DownloadHandler.cs.meta new file mode 100644 index 0000000..738d8cb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/UnityWebRequestDownloadAgentHelper.DownloadHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fc6b62e45f7a521499fdd86e1e9071df +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/UnityWebRequestDownloadAgentHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/UnityWebRequestDownloadAgentHelper.cs new file mode 100644 index 0000000..4f01fa8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/UnityWebRequestDownloadAgentHelper.cs @@ -0,0 +1,248 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Download; +using System; +#if UNITY_5_4_OR_NEWER +using UnityEngine.Networking; +#else +using UnityEngine.Experimental.Networking; +#endif +using Utility = GameFramework.Utility; + +namespace UnityGameFramework.Runtime +{ + /// + /// 使用 UnityWebRequest 实现的下载代理辅助器。 + /// + public partial class UnityWebRequestDownloadAgentHelper : DownloadAgentHelperBase, IDisposable + { + private const int CachedBytesLength = 0x1000; + private readonly byte[] m_CachedBytes = new byte[CachedBytesLength]; + + private UnityWebRequest m_UnityWebRequest = null; + private bool m_Disposed = false; + + private EventHandler m_DownloadAgentHelperUpdateBytesEventHandler = null; + private EventHandler m_DownloadAgentHelperUpdateLengthEventHandler = null; + private EventHandler m_DownloadAgentHelperCompleteEventHandler = null; + private EventHandler m_DownloadAgentHelperErrorEventHandler = null; + + /// + /// 下载代理辅助器更新数据流事件。 + /// + public override event EventHandler DownloadAgentHelperUpdateBytes + { + add + { + m_DownloadAgentHelperUpdateBytesEventHandler += value; + } + remove + { + m_DownloadAgentHelperUpdateBytesEventHandler -= value; + } + } + + /// + /// 下载代理辅助器更新数据大小事件。 + /// + public override event EventHandler DownloadAgentHelperUpdateLength + { + add + { + m_DownloadAgentHelperUpdateLengthEventHandler += value; + } + remove + { + m_DownloadAgentHelperUpdateLengthEventHandler -= value; + } + } + + /// + /// 下载代理辅助器完成事件。 + /// + public override event EventHandler DownloadAgentHelperComplete + { + add + { + m_DownloadAgentHelperCompleteEventHandler += value; + } + remove + { + m_DownloadAgentHelperCompleteEventHandler -= value; + } + } + + /// + /// 下载代理辅助器错误事件。 + /// + public override event EventHandler DownloadAgentHelperError + { + add + { + m_DownloadAgentHelperErrorEventHandler += value; + } + remove + { + m_DownloadAgentHelperErrorEventHandler -= value; + } + } + + /// + /// 通过下载代理辅助器下载指定地址的数据。 + /// + /// 下载地址。 + /// 用户自定义数据。 + public override void Download(string downloadUri, object userData) + { + if (m_DownloadAgentHelperUpdateBytesEventHandler == null || m_DownloadAgentHelperUpdateLengthEventHandler == null || m_DownloadAgentHelperCompleteEventHandler == null || m_DownloadAgentHelperErrorEventHandler == null) + { + Log.Fatal("Download agent helper handler is invalid."); + return; + } + + m_UnityWebRequest = new UnityWebRequest(downloadUri); + m_UnityWebRequest.downloadHandler = new DownloadHandler(this); +#if UNITY_2017_2_OR_NEWER + m_UnityWebRequest.SendWebRequest(); +#else + m_UnityWebRequest.Send(); +#endif + } + + /// + /// 通过下载代理辅助器下载指定地址的数据。 + /// + /// 下载地址。 + /// 下载数据起始位置。 + /// 用户自定义数据。 + public override void Download(string downloadUri, long fromPosition, object userData) + { + if (m_DownloadAgentHelperUpdateBytesEventHandler == null || m_DownloadAgentHelperUpdateLengthEventHandler == null || m_DownloadAgentHelperCompleteEventHandler == null || m_DownloadAgentHelperErrorEventHandler == null) + { + Log.Fatal("Download agent helper handler is invalid."); + return; + } + + m_UnityWebRequest = new UnityWebRequest(downloadUri); + m_UnityWebRequest.SetRequestHeader("Range", Utility.Text.Format("bytes={0}-", fromPosition)); + m_UnityWebRequest.downloadHandler = new DownloadHandler(this); +#if UNITY_2017_2_OR_NEWER + m_UnityWebRequest.SendWebRequest(); +#else + m_UnityWebRequest.Send(); +#endif + } + + /// + /// 通过下载代理辅助器下载指定地址的数据。 + /// + /// 下载地址。 + /// 下载数据起始位置。 + /// 下载数据结束位置。 + /// 用户自定义数据。 + public override void Download(string downloadUri, long fromPosition, long toPosition, object userData) + { + if (m_DownloadAgentHelperUpdateBytesEventHandler == null || m_DownloadAgentHelperUpdateLengthEventHandler == null || m_DownloadAgentHelperCompleteEventHandler == null || m_DownloadAgentHelperErrorEventHandler == null) + { + Log.Fatal("Download agent helper handler is invalid."); + return; + } + + m_UnityWebRequest = new UnityWebRequest(downloadUri); + m_UnityWebRequest.SetRequestHeader("Range", Utility.Text.Format("bytes={0}-{1}", fromPosition, toPosition)); + m_UnityWebRequest.downloadHandler = new DownloadHandler(this); +#if UNITY_2017_2_OR_NEWER + m_UnityWebRequest.SendWebRequest(); +#else + m_UnityWebRequest.Send(); +#endif + } + + /// + /// 重置下载代理辅助器。 + /// + public override void Reset() + { + if (m_UnityWebRequest != null) + { + m_UnityWebRequest.Abort(); + m_UnityWebRequest.Dispose(); + m_UnityWebRequest = null; + } + + Array.Clear(m_CachedBytes, 0, CachedBytesLength); + } + + /// + /// 释放资源。 + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// 释放资源。 + /// + /// 释放资源标记。 + protected virtual void Dispose(bool disposing) + { + if (m_Disposed) + { + return; + } + + if (disposing) + { + if (m_UnityWebRequest != null) + { + m_UnityWebRequest.Dispose(); + m_UnityWebRequest = null; + } + } + + m_Disposed = true; + } + + private void Update() + { + if (m_UnityWebRequest == null) + { + return; + } + + if (!m_UnityWebRequest.isDone) + { + return; + } + + bool isError = false; +#if UNITY_2020_2_OR_NEWER + isError = m_UnityWebRequest.result != UnityWebRequest.Result.Success; +#elif UNITY_2017_1_OR_NEWER + isError = m_UnityWebRequest.isNetworkError || m_UnityWebRequest.isHttpError; +#else + isError = m_UnityWebRequest.isError; +#endif + if (isError) + { + DownloadAgentHelperErrorEventArgs downloadAgentHelperErrorEventArgs = DownloadAgentHelperErrorEventArgs.Create(m_UnityWebRequest.responseCode == RangeNotSatisfiableErrorCode, m_UnityWebRequest.error); + m_DownloadAgentHelperErrorEventHandler(this, downloadAgentHelperErrorEventArgs); + ReferencePool.Release(downloadAgentHelperErrorEventArgs); + } + else + { + DownloadAgentHelperCompleteEventArgs downloadAgentHelperCompleteEventArgs = DownloadAgentHelperCompleteEventArgs.Create((long)m_UnityWebRequest.downloadedBytes); + m_DownloadAgentHelperCompleteEventHandler(this, downloadAgentHelperCompleteEventArgs); + ReferencePool.Release(downloadAgentHelperCompleteEventArgs); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/UnityWebRequestDownloadAgentHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/UnityWebRequestDownloadAgentHelper.cs.meta new file mode 100644 index 0000000..c595a0a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/UnityWebRequestDownloadAgentHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a19b280dcc736764fb78ce804a6c4d88 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/WWWDownloadAgentHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/WWWDownloadAgentHelper.cs new file mode 100644 index 0000000..8daccc1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/WWWDownloadAgentHelper.cs @@ -0,0 +1,246 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +#if !UNITY_2018_3_OR_NEWER + +using GameFramework; +using GameFramework.Download; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// WWW 下载代理辅助器。 + /// + public class WWWDownloadAgentHelper : DownloadAgentHelperBase, IDisposable + { + private WWW m_WWW = null; + private int m_LastDownloadedSize = 0; + private bool m_Disposed = false; + + private EventHandler m_DownloadAgentHelperUpdateBytesEventHandler = null; + private EventHandler m_DownloadAgentHelperUpdateLengthEventHandler = null; + private EventHandler m_DownloadAgentHelperCompleteEventHandler = null; + private EventHandler m_DownloadAgentHelperErrorEventHandler = null; + + /// + /// 下载代理辅助器更新数据流事件。 + /// + public override event EventHandler DownloadAgentHelperUpdateBytes + { + add + { + m_DownloadAgentHelperUpdateBytesEventHandler += value; + } + remove + { + m_DownloadAgentHelperUpdateBytesEventHandler -= value; + } + } + + /// + /// 下载代理辅助器更新数据大小事件。 + /// + public override event EventHandler DownloadAgentHelperUpdateLength + { + add + { + m_DownloadAgentHelperUpdateLengthEventHandler += value; + } + remove + { + m_DownloadAgentHelperUpdateLengthEventHandler -= value; + } + } + + /// + /// 下载代理辅助器完成事件。 + /// + public override event EventHandler DownloadAgentHelperComplete + { + add + { + m_DownloadAgentHelperCompleteEventHandler += value; + } + remove + { + m_DownloadAgentHelperCompleteEventHandler -= value; + } + } + + /// + /// 下载代理辅助器错误事件。 + /// + public override event EventHandler DownloadAgentHelperError + { + add + { + m_DownloadAgentHelperErrorEventHandler += value; + } + remove + { + m_DownloadAgentHelperErrorEventHandler -= value; + } + } + + /// + /// 通过下载代理辅助器下载指定地址的数据。 + /// + /// 下载地址。 + /// 用户自定义数据。 + public override void Download(string downloadUri, object userData) + { + if (m_DownloadAgentHelperUpdateBytesEventHandler == null || m_DownloadAgentHelperUpdateLengthEventHandler == null || m_DownloadAgentHelperCompleteEventHandler == null || m_DownloadAgentHelperErrorEventHandler == null) + { + Log.Fatal("Download agent helper handler is invalid."); + return; + } + + m_WWW = new WWW(downloadUri); + } + + /// + /// 通过下载代理辅助器下载指定地址的数据。 + /// + /// 下载地址。 + /// 下载数据起始位置。 + /// 用户自定义数据。 + public override void Download(string downloadUri, long fromPosition, object userData) + { + if (m_DownloadAgentHelperUpdateBytesEventHandler == null || m_DownloadAgentHelperUpdateLengthEventHandler == null || m_DownloadAgentHelperCompleteEventHandler == null || m_DownloadAgentHelperErrorEventHandler == null) + { + Log.Fatal("Download agent helper handler is invalid."); + return; + } + + Dictionary header = new Dictionary + { + { "Range", Utility.Text.Format("bytes={0}-", fromPosition) } + }; + + m_WWW = new WWW(downloadUri, null, header); + } + + /// + /// 通过下载代理辅助器下载指定地址的数据。 + /// + /// 下载地址。 + /// 下载数据起始位置。 + /// 下载数据结束位置。 + /// 用户自定义数据。 + public override void Download(string downloadUri, long fromPosition, long toPosition, object userData) + { + if (m_DownloadAgentHelperUpdateBytesEventHandler == null || m_DownloadAgentHelperUpdateLengthEventHandler == null || m_DownloadAgentHelperCompleteEventHandler == null || m_DownloadAgentHelperErrorEventHandler == null) + { + Log.Fatal("Download agent helper handler is invalid."); + return; + } + + Dictionary header = new Dictionary + { + { "Range", Utility.Text.Format("bytes={0}-{1}", fromPosition, toPosition) } + }; + + m_WWW = new WWW(downloadUri, null, header); + } + + /// + /// 重置下载代理辅助器。 + /// + public override void Reset() + { + if (m_WWW != null) + { + m_WWW.Dispose(); + m_WWW = null; + } + + m_LastDownloadedSize = 0; + } + + /// + /// 释放资源。 + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// 释放资源。 + /// + /// 释放资源标记。 + protected virtual void Dispose(bool disposing) + { + if (m_Disposed) + { + return; + } + + if (disposing) + { + if (m_WWW != null) + { + m_WWW.Dispose(); + m_WWW = null; + } + } + + m_Disposed = true; + } + + private void Update() + { + if (m_WWW == null) + { + return; + } + + int deltaLength = m_WWW.bytesDownloaded - m_LastDownloadedSize; + if (deltaLength > 0) + { + m_LastDownloadedSize = m_WWW.bytesDownloaded; + DownloadAgentHelperUpdateLengthEventArgs downloadAgentHelperUpdateLengthEventArgs = DownloadAgentHelperUpdateLengthEventArgs.Create(deltaLength); + m_DownloadAgentHelperUpdateLengthEventHandler(this, downloadAgentHelperUpdateLengthEventArgs); + ReferencePool.Release(downloadAgentHelperUpdateLengthEventArgs); + } + + if (m_WWW == null) + { + return; + } + + if (!m_WWW.isDone) + { + return; + } + + if (!string.IsNullOrEmpty(m_WWW.error)) + { + DownloadAgentHelperErrorEventArgs dodwnloadAgentHelperErrorEventArgs = DownloadAgentHelperErrorEventArgs.Create(m_WWW.error.StartsWith(RangeNotSatisfiableErrorCode.ToString(), StringComparison.Ordinal), m_WWW.error); + m_DownloadAgentHelperErrorEventHandler(this, dodwnloadAgentHelperErrorEventArgs); + ReferencePool.Release(dodwnloadAgentHelperErrorEventArgs); + } + else + { + byte[] bytes = m_WWW.bytes; + DownloadAgentHelperUpdateBytesEventArgs downloadAgentHelperUpdateBytesEventArgs = DownloadAgentHelperUpdateBytesEventArgs.Create(bytes, 0, bytes.Length); + m_DownloadAgentHelperUpdateBytesEventHandler(this, downloadAgentHelperUpdateBytesEventArgs); + ReferencePool.Release(downloadAgentHelperUpdateBytesEventArgs); + + DownloadAgentHelperCompleteEventArgs downloadAgentHelperCompleteEventArgs = DownloadAgentHelperCompleteEventArgs.Create(bytes.LongLength); + m_DownloadAgentHelperCompleteEventHandler(this, downloadAgentHelperCompleteEventArgs); + ReferencePool.Release(downloadAgentHelperCompleteEventArgs); + } + } + } +} + +#endif diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/WWWDownloadAgentHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/WWWDownloadAgentHelper.cs.meta new file mode 100644 index 0000000..67dc31b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Download/WWWDownloadAgentHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 30217a4100363014a9c8c671b5848a61 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity.meta new file mode 100644 index 0000000..633fe4e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c847fbba6525ec643a5fbb113b54eaf0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/AttachEntityInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/AttachEntityInfo.cs new file mode 100644 index 0000000..c8e3fff --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/AttachEntityInfo.cs @@ -0,0 +1,54 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + internal sealed class AttachEntityInfo : IReference + { + private Transform m_ParentTransform; + private object m_UserData; + + public AttachEntityInfo() + { + m_ParentTransform = null; + m_UserData = null; + } + + public Transform ParentTransform + { + get + { + return m_ParentTransform; + } + } + + public object UserData + { + get + { + return m_UserData; + } + } + + public static AttachEntityInfo Create(Transform parentTransform, object userData) + { + AttachEntityInfo attachEntityInfo = ReferencePool.Acquire(); + attachEntityInfo.m_ParentTransform = parentTransform; + attachEntityInfo.m_UserData = userData; + return attachEntityInfo; + } + + public void Clear() + { + m_ParentTransform = null; + m_UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/AttachEntityInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/AttachEntityInfo.cs.meta new file mode 100644 index 0000000..15fee8c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/AttachEntityInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93ee8133074b5234da08e1308a55efb2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/DefaultEntityGroupHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/DefaultEntityGroupHelper.cs new file mode 100644 index 0000000..cb123db --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/DefaultEntityGroupHelper.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认实体组辅助器。 + /// + public class DefaultEntityGroupHelper : EntityGroupHelperBase + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/DefaultEntityGroupHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/DefaultEntityGroupHelper.cs.meta new file mode 100644 index 0000000..c56b639 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/DefaultEntityGroupHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2eae0b22de94ba442b482bff7fab17ff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/DefaultEntityHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/DefaultEntityHelper.cs new file mode 100644 index 0000000..a22e066 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/DefaultEntityHelper.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Entity; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认实体辅助器。 + /// + public class DefaultEntityHelper : EntityHelperBase + { + private ResourceComponent m_ResourceComponent = null; + + /// + /// 实例化实体。 + /// + /// 要实例化的实体资源。 + /// 实例化后的实体。 + public override object InstantiateEntity(object entityAsset) + { + return Instantiate((Object)entityAsset); + } + + /// + /// 创建实体。 + /// + /// 实体实例。 + /// 实体所属的实体组。 + /// 用户自定义数据。 + /// 实体。 + public override IEntity CreateEntity(object entityInstance, IEntityGroup entityGroup, object userData) + { + GameObject gameObject = entityInstance as GameObject; + if (gameObject == null) + { + Log.Error("Entity instance is invalid."); + return null; + } + + Transform transform = gameObject.transform; + transform.SetParent(((MonoBehaviour)entityGroup.Helper).transform); + + return gameObject.GetOrAddComponent(); + } + + /// + /// 释放实体。 + /// + /// 要释放的实体资源。 + /// 要释放的实体实例。 + public override void ReleaseEntity(object entityAsset, object entityInstance) + { + m_ResourceComponent.UnloadAsset(entityAsset); + Destroy((Object)entityInstance); + } + + private void Start() + { + m_ResourceComponent = GameEntry.GetComponent(); + if (m_ResourceComponent == null) + { + Log.Fatal("Resource component is invalid."); + return; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/DefaultEntityHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/DefaultEntityHelper.cs.meta new file mode 100644 index 0000000..76a3eea --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/DefaultEntityHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5b0ffb61c68e948498fa57c1901f0001 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/Entity.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/Entity.cs new file mode 100644 index 0000000..9a3e320 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/Entity.cs @@ -0,0 +1,280 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Entity; +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 实体。 + /// + public sealed class Entity : MonoBehaviour, IEntity + { + private int m_Id; + private string m_EntityAssetName; + private IEntityGroup m_EntityGroup; + private EntityLogic m_EntityLogic; + + /// + /// 获取实体编号。 + /// + public int Id + { + get + { + return m_Id; + } + } + + /// + /// 获取实体资源名称。 + /// + public string EntityAssetName + { + get + { + return m_EntityAssetName; + } + } + + /// + /// 获取实体实例。 + /// + public object Handle + { + get + { + return gameObject; + } + } + + /// + /// 获取实体所属的实体组。 + /// + public IEntityGroup EntityGroup + { + get + { + return m_EntityGroup; + } + } + + /// + /// 获取实体逻辑。 + /// + public EntityLogic Logic + { + get + { + return m_EntityLogic; + } + } + + /// + /// 实体初始化。 + /// + /// 实体编号。 + /// 实体资源名称。 + /// 实体所属的实体组。 + /// 是否是新实例。 + /// 用户自定义数据。 + public void OnInit(int entityId, string entityAssetName, IEntityGroup entityGroup, bool isNewInstance, object userData) + { + m_Id = entityId; + m_EntityAssetName = entityAssetName; + if (isNewInstance) + { + m_EntityGroup = entityGroup; + } + else if (m_EntityGroup != entityGroup) + { + Log.Error("Entity group is inconsistent for non-new-instance entity."); + return; + } + + ShowEntityInfo showEntityInfo = (ShowEntityInfo)userData; + Type entityLogicType = showEntityInfo.EntityLogicType; + if (entityLogicType == null) + { + Log.Error("Entity logic type is invalid."); + return; + } + + if (m_EntityLogic != null) + { + if (m_EntityLogic.GetType() == entityLogicType) + { + m_EntityLogic.enabled = true; + return; + } + + Destroy(m_EntityLogic); + m_EntityLogic = null; + } + + m_EntityLogic = gameObject.AddComponent(entityLogicType) as EntityLogic; + if (m_EntityLogic == null) + { + Log.Error("Entity '{0}' can not add entity logic.", entityAssetName); + return; + } + + try + { + m_EntityLogic.OnInit(showEntityInfo.UserData); + } + catch (Exception exception) + { + Log.Error("Entity '[{0}]{1}' OnInit with exception '{2}'.", m_Id, m_EntityAssetName, exception); + } + } + + /// + /// 实体回收。 + /// + public void OnRecycle() + { + try + { + m_EntityLogic.OnRecycle(); + m_EntityLogic.enabled = false; + } + catch (Exception exception) + { + Log.Error("Entity '[{0}]{1}' OnRecycle with exception '{2}'.", m_Id, m_EntityAssetName, exception); + } + + m_Id = 0; + } + + /// + /// 实体显示。 + /// + /// 用户自定义数据。 + public void OnShow(object userData) + { + ShowEntityInfo showEntityInfo = (ShowEntityInfo)userData; + try + { + m_EntityLogic.OnShow(showEntityInfo.UserData); + } + catch (Exception exception) + { + Log.Error("Entity '[{0}]{1}' OnShow with exception '{2}'.", m_Id, m_EntityAssetName, exception); + } + } + + /// + /// 实体隐藏。 + /// + /// 是否是关闭实体管理器时触发。 + /// 用户自定义数据。 + public void OnHide(bool isShutdown, object userData) + { + try + { + m_EntityLogic.OnHide(isShutdown, userData); + } + catch (Exception exception) + { + Log.Error("Entity '[{0}]{1}' OnHide with exception '{2}'.", m_Id, m_EntityAssetName, exception); + } + } + + /// + /// 实体附加子实体。 + /// + /// 附加的子实体。 + /// 用户自定义数据。 + public void OnAttached(IEntity childEntity, object userData) + { + AttachEntityInfo attachEntityInfo = (AttachEntityInfo)userData; + try + { + m_EntityLogic.OnAttached(((Entity)childEntity).Logic, attachEntityInfo.ParentTransform, attachEntityInfo.UserData); + } + catch (Exception exception) + { + Log.Error("Entity '[{0}]{1}' OnAttached with exception '{2}'.", m_Id, m_EntityAssetName, exception); + } + } + + /// + /// 实体解除子实体。 + /// + /// 解除的子实体。 + /// 用户自定义数据。 + public void OnDetached(IEntity childEntity, object userData) + { + try + { + m_EntityLogic.OnDetached(((Entity)childEntity).Logic, userData); + } + catch (Exception exception) + { + Log.Error("Entity '[{0}]{1}' OnDetached with exception '{2}'.", m_Id, m_EntityAssetName, exception); + } + } + + /// + /// 实体附加子实体。 + /// + /// 被附加的父实体。 + /// 用户自定义数据。 + public void OnAttachTo(IEntity parentEntity, object userData) + { + AttachEntityInfo attachEntityInfo = (AttachEntityInfo)userData; + try + { + m_EntityLogic.OnAttachTo(((Entity)parentEntity).Logic, attachEntityInfo.ParentTransform, attachEntityInfo.UserData); + } + catch (Exception exception) + { + Log.Error("Entity '[{0}]{1}' OnAttachTo with exception '{2}'.", m_Id, m_EntityAssetName, exception); + } + + ReferencePool.Release(attachEntityInfo); + } + + /// + /// 实体解除子实体。 + /// + /// 被解除的父实体。 + /// 用户自定义数据。 + public void OnDetachFrom(IEntity parentEntity, object userData) + { + try + { + m_EntityLogic.OnDetachFrom(((Entity)parentEntity).Logic, userData); + } + catch (Exception exception) + { + Log.Error("Entity '[{0}]{1}' OnDetachFrom with exception '{2}'.", m_Id, m_EntityAssetName, exception); + } + } + + /// + /// 实体轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + try + { + m_EntityLogic.OnUpdate(elapseSeconds, realElapseSeconds); + } + catch (Exception exception) + { + Log.Error("Entity '[{0}]{1}' OnUpdate with exception '{2}'.", m_Id, m_EntityAssetName, exception); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/Entity.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/Entity.cs.meta new file mode 100644 index 0000000..85e287d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/Entity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bac1e67b934ef0944b6de46554cf5042 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityComponent.EntityGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityComponent.EntityGroup.cs new file mode 100644 index 0000000..1ffe103 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityComponent.EntityGroup.cs @@ -0,0 +1,74 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class EntityComponent : GameFrameworkComponent + { + [Serializable] + private sealed class EntityGroup + { + [SerializeField] + private string m_Name = null; + + [SerializeField] + private float m_InstanceAutoReleaseInterval = 60f; + + [SerializeField] + private int m_InstanceCapacity = 16; + + [SerializeField] + private float m_InstanceExpireTime = 60f; + + [SerializeField] + private int m_InstancePriority = 0; + + public string Name + { + get + { + return m_Name; + } + } + + public float InstanceAutoReleaseInterval + { + get + { + return m_InstanceAutoReleaseInterval; + } + } + + public int InstanceCapacity + { + get + { + return m_InstanceCapacity; + } + } + + public float InstanceExpireTime + { + get + { + return m_InstanceExpireTime; + } + } + + public int InstancePriority + { + get + { + return m_InstancePriority; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityComponent.EntityGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityComponent.EntityGroup.cs.meta new file mode 100644 index 0000000..c12b4fb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityComponent.EntityGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d93d1ae840acb2f449ac5f5cad2d0259 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityComponent.cs new file mode 100644 index 0000000..6df3130 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityComponent.cs @@ -0,0 +1,1146 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Entity; +using GameFramework.ObjectPool; +using GameFramework.Resource; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 实体组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Entity")] + public sealed partial class EntityComponent : GameFrameworkComponent + { + private const int DefaultPriority = 0; + + private IEntityManager m_EntityManager = null; + private EventComponent m_EventComponent = null; + + private readonly List m_InternalEntityResults = new List(); + + [SerializeField] + private bool m_EnableShowEntityUpdateEvent = false; + + [SerializeField] + private bool m_EnableShowEntityDependencyAssetEvent = false; + + [SerializeField] + private Transform m_InstanceRoot = null; + + [SerializeField] + private string m_EntityHelperTypeName = "UnityGameFramework.Runtime.DefaultEntityHelper"; + + [SerializeField] + private EntityHelperBase m_CustomEntityHelper = null; + + [SerializeField] + private string m_EntityGroupHelperTypeName = "UnityGameFramework.Runtime.DefaultEntityGroupHelper"; + + [SerializeField] + private EntityGroupHelperBase m_CustomEntityGroupHelper = null; + + [SerializeField] + private EntityGroup[] m_EntityGroups = null; + + /// + /// 获取实体数量。 + /// + public int EntityCount + { + get + { + return m_EntityManager.EntityCount; + } + } + + /// + /// 获取实体组数量。 + /// + public int EntityGroupCount + { + get + { + return m_EntityManager.EntityGroupCount; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_EntityManager = GameFrameworkEntry.GetModule(); + if (m_EntityManager == null) + { + Log.Fatal("Entity manager is invalid."); + return; + } + + m_EntityManager.ShowEntitySuccess += OnShowEntitySuccess; + m_EntityManager.ShowEntityFailure += OnShowEntityFailure; + + if (m_EnableShowEntityUpdateEvent) + { + m_EntityManager.ShowEntityUpdate += OnShowEntityUpdate; + } + + if (m_EnableShowEntityDependencyAssetEvent) + { + m_EntityManager.ShowEntityDependencyAsset += OnShowEntityDependencyAsset; + } + + m_EntityManager.HideEntityComplete += OnHideEntityComplete; + } + + private void Start() + { + BaseComponent baseComponent = GameEntry.GetComponent(); + if (baseComponent == null) + { + Log.Fatal("Base component is invalid."); + return; + } + + m_EventComponent = GameEntry.GetComponent(); + if (m_EventComponent == null) + { + Log.Fatal("Event component is invalid."); + return; + } + + if (baseComponent.EditorResourceMode) + { + m_EntityManager.SetResourceManager(baseComponent.EditorResourceHelper); + } + else + { + m_EntityManager.SetResourceManager(GameFrameworkEntry.GetModule()); + } + + m_EntityManager.SetObjectPoolManager(GameFrameworkEntry.GetModule()); + + EntityHelperBase entityHelper = Helper.CreateHelper(m_EntityHelperTypeName, m_CustomEntityHelper); + if (entityHelper == null) + { + Log.Error("Can not create entity helper."); + return; + } + + entityHelper.name = "Entity Helper"; + Transform transform = entityHelper.transform; + transform.SetParent(this.transform); + transform.localScale = Vector3.one; + + m_EntityManager.SetEntityHelper(entityHelper); + + if (m_InstanceRoot == null) + { + m_InstanceRoot = new GameObject("Entity Instances").transform; + m_InstanceRoot.SetParent(gameObject.transform); + m_InstanceRoot.localScale = Vector3.one; + } + + for (int i = 0; i < m_EntityGroups.Length; i++) + { + if (!AddEntityGroup(m_EntityGroups[i].Name, m_EntityGroups[i].InstanceAutoReleaseInterval, m_EntityGroups[i].InstanceCapacity, m_EntityGroups[i].InstanceExpireTime, m_EntityGroups[i].InstancePriority)) + { + Log.Warning("Add entity group '{0}' failure.", m_EntityGroups[i].Name); + continue; + } + } + } + + /// + /// 是否存在实体组。 + /// + /// 实体组名称。 + /// 是否存在实体组。 + public bool HasEntityGroup(string entityGroupName) + { + return m_EntityManager.HasEntityGroup(entityGroupName); + } + + /// + /// 获取实体组。 + /// + /// 实体组名称。 + /// 要获取的实体组。 + public IEntityGroup GetEntityGroup(string entityGroupName) + { + return m_EntityManager.GetEntityGroup(entityGroupName); + } + + /// + /// 获取所有实体组。 + /// + /// 所有实体组。 + public IEntityGroup[] GetAllEntityGroups() + { + return m_EntityManager.GetAllEntityGroups(); + } + + /// + /// 获取所有实体组。 + /// + /// 所有实体组。 + public void GetAllEntityGroups(List results) + { + m_EntityManager.GetAllEntityGroups(results); + } + + /// + /// 增加实体组。 + /// + /// 实体组名称。 + /// 实体实例对象池自动释放可释放对象的间隔秒数。 + /// 实体实例对象池容量。 + /// 实体实例对象池对象过期秒数。 + /// 实体实例对象池的优先级。 + /// 是否增加实体组成功。 + public bool AddEntityGroup(string entityGroupName, float instanceAutoReleaseInterval, int instanceCapacity, float instanceExpireTime, int instancePriority) + { + if (m_EntityManager.HasEntityGroup(entityGroupName)) + { + return false; + } + + EntityGroupHelperBase entityGroupHelper = Helper.CreateHelper(m_EntityGroupHelperTypeName, m_CustomEntityGroupHelper, EntityGroupCount); + if (entityGroupHelper == null) + { + Log.Error("Can not create entity group helper."); + return false; + } + + entityGroupHelper.name = Utility.Text.Format("Entity Group - {0}", entityGroupName); + Transform transform = entityGroupHelper.transform; + transform.SetParent(m_InstanceRoot); + transform.localScale = Vector3.one; + + return m_EntityManager.AddEntityGroup(entityGroupName, instanceAutoReleaseInterval, instanceCapacity, instanceExpireTime, instancePriority, entityGroupHelper); + } + + /// + /// 是否存在实体。 + /// + /// 实体编号。 + /// 是否存在实体。 + public bool HasEntity(int entityId) + { + return m_EntityManager.HasEntity(entityId); + } + + /// + /// 是否存在实体。 + /// + /// 实体资源名称。 + /// 是否存在实体。 + public bool HasEntity(string entityAssetName) + { + return m_EntityManager.HasEntity(entityAssetName); + } + + /// + /// 获取实体。 + /// + /// 实体编号。 + /// 实体。 + public Entity GetEntity(int entityId) + { + return (Entity)m_EntityManager.GetEntity(entityId); + } + + /// + /// 获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + public Entity GetEntity(string entityAssetName) + { + return (Entity)m_EntityManager.GetEntity(entityAssetName); + } + + /// + /// 获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + public Entity[] GetEntities(string entityAssetName) + { + IEntity[] entities = m_EntityManager.GetEntities(entityAssetName); + Entity[] entityImpls = new Entity[entities.Length]; + for (int i = 0; i < entities.Length; i++) + { + entityImpls[i] = (Entity)entities[i]; + } + + return entityImpls; + } + + /// + /// 获取实体。 + /// + /// 实体资源名称。 + /// 要获取的实体。 + public void GetEntities(string entityAssetName, List results) + { + if (results == null) + { + Log.Error("Results is invalid."); + return; + } + + results.Clear(); + m_EntityManager.GetEntities(entityAssetName, m_InternalEntityResults); + foreach (IEntity entity in m_InternalEntityResults) + { + results.Add((Entity)entity); + } + } + + /// + /// 获取所有已加载的实体。 + /// + /// 所有已加载的实体。 + public Entity[] GetAllLoadedEntities() + { + IEntity[] entities = m_EntityManager.GetAllLoadedEntities(); + Entity[] entityImpls = new Entity[entities.Length]; + for (int i = 0; i < entities.Length; i++) + { + entityImpls[i] = (Entity)entities[i]; + } + + return entityImpls; + } + + /// + /// 获取所有已加载的实体。 + /// + /// 所有已加载的实体。 + public void GetAllLoadedEntities(List results) + { + if (results == null) + { + Log.Error("Results is invalid."); + return; + } + + results.Clear(); + m_EntityManager.GetAllLoadedEntities(m_InternalEntityResults); + foreach (IEntity entity in m_InternalEntityResults) + { + results.Add((Entity)entity); + } + } + + /// + /// 获取所有正在加载实体的编号。 + /// + /// 所有正在加载实体的编号。 + public int[] GetAllLoadingEntityIds() + { + return m_EntityManager.GetAllLoadingEntityIds(); + } + + /// + /// 获取所有正在加载实体的编号。 + /// + /// 所有正在加载实体的编号。 + public void GetAllLoadingEntityIds(List results) + { + m_EntityManager.GetAllLoadingEntityIds(results); + } + + /// + /// 是否正在加载实体。 + /// + /// 实体编号。 + /// 是否正在加载实体。 + public bool IsLoadingEntity(int entityId) + { + return m_EntityManager.IsLoadingEntity(entityId); + } + + /// + /// 是否是合法的实体。 + /// + /// 实体。 + /// 实体是否合法。 + public bool IsValidEntity(Entity entity) + { + return m_EntityManager.IsValidEntity(entity); + } + + /// + /// 显示实体。 + /// + /// 实体逻辑类型。 + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + public void ShowEntity(int entityId, string entityAssetName, string entityGroupName) where T : EntityLogic + { + ShowEntity(entityId, typeof(T), entityAssetName, entityGroupName, DefaultPriority, null); + } + + /// + /// 显示实体。 + /// + /// 实体编号。 + /// 实体逻辑类型。 + /// 实体资源名称。 + /// 实体组名称。 + public void ShowEntity(int entityId, Type entityLogicType, string entityAssetName, string entityGroupName) + { + ShowEntity(entityId, entityLogicType, entityAssetName, entityGroupName, DefaultPriority, null); + } + + /// + /// 显示实体。 + /// + /// 实体逻辑类型。 + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + /// 加载实体资源的优先级。 + public void ShowEntity(int entityId, string entityAssetName, string entityGroupName, int priority) where T : EntityLogic + { + ShowEntity(entityId, typeof(T), entityAssetName, entityGroupName, priority, null); + } + + /// + /// 显示实体。 + /// + /// 实体编号。 + /// 实体逻辑类型。 + /// 实体资源名称。 + /// 实体组名称。 + /// 加载实体资源的优先级。 + public void ShowEntity(int entityId, Type entityLogicType, string entityAssetName, string entityGroupName, int priority) + { + ShowEntity(entityId, entityLogicType, entityAssetName, entityGroupName, priority, null); + } + + /// + /// 显示实体。 + /// + /// 实体逻辑类型。 + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + /// 用户自定义数据。 + public void ShowEntity(int entityId, string entityAssetName, string entityGroupName, object userData) where T : EntityLogic + { + ShowEntity(entityId, typeof(T), entityAssetName, entityGroupName, DefaultPriority, userData); + } + + /// + /// 显示实体。 + /// + /// 实体编号。 + /// 实体逻辑类型。 + /// 实体资源名称。 + /// 实体组名称。 + /// 用户自定义数据。 + public void ShowEntity(int entityId, Type entityLogicType, string entityAssetName, string entityGroupName, object userData) + { + ShowEntity(entityId, entityLogicType, entityAssetName, entityGroupName, DefaultPriority, userData); + } + + /// + /// 显示实体。 + /// + /// 实体逻辑类型。 + /// 实体编号。 + /// 实体资源名称。 + /// 实体组名称。 + /// 加载实体资源的优先级。 + /// 用户自定义数据。 + public void ShowEntity(int entityId, string entityAssetName, string entityGroupName, int priority, object userData) where T : EntityLogic + { + ShowEntity(entityId, typeof(T), entityAssetName, entityGroupName, priority, userData); + } + + /// + /// 显示实体。 + /// + /// 实体编号。 + /// 实体逻辑类型。 + /// 实体资源名称。 + /// 实体组名称。 + /// 加载实体资源的优先级。 + /// 用户自定义数据。 + public void ShowEntity(int entityId, Type entityLogicType, string entityAssetName, string entityGroupName, int priority, object userData) + { + if (entityLogicType == null) + { + Log.Error("Entity type is invalid."); + return; + } + + m_EntityManager.ShowEntity(entityId, entityAssetName, entityGroupName, priority, ShowEntityInfo.Create(entityLogicType, userData)); + } + + /// + /// 隐藏实体。 + /// + /// 实体编号。 + public void HideEntity(int entityId) + { + m_EntityManager.HideEntity(entityId); + } + + /// + /// 隐藏实体。 + /// + /// 实体编号。 + /// 用户自定义数据。 + public void HideEntity(int entityId, object userData) + { + m_EntityManager.HideEntity(entityId, userData); + } + + /// + /// 隐藏实体。 + /// + /// 实体。 + public void HideEntity(Entity entity) + { + m_EntityManager.HideEntity(entity); + } + + /// + /// 隐藏实体。 + /// + /// 实体。 + /// 用户自定义数据。 + public void HideEntity(Entity entity, object userData) + { + m_EntityManager.HideEntity(entity, userData); + } + + /// + /// 隐藏所有已加载的实体。 + /// + public void HideAllLoadedEntities() + { + m_EntityManager.HideAllLoadedEntities(); + } + + /// + /// 隐藏所有已加载的实体。 + /// + /// 用户自定义数据。 + public void HideAllLoadedEntities(object userData) + { + m_EntityManager.HideAllLoadedEntities(userData); + } + + /// + /// 隐藏所有正在加载的实体。 + /// + public void HideAllLoadingEntities() + { + m_EntityManager.HideAllLoadingEntities(); + } + + /// + /// 获取父实体。 + /// + /// 要获取父实体的子实体的实体编号。 + /// 子实体的父实体。 + public Entity GetParentEntity(int childEntityId) + { + return (Entity)m_EntityManager.GetParentEntity(childEntityId); + } + + /// + /// 获取父实体。 + /// + /// 要获取父实体的子实体。 + /// 子实体的父实体。 + public Entity GetParentEntity(Entity childEntity) + { + return (Entity)m_EntityManager.GetParentEntity(childEntity); + } + + /// + /// 获取子实体数量。 + /// + /// 要获取子实体数量的父实体的实体编号。 + /// 子实体数量。 + public int GetChildEntityCount(int parentEntityId) + { + return m_EntityManager.GetChildEntityCount(parentEntityId); + } + + /// + /// 获取子实体。 + /// + /// 要获取子实体的父实体的实体编号。 + /// 子实体。 + public Entity GetChildEntity(int parentEntityId) + { + return (Entity)m_EntityManager.GetChildEntity(parentEntityId); + } + + /// + /// 获取子实体。 + /// + /// 要获取子实体的父实体。 + /// 子实体。 + public Entity GetChildEntity(IEntity parentEntity) + { + return (Entity)m_EntityManager.GetChildEntity(parentEntity); + } + + /// + /// 获取所有子实体。 + /// + /// 要获取所有子实体的父实体的实体编号。 + /// 所有子实体。 + public Entity[] GetChildEntities(int parentEntityId) + { + IEntity[] entities = m_EntityManager.GetChildEntities(parentEntityId); + Entity[] entityImpls = new Entity[entities.Length]; + for (int i = 0; i < entities.Length; i++) + { + entityImpls[i] = (Entity)entities[i]; + } + + return entityImpls; + } + + /// + /// 获取所有子实体。 + /// + /// 要获取所有子实体的父实体的实体编号。 + /// 所有子实体。 + public void GetChildEntities(int parentEntityId, List results) + { + if (results == null) + { + Log.Error("Results is invalid."); + return; + } + + results.Clear(); + m_EntityManager.GetChildEntities(parentEntityId, m_InternalEntityResults); + foreach (IEntity entity in m_InternalEntityResults) + { + results.Add((Entity)entity); + } + } + + /// + /// 获取所有子实体。 + /// + /// 要获取所有子实体的父实体。 + /// 所有子实体。 + public Entity[] GetChildEntities(Entity parentEntity) + { + IEntity[] entities = m_EntityManager.GetChildEntities(parentEntity); + Entity[] entityImpls = new Entity[entities.Length]; + for (int i = 0; i < entities.Length; i++) + { + entityImpls[i] = (Entity)entities[i]; + } + + return entityImpls; + } + + /// + /// 获取所有子实体。 + /// + /// 要获取所有子实体的父实体。 + /// 所有子实体。 + public void GetChildEntities(IEntity parentEntity, List results) + { + if (results == null) + { + Log.Error("Results is invalid."); + return; + } + + results.Clear(); + m_EntityManager.GetChildEntities(parentEntity, m_InternalEntityResults); + foreach (IEntity entity in m_InternalEntityResults) + { + results.Add((Entity)entity); + } + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体的实体编号。 + public void AttachEntity(int childEntityId, int parentEntityId) + { + AttachEntity(GetEntity(childEntityId), GetEntity(parentEntityId), string.Empty, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体。 + public void AttachEntity(int childEntityId, Entity parentEntity) + { + AttachEntity(GetEntity(childEntityId), parentEntity, string.Empty, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体的实体编号。 + public void AttachEntity(Entity childEntity, int parentEntityId) + { + AttachEntity(childEntity, GetEntity(parentEntityId), string.Empty, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体。 + public void AttachEntity(Entity childEntity, Entity parentEntity) + { + AttachEntity(childEntity, parentEntity, string.Empty, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体的实体编号。 + /// 相对于被附加父实体的位置。 + public void AttachEntity(int childEntityId, int parentEntityId, string parentTransformPath) + { + AttachEntity(GetEntity(childEntityId), GetEntity(parentEntityId), parentTransformPath, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体。 + /// 相对于被附加父实体的位置。 + public void AttachEntity(int childEntityId, Entity parentEntity, string parentTransformPath) + { + AttachEntity(GetEntity(childEntityId), parentEntity, parentTransformPath, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体的实体编号。 + /// 相对于被附加父实体的位置。 + public void AttachEntity(Entity childEntity, int parentEntityId, string parentTransformPath) + { + AttachEntity(childEntity, GetEntity(parentEntityId), parentTransformPath, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体。 + /// 相对于被附加父实体的位置。 + public void AttachEntity(Entity childEntity, Entity parentEntity, string parentTransformPath) + { + AttachEntity(childEntity, parentEntity, parentTransformPath, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体的实体编号。 + /// 相对于被附加父实体的位置。 + public void AttachEntity(int childEntityId, int parentEntityId, Transform parentTransform) + { + AttachEntity(GetEntity(childEntityId), GetEntity(parentEntityId), parentTransform, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体。 + /// 相对于被附加父实体的位置。 + public void AttachEntity(int childEntityId, Entity parentEntity, Transform parentTransform) + { + AttachEntity(GetEntity(childEntityId), parentEntity, parentTransform, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体的实体编号。 + /// 相对于被附加父实体的位置。 + public void AttachEntity(Entity childEntity, int parentEntityId, Transform parentTransform) + { + AttachEntity(childEntity, GetEntity(parentEntityId), parentTransform, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体。 + /// 相对于被附加父实体的位置。 + public void AttachEntity(Entity childEntity, Entity parentEntity, Transform parentTransform) + { + AttachEntity(childEntity, parentEntity, parentTransform, null); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体的实体编号。 + /// 用户自定义数据。 + public void AttachEntity(int childEntityId, int parentEntityId, object userData) + { + AttachEntity(GetEntity(childEntityId), GetEntity(parentEntityId), string.Empty, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体。 + /// 用户自定义数据。 + public void AttachEntity(int childEntityId, Entity parentEntity, object userData) + { + AttachEntity(GetEntity(childEntityId), parentEntity, string.Empty, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体的实体编号。 + /// 用户自定义数据。 + public void AttachEntity(Entity childEntity, int parentEntityId, object userData) + { + AttachEntity(childEntity, GetEntity(parentEntityId), string.Empty, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体。 + /// 用户自定义数据。 + public void AttachEntity(Entity childEntity, Entity parentEntity, object userData) + { + AttachEntity(childEntity, parentEntity, string.Empty, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体的实体编号。 + /// 相对于被附加父实体的位置。 + /// 用户自定义数据。 + public void AttachEntity(int childEntityId, int parentEntityId, string parentTransformPath, object userData) + { + AttachEntity(GetEntity(childEntityId), GetEntity(parentEntityId), parentTransformPath, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体。 + /// 相对于被附加父实体的位置。 + /// 用户自定义数据。 + public void AttachEntity(int childEntityId, Entity parentEntity, string parentTransformPath, object userData) + { + AttachEntity(GetEntity(childEntityId), parentEntity, parentTransformPath, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体的实体编号。 + /// 相对于被附加父实体的位置。 + /// 用户自定义数据。 + public void AttachEntity(Entity childEntity, int parentEntityId, string parentTransformPath, object userData) + { + AttachEntity(childEntity, GetEntity(parentEntityId), parentTransformPath, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体。 + /// 相对于被附加父实体的位置。 + /// 用户自定义数据。 + public void AttachEntity(Entity childEntity, Entity parentEntity, string parentTransformPath, object userData) + { + if (childEntity == null) + { + Log.Warning("Child entity is invalid."); + return; + } + + if (parentEntity == null) + { + Log.Warning("Parent entity is invalid."); + return; + } + + Transform parentTransform = null; + if (string.IsNullOrEmpty(parentTransformPath)) + { + parentTransform = parentEntity.Logic.CachedTransform; + } + else + { + parentTransform = parentEntity.Logic.CachedTransform.Find(parentTransformPath); + if (parentTransform == null) + { + Log.Warning("Can not find transform path '{0}' from parent entity '{1}'.", parentTransformPath, parentEntity.Logic.Name); + parentTransform = parentEntity.Logic.CachedTransform; + } + } + + AttachEntity(childEntity, parentEntity, parentTransform, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体的实体编号。 + /// 相对于被附加父实体的位置。 + /// 用户自定义数据。 + public void AttachEntity(int childEntityId, int parentEntityId, Transform parentTransform, object userData) + { + AttachEntity(GetEntity(childEntityId), GetEntity(parentEntityId), parentTransform, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体的实体编号。 + /// 被附加的父实体。 + /// 相对于被附加父实体的位置。 + /// 用户自定义数据。 + public void AttachEntity(int childEntityId, Entity parentEntity, Transform parentTransform, object userData) + { + AttachEntity(GetEntity(childEntityId), parentEntity, parentTransform, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体的实体编号。 + /// 相对于被附加父实体的位置。 + /// 用户自定义数据。 + public void AttachEntity(Entity childEntity, int parentEntityId, Transform parentTransform, object userData) + { + AttachEntity(childEntity, GetEntity(parentEntityId), parentTransform, userData); + } + + /// + /// 附加子实体。 + /// + /// 要附加的子实体。 + /// 被附加的父实体。 + /// 相对于被附加父实体的位置。 + /// 用户自定义数据。 + public void AttachEntity(Entity childEntity, Entity parentEntity, Transform parentTransform, object userData) + { + if (childEntity == null) + { + Log.Warning("Child entity is invalid."); + return; + } + + if (parentEntity == null) + { + Log.Warning("Parent entity is invalid."); + return; + } + + if (parentTransform == null) + { + parentTransform = parentEntity.Logic.CachedTransform; + } + + m_EntityManager.AttachEntity(childEntity, parentEntity, AttachEntityInfo.Create(parentTransform, userData)); + } + + /// + /// 解除子实体。 + /// + /// 要解除的子实体的实体编号。 + public void DetachEntity(int childEntityId) + { + m_EntityManager.DetachEntity(childEntityId); + } + + /// + /// 解除子实体。 + /// + /// 要解除的子实体的实体编号。 + /// 用户自定义数据。 + public void DetachEntity(int childEntityId, object userData) + { + m_EntityManager.DetachEntity(childEntityId, userData); + } + + /// + /// 解除子实体。 + /// + /// 要解除的子实体。 + public void DetachEntity(Entity childEntity) + { + m_EntityManager.DetachEntity(childEntity); + } + + /// + /// 解除子实体。 + /// + /// 要解除的子实体。 + /// 用户自定义数据。 + public void DetachEntity(Entity childEntity, object userData) + { + m_EntityManager.DetachEntity(childEntity, userData); + } + + /// + /// 解除所有子实体。 + /// + /// 被解除的父实体的实体编号。 + public void DetachChildEntities(int parentEntityId) + { + m_EntityManager.DetachChildEntities(parentEntityId); + } + + /// + /// 解除所有子实体。 + /// + /// 被解除的父实体的实体编号。 + /// 用户自定义数据。 + public void DetachChildEntities(int parentEntityId, object userData) + { + m_EntityManager.DetachChildEntities(parentEntityId, userData); + } + + /// + /// 解除所有子实体。 + /// + /// 被解除的父实体。 + public void DetachChildEntities(Entity parentEntity) + { + m_EntityManager.DetachChildEntities(parentEntity); + } + + /// + /// 解除所有子实体。 + /// + /// 被解除的父实体。 + /// 用户自定义数据。 + public void DetachChildEntities(Entity parentEntity, object userData) + { + m_EntityManager.DetachChildEntities(parentEntity, userData); + } + + /// + /// 设置实体是否被加锁。 + /// + /// 实体。 + /// 实体是否被加锁。 + public void SetEntityInstanceLocked(Entity entity, bool locked) + { + if (entity == null) + { + Log.Warning("Entity is invalid."); + return; + } + + IEntityGroup entityGroup = entity.EntityGroup; + if (entityGroup == null) + { + Log.Warning("Entity group is invalid."); + return; + } + + entityGroup.SetEntityInstanceLocked(entity.gameObject, locked); + } + + /// + /// 设置实体的优先级。 + /// + /// 实体。 + /// 实体优先级。 + public void SetInstancePriority(Entity entity, int priority) + { + if (entity == null) + { + Log.Warning("Entity is invalid."); + return; + } + + IEntityGroup entityGroup = entity.EntityGroup; + if (entityGroup == null) + { + Log.Warning("Entity group is invalid."); + return; + } + + entityGroup.SetEntityInstancePriority(entity.gameObject, priority); + } + + private void OnShowEntitySuccess(object sender, GameFramework.Entity.ShowEntitySuccessEventArgs e) + { + m_EventComponent.Fire(this, ShowEntitySuccessEventArgs.Create(e)); + } + + private void OnShowEntityFailure(object sender, GameFramework.Entity.ShowEntityFailureEventArgs e) + { + Log.Warning("Show entity failure, entity id '{0}', asset name '{1}', entity group name '{2}', error message '{3}'.", e.EntityId, e.EntityAssetName, e.EntityGroupName, e.ErrorMessage); + m_EventComponent.Fire(this, ShowEntityFailureEventArgs.Create(e)); + } + + private void OnShowEntityUpdate(object sender, GameFramework.Entity.ShowEntityUpdateEventArgs e) + { + m_EventComponent.Fire(this, ShowEntityUpdateEventArgs.Create(e)); + } + + private void OnShowEntityDependencyAsset(object sender, GameFramework.Entity.ShowEntityDependencyAssetEventArgs e) + { + m_EventComponent.Fire(this, ShowEntityDependencyAssetEventArgs.Create(e)); + } + + private void OnHideEntityComplete(object sender, GameFramework.Entity.HideEntityCompleteEventArgs e) + { + m_EventComponent.Fire(this, HideEntityCompleteEventArgs.Create(e)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityComponent.cs.meta new file mode 100644 index 0000000..63e55aa --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 58aa63e99dabf9c4fb61a9ec4ac4d8ca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityGroupHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityGroupHelperBase.cs new file mode 100644 index 0000000..d54d61b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityGroupHelperBase.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Entity; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 实体组辅助器基类。 + /// + public abstract class EntityGroupHelperBase : MonoBehaviour, IEntityGroupHelper + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityGroupHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityGroupHelperBase.cs.meta new file mode 100644 index 0000000..d85d80d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityGroupHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb8122bd1a1ff7d4cb0a9806d5b3f065 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityHelperBase.cs new file mode 100644 index 0000000..191e46c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityHelperBase.cs @@ -0,0 +1,41 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Entity; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 实体辅助器基类。 + /// + public abstract class EntityHelperBase : MonoBehaviour, IEntityHelper + { + /// + /// 实例化实体。 + /// + /// 要实例化的实体资源。 + /// 实例化后的实体。 + public abstract object InstantiateEntity(object entityAsset); + + /// + /// 创建实体。 + /// + /// 实体实例。 + /// 实体所属的实体组。 + /// 用户自定义数据。 + /// 实体。 + public abstract IEntity CreateEntity(object entityInstance, IEntityGroup entityGroup, object userData); + + /// + /// 释放实体。 + /// + /// 要释放的实体资源。 + /// 要释放的实体实例。 + public abstract void ReleaseEntity(object entityAsset, object entityInstance); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityHelperBase.cs.meta new file mode 100644 index 0000000..fea74fd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8992f89de70519047ba31e6383445cca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityLogic.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityLogic.cs new file mode 100644 index 0000000..aa9f2db --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityLogic.cs @@ -0,0 +1,202 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 实体逻辑基类。 + /// + public abstract class EntityLogic : MonoBehaviour + { + private bool m_Available = false; + private bool m_Visible = false; + private Entity m_Entity = null; + private Transform m_CachedTransform = null; + private int m_OriginalLayer = 0; + private Transform m_OriginalTransform = null; + + /// + /// 获取实体。 + /// + public Entity Entity + { + get + { + return m_Entity; + } + } + + /// + /// 获取或设置实体名称。 + /// + public string Name + { + get + { + return gameObject.name; + } + set + { + gameObject.name = value; + } + } + + /// + /// 获取实体是否可用。 + /// + public bool Available + { + get + { + return m_Available; + } + } + + /// + /// 获取或设置实体是否可见。 + /// + public bool Visible + { + get + { + return m_Available && m_Visible; + } + set + { + if (!m_Available) + { + Log.Warning("Entity '{0}' is not available.", Name); + return; + } + + if (m_Visible == value) + { + return; + } + + m_Visible = value; + InternalSetVisible(value); + } + } + + /// + /// 获取已缓存的 Transform。 + /// + public Transform CachedTransform + { + get + { + return m_CachedTransform; + } + } + + /// + /// 实体初始化。 + /// + /// 用户自定义数据。 + protected internal virtual void OnInit(object userData) + { + if (m_CachedTransform == null) + { + m_CachedTransform = transform; + } + + m_Entity = GetComponent(); + m_OriginalLayer = gameObject.layer; + m_OriginalTransform = CachedTransform.parent; + } + + /// + /// 实体回收。 + /// + protected internal virtual void OnRecycle() + { + } + + /// + /// 实体显示。 + /// + /// 用户自定义数据。 + protected internal virtual void OnShow(object userData) + { + m_Available = true; + Visible = true; + } + + /// + /// 实体隐藏。 + /// + /// 是否是关闭实体管理器时触发。 + /// 用户自定义数据。 + protected internal virtual void OnHide(bool isShutdown, object userData) + { + gameObject.SetLayerRecursively(m_OriginalLayer); + Visible = false; + m_Available = false; + } + + /// + /// 实体附加子实体。 + /// + /// 附加的子实体。 + /// 被附加父实体的位置。 + /// 用户自定义数据。 + protected internal virtual void OnAttached(EntityLogic childEntity, Transform parentTransform, object userData) + { + } + + /// + /// 实体解除子实体。 + /// + /// 解除的子实体。 + /// 用户自定义数据。 + protected internal virtual void OnDetached(EntityLogic childEntity, object userData) + { + } + + /// + /// 实体附加子实体。 + /// + /// 被附加的父实体。 + /// 被附加父实体的位置。 + /// 用户自定义数据。 + protected internal virtual void OnAttachTo(EntityLogic parentEntity, Transform parentTransform, object userData) + { + CachedTransform.SetParent(parentTransform); + } + + /// + /// 实体解除子实体。 + /// + /// 被解除的父实体。 + /// 用户自定义数据。 + protected internal virtual void OnDetachFrom(EntityLogic parentEntity, object userData) + { + CachedTransform.SetParent(m_OriginalTransform); + } + + /// + /// 实体轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + protected internal virtual void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 设置实体的可见性。 + /// + /// 实体的可见性。 + protected virtual void InternalSetVisible(bool visible) + { + gameObject.SetActive(visible); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityLogic.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityLogic.cs.meta new file mode 100644 index 0000000..82446b8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/EntityLogic.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 699dd149c0a53234e8f76e6d6c1b5545 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/HideEntityCompleteEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/HideEntityCompleteEventArgs.cs new file mode 100644 index 0000000..2244fa5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/HideEntityCompleteEventArgs.cs @@ -0,0 +1,108 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Entity; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 隐藏实体完成事件。 + /// + public sealed class HideEntityCompleteEventArgs : GameEventArgs + { + /// + /// 隐藏实体完成事件编号。 + /// + public static readonly int EventId = typeof(HideEntityCompleteEventArgs).GetHashCode(); + + /// + /// 初始化隐藏实体完成事件的新实例。 + /// + public HideEntityCompleteEventArgs() + { + EntityId = 0; + EntityAssetName = null; + EntityGroup = null; + UserData = null; + } + + /// + /// 获取隐藏实体完成事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取实体编号。 + /// + public int EntityId + { + get; + private set; + } + + /// + /// 获取实体资源名称。 + /// + public string EntityAssetName + { + get; + private set; + } + + /// + /// 获取实体所属的实体组。 + /// + public IEntityGroup EntityGroup + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建隐藏实体完成事件。 + /// + /// 内部事件。 + /// 创建的隐藏实体完成事件。 + public static HideEntityCompleteEventArgs Create(GameFramework.Entity.HideEntityCompleteEventArgs e) + { + HideEntityCompleteEventArgs hideEntityCompleteEventArgs = ReferencePool.Acquire(); + hideEntityCompleteEventArgs.EntityId = e.EntityId; + hideEntityCompleteEventArgs.EntityAssetName = e.EntityAssetName; + hideEntityCompleteEventArgs.EntityGroup = e.EntityGroup; + hideEntityCompleteEventArgs.UserData = e.UserData; + return hideEntityCompleteEventArgs; + } + + /// + /// 清理隐藏实体完成事件。 + /// + public override void Clear() + { + EntityId = 0; + EntityAssetName = null; + EntityGroup = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/HideEntityCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/HideEntityCompleteEventArgs.cs.meta new file mode 100644 index 0000000..96661d2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/HideEntityCompleteEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 852f69476ad9a2e4cb44c564a250aff2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityDependencyAssetEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityDependencyAssetEventArgs.cs new file mode 100644 index 0000000..5b4a334 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityDependencyAssetEventArgs.cs @@ -0,0 +1,157 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using System; + +namespace UnityGameFramework.Runtime +{ + /// + /// 显示实体时加载依赖资源事件。 + /// + public sealed class ShowEntityDependencyAssetEventArgs : GameEventArgs + { + /// + /// 显示实体时加载依赖资源事件编号。 + /// + public static readonly int EventId = typeof(ShowEntityDependencyAssetEventArgs).GetHashCode(); + + /// + /// 初始化显示实体时加载依赖资源事件的新实例。 + /// + public ShowEntityDependencyAssetEventArgs() + { + EntityId = 0; + EntityLogicType = null; + EntityAssetName = null; + EntityGroupName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + + /// + /// 获取显示实体时加载依赖资源事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取实体编号。 + /// + public int EntityId + { + get; + private set; + } + + /// + /// 获取实体逻辑类型。 + /// + public Type EntityLogicType + { + get; + private set; + } + + /// + /// 获取实体资源名称。 + /// + public string EntityAssetName + { + get; + private set; + } + + /// + /// 获取实体组名称。 + /// + public string EntityGroupName + { + get; + private set; + } + + /// + /// 获取被加载的依赖资源名称。 + /// + public string DependencyAssetName + { + get; + private set; + } + + /// + /// 获取当前已加载依赖资源数量。 + /// + public int LoadedCount + { + get; + private set; + } + + /// + /// 获取总共加载依赖资源数量。 + /// + public int TotalCount + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建显示实体时加载依赖资源事件。 + /// + /// 内部事件。 + /// 创建的显示实体时加载依赖资源事件。 + public static ShowEntityDependencyAssetEventArgs Create(GameFramework.Entity.ShowEntityDependencyAssetEventArgs e) + { + ShowEntityInfo showEntityInfo = (ShowEntityInfo)e.UserData; + ShowEntityDependencyAssetEventArgs showEntityDependencyAssetEventArgs = ReferencePool.Acquire(); + showEntityDependencyAssetEventArgs.EntityId = e.EntityId; + showEntityDependencyAssetEventArgs.EntityLogicType = showEntityInfo.EntityLogicType; + showEntityDependencyAssetEventArgs.EntityAssetName = e.EntityAssetName; + showEntityDependencyAssetEventArgs.EntityGroupName = e.EntityGroupName; + showEntityDependencyAssetEventArgs.DependencyAssetName = e.DependencyAssetName; + showEntityDependencyAssetEventArgs.LoadedCount = e.LoadedCount; + showEntityDependencyAssetEventArgs.TotalCount = e.TotalCount; + showEntityDependencyAssetEventArgs.UserData = showEntityInfo.UserData; + return showEntityDependencyAssetEventArgs; + } + + /// + /// 清理显示实体时加载依赖资源事件。 + /// + public override void Clear() + { + EntityId = 0; + EntityLogicType = null; + EntityAssetName = null; + EntityGroupName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityDependencyAssetEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityDependencyAssetEventArgs.cs.meta new file mode 100644 index 0000000..e63ed01 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityDependencyAssetEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cef77d19116ea6f4aaa8b77116df65c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityFailureEventArgs.cs new file mode 100644 index 0000000..78b0188 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityFailureEventArgs.cs @@ -0,0 +1,134 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using System; + +namespace UnityGameFramework.Runtime +{ + /// + /// 显示实体失败事件。 + /// + public sealed class ShowEntityFailureEventArgs : GameEventArgs + { + /// + /// 显示实体失败事件编号。 + /// + public static readonly int EventId = typeof(ShowEntityFailureEventArgs).GetHashCode(); + + /// + /// 初始化显示实体失败事件的新实例。 + /// + public ShowEntityFailureEventArgs() + { + EntityId = 0; + EntityLogicType = null; + EntityAssetName = null; + EntityGroupName = null; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取显示实体失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取实体编号。 + /// + public int EntityId + { + get; + private set; + } + + /// + /// 获取实体逻辑类型。 + /// + public Type EntityLogicType + { + get; + private set; + } + + /// + /// 获取实体资源名称。 + /// + public string EntityAssetName + { + get; + private set; + } + + /// + /// 获取实体组名称。 + /// + public string EntityGroupName + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建显示实体失败事件。 + /// + /// 内部事件。 + /// 创建的显示实体失败事件。 + public static ShowEntityFailureEventArgs Create(GameFramework.Entity.ShowEntityFailureEventArgs e) + { + ShowEntityInfo showEntityInfo = (ShowEntityInfo)e.UserData; + ShowEntityFailureEventArgs showEntityFailureEventArgs = ReferencePool.Acquire(); + showEntityFailureEventArgs.EntityId = e.EntityId; + showEntityFailureEventArgs.EntityLogicType = showEntityInfo.EntityLogicType; + showEntityFailureEventArgs.EntityAssetName = e.EntityAssetName; + showEntityFailureEventArgs.EntityGroupName = e.EntityGroupName; + showEntityFailureEventArgs.ErrorMessage = e.ErrorMessage; + showEntityFailureEventArgs.UserData = showEntityInfo.UserData; + ReferencePool.Release(showEntityInfo); + return showEntityFailureEventArgs; + } + + /// + /// 清理显示实体失败事件。 + /// + public override void Clear() + { + EntityId = 0; + EntityLogicType = null; + EntityAssetName = null; + EntityGroupName = null; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityFailureEventArgs.cs.meta new file mode 100644 index 0000000..a8e08db --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c7188888f5121ad44bfaba20e4ed7ca9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityInfo.cs new file mode 100644 index 0000000..0960049 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityInfo.cs @@ -0,0 +1,54 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; + +namespace UnityGameFramework.Runtime +{ + internal sealed class ShowEntityInfo : IReference + { + private Type m_EntityLogicType; + private object m_UserData; + + public ShowEntityInfo() + { + m_EntityLogicType = null; + m_UserData = null; + } + + public Type EntityLogicType + { + get + { + return m_EntityLogicType; + } + } + + public object UserData + { + get + { + return m_UserData; + } + } + + public static ShowEntityInfo Create(Type entityLogicType, object userData) + { + ShowEntityInfo showEntityInfo = ReferencePool.Acquire(); + showEntityInfo.m_EntityLogicType = entityLogicType; + showEntityInfo.m_UserData = userData; + return showEntityInfo; + } + + public void Clear() + { + m_EntityLogicType = null; + m_UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityInfo.cs.meta new file mode 100644 index 0000000..26b3a5b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5535dde509ba87b42912084f30591779 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntitySuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntitySuccessEventArgs.cs new file mode 100644 index 0000000..f202229 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntitySuccessEventArgs.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using System; + +namespace UnityGameFramework.Runtime +{ + /// + /// 显示实体成功事件。 + /// + public sealed class ShowEntitySuccessEventArgs : GameEventArgs + { + /// + /// 显示实体成功事件编号。 + /// + public static readonly int EventId = typeof(ShowEntitySuccessEventArgs).GetHashCode(); + + /// + /// 初始化显示实体成功事件的新实例。 + /// + public ShowEntitySuccessEventArgs() + { + EntityLogicType = null; + Entity = null; + Duration = 0f; + UserData = null; + } + + /// + /// 获取显示实体成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取实体逻辑类型。 + /// + public Type EntityLogicType + { + get; + private set; + } + + /// + /// 获取显示成功的实体。 + /// + public Entity Entity + { + get; + private set; + } + + /// + /// 获取加载持续时间。 + /// + public float Duration + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建显示实体成功事件。 + /// + /// 内部事件。 + /// 创建的显示实体成功事件。 + public static ShowEntitySuccessEventArgs Create(GameFramework.Entity.ShowEntitySuccessEventArgs e) + { + ShowEntityInfo showEntityInfo = (ShowEntityInfo)e.UserData; + ShowEntitySuccessEventArgs showEntitySuccessEventArgs = ReferencePool.Acquire(); + showEntitySuccessEventArgs.EntityLogicType = showEntityInfo.EntityLogicType; + showEntitySuccessEventArgs.Entity = (Entity)e.Entity; + showEntitySuccessEventArgs.Duration = e.Duration; + showEntitySuccessEventArgs.UserData = showEntityInfo.UserData; + ReferencePool.Release(showEntityInfo); + return showEntitySuccessEventArgs; + } + + /// + /// 清理显示实体成功事件。 + /// + public override void Clear() + { + EntityLogicType = null; + Entity = null; + Duration = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntitySuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntitySuccessEventArgs.cs.meta new file mode 100644 index 0000000..8057f5f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntitySuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9786630f2f7760f4da147cd8173e9b18 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityUpdateEventArgs.cs new file mode 100644 index 0000000..c1aef33 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityUpdateEventArgs.cs @@ -0,0 +1,133 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using System; + +namespace UnityGameFramework.Runtime +{ + /// + /// 显示实体更新事件。 + /// + public sealed class ShowEntityUpdateEventArgs : GameEventArgs + { + /// + /// 显示实体更新事件编号。 + /// + public static readonly int EventId = typeof(ShowEntityUpdateEventArgs).GetHashCode(); + + /// + /// 初始化显示实体更新事件的新实例。 + /// + public ShowEntityUpdateEventArgs() + { + EntityId = 0; + EntityLogicType = null; + EntityAssetName = null; + EntityGroupName = null; + Progress = 0f; + UserData = null; + } + + /// + /// 获取显示实体更新事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取实体编号。 + /// + public int EntityId + { + get; + private set; + } + + /// + /// 获取实体逻辑类型。 + /// + public Type EntityLogicType + { + get; + private set; + } + + /// + /// 获取实体资源名称。 + /// + public string EntityAssetName + { + get; + private set; + } + + /// + /// 获取实体组名称。 + /// + public string EntityGroupName + { + get; + private set; + } + + /// + /// 获取显示实体进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建显示实体更新事件。 + /// + /// 内部事件。 + /// 创建的显示实体更新事件。 + public static ShowEntityUpdateEventArgs Create(GameFramework.Entity.ShowEntityUpdateEventArgs e) + { + ShowEntityInfo showEntityInfo = (ShowEntityInfo)e.UserData; + ShowEntityUpdateEventArgs showEntityUpdateEventArgs = ReferencePool.Acquire(); + showEntityUpdateEventArgs.EntityId = e.EntityId; + showEntityUpdateEventArgs.EntityLogicType = showEntityInfo.EntityLogicType; + showEntityUpdateEventArgs.EntityAssetName = e.EntityAssetName; + showEntityUpdateEventArgs.EntityGroupName = e.EntityGroupName; + showEntityUpdateEventArgs.Progress = e.Progress; + showEntityUpdateEventArgs.UserData = showEntityInfo.UserData; + return showEntityUpdateEventArgs; + } + + /// + /// 清理显示实体更新事件。 + /// + public override void Clear() + { + EntityId = 0; + EntityLogicType = null; + EntityAssetName = null; + EntityGroupName = null; + Progress = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityUpdateEventArgs.cs.meta new file mode 100644 index 0000000..8d2313a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Entity/ShowEntityUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8fb90ce75efc136468379f5728401d0c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Event.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Event.meta new file mode 100644 index 0000000..f7bb531 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Event.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6a1049d8ab8f5f147831166d2e3a8db7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Event/EventComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Event/EventComponent.cs new file mode 100644 index 0000000..ed391cf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Event/EventComponent.cs @@ -0,0 +1,135 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 事件组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Event")] + public sealed class EventComponent : GameFrameworkComponent + { + private IEventManager m_EventManager = null; + + /// + /// 获取事件处理函数的数量。 + /// + public int EventHandlerCount + { + get + { + return m_EventManager.EventHandlerCount; + } + } + + /// + /// 获取事件数量。 + /// + public int EventCount + { + get + { + return m_EventManager.EventCount; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_EventManager = GameFrameworkEntry.GetModule(); + if (m_EventManager == null) + { + Log.Fatal("Event manager is invalid."); + return; + } + } + + private void Start() + { + } + + /// + /// 获取事件处理函数的数量。 + /// + /// 事件类型编号。 + /// 事件处理函数的数量。 + public int Count(int id) + { + return m_EventManager.Count(id); + } + + /// + /// 检查是否存在事件处理函数。 + /// + /// 事件类型编号。 + /// 要检查的事件处理函数。 + /// 是否存在事件处理函数。 + public bool Check(int id, EventHandler handler) + { + return m_EventManager.Check(id, handler); + } + + /// + /// 订阅事件处理回调函数。 + /// + /// 事件类型编号。 + /// 要订阅的事件处理回调函数。 + public void Subscribe(int id, EventHandler handler) + { + m_EventManager.Subscribe(id, handler); + } + + /// + /// 取消订阅事件处理回调函数。 + /// + /// 事件类型编号。 + /// 要取消订阅的事件处理回调函数。 + public void Unsubscribe(int id, EventHandler handler) + { + m_EventManager.Unsubscribe(id, handler); + } + + /// + /// 设置默认事件处理函数。 + /// + /// 要设置的默认事件处理函数。 + public void SetDefaultHandler(EventHandler handler) + { + m_EventManager.SetDefaultHandler(handler); + } + + /// + /// 抛出事件,这个操作是线程安全的,即使不在主线程中抛出,也可保证在主线程中回调事件处理函数,但事件会在抛出后的下一帧分发。 + /// + /// 事件发送者。 + /// 事件内容。 + public void Fire(object sender, GameEventArgs e) + { + m_EventManager.Fire(sender, e); + } + + /// + /// 抛出事件立即模式,这个操作不是线程安全的,事件会立刻分发。 + /// + /// 事件发送者。 + /// 事件内容。 + public void FireNow(object sender, GameEventArgs e) + { + m_EventManager.FireNow(sender, e); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Event/EventComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Event/EventComponent.cs.meta new file mode 100644 index 0000000..f83dff9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Event/EventComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d7daf8320a3d04046b4bbd7c47307914 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem.meta new file mode 100644 index 0000000..d242d82 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 080a8216f14ee5047b7fc9d20c8baf37 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/AndroidFileSystemStream.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/AndroidFileSystemStream.cs new file mode 100644 index 0000000..05cf30e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/AndroidFileSystemStream.cs @@ -0,0 +1,293 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.FileSystem; +using System; +using System.IO; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 安卓文件系统流。 + /// + public sealed class AndroidFileSystemStream : FileSystemStream + { + private static readonly string SplitFlag = "!/assets/"; + private static readonly int SplitFlagLength = SplitFlag.Length; + private static readonly AndroidJavaObject s_AssetManager = null; + private static readonly IntPtr s_InternalReadMethodId = IntPtr.Zero; + private static readonly jvalue[] s_InternalReadArgs = null; + + private readonly AndroidJavaObject m_FileStream; + private readonly IntPtr m_FileStreamRawObject; + + static AndroidFileSystemStream() + { + AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); + if (unityPlayer == null) + { + throw new GameFrameworkException("Unity player is invalid."); + } + + AndroidJavaObject currentActivity = unityPlayer.GetStatic("currentActivity"); + if (currentActivity == null) + { + throw new GameFrameworkException("Current activity is invalid."); + } + + AndroidJavaObject assetManager = currentActivity.Call("getAssets"); + if (assetManager == null) + { + throw new GameFrameworkException("Asset manager is invalid."); + } + + s_AssetManager = assetManager; + + IntPtr inputStreamClassPtr = AndroidJNI.FindClass("java/io/InputStream"); + s_InternalReadMethodId = AndroidJNIHelper.GetMethodID(inputStreamClassPtr, "read", "([BII)I"); + s_InternalReadArgs = new jvalue[3]; + + AndroidJNI.DeleteLocalRef(inputStreamClassPtr); + currentActivity.Dispose(); + unityPlayer.Dispose(); + } + + /// + /// 初始化安卓文件系统流的新实例。 + /// + /// 要加载的文件系统的完整路径。 + /// 要加载的文件系统的访问方式。 + /// 是否创建新的文件系统流。 + public AndroidFileSystemStream(string fullPath, FileSystemAccess access, bool createNew) + { + if (string.IsNullOrEmpty(fullPath)) + { + throw new GameFrameworkException("Full path is invalid."); + } + + if (access != FileSystemAccess.Read) + { + throw new GameFrameworkException(Utility.Text.Format("'{0}' is not supported in AndroidFileSystemStream.", access)); + } + + if (createNew) + { + throw new GameFrameworkException("Create new is not supported in AndroidFileSystemStream."); + } + + int position = fullPath.LastIndexOf(SplitFlag, StringComparison.Ordinal); + if (position < 0) + { + throw new GameFrameworkException("Can not find split flag in full path."); + } + + string fileName = fullPath.Substring(position + SplitFlagLength); + m_FileStream = InternalOpen(fileName); + if (m_FileStream == null) + { + throw new GameFrameworkException(Utility.Text.Format("Open file '{0}' from Android asset manager failure.", fullPath)); + } + + m_FileStreamRawObject = m_FileStream.GetRawObject(); + } + + /// + /// 获取或设置文件系统流位置。 + /// + public override long Position + { + get + { + throw new GameFrameworkException("Get position is not supported in AndroidFileSystemStream."); + } + set + { + Seek(value, SeekOrigin.Begin); + } + } + + /// + /// 获取文件系统流长度。 + /// + public override long Length + { + get + { + return InternalAvailable(); + } + } + + /// + /// 设置文件系统流长度。 + /// + /// 要设置的文件系统流的长度。 + public override void SetLength(long length) + { + throw new GameFrameworkException("SetLength is not supported in AndroidFileSystemStream."); + } + + /// + /// 定位文件系统流位置。 + /// + /// 要定位的文件系统流位置的偏移。 + /// 要定位的文件系统流位置的方式。 + public override void Seek(long offset, SeekOrigin origin) + { + if (origin == SeekOrigin.End) + { + Seek(Length + offset, SeekOrigin.Begin); + return; + } + + if (origin == SeekOrigin.Begin) + { + InternalReset(); + } + + while (offset > 0) + { + long skip = InternalSkip(offset); + if (skip < 0) + { + return; + } + + offset -= skip; + } + } + + /// + /// 从文件系统流中读取一个字节。 + /// + /// 读取的字节,若已经到达文件结尾,则返回 -1。 + public override int ReadByte() + { + return InternalRead(); + } + + /// + /// 从文件系统流中读取二进制流。 + /// + /// 存储读取文件内容的二进制流。 + /// 存储读取文件内容的二进制流的起始位置。 + /// 存储读取文件内容的二进制流的长度。 + /// 实际读取了多少字节。 + public override int Read(byte[] buffer, int startIndex, int length) + { + byte[] result = null; + int bytesRead = InternalRead(length, out result); + Array.Copy(result, 0, buffer, startIndex, bytesRead); + return bytesRead; + } + + /// + /// 向文件系统流中写入一个字节。 + /// + /// 要写入的字节。 + public override void WriteByte(byte value) + { + throw new GameFrameworkException("WriteByte is not supported in AndroidFileSystemStream."); + } + + /// + /// 向文件系统流中写入二进制流。 + /// + /// 存储写入文件内容的二进制流。 + /// 存储写入文件内容的二进制流的起始位置。 + /// 存储写入文件内容的二进制流的长度。 + public override void Write(byte[] buffer, int startIndex, int length) + { + throw new GameFrameworkException("Write is not supported in AndroidFileSystemStream."); + } + + /// + /// 将文件系统流立刻更新到存储介质中。 + /// + public override void Flush() + { + throw new GameFrameworkException("Flush is not supported in AndroidFileSystemStream."); + } + + /// + /// 关闭文件系统流。 + /// + public override void Close() + { + InternalClose(); + m_FileStream.Dispose(); + } + + private AndroidJavaObject InternalOpen(string fileName) + { + return s_AssetManager.Call("open", fileName); + } + + private int InternalAvailable() + { + return m_FileStream.Call("available"); + } + + private void InternalClose() + { + m_FileStream.Call("close"); + } + + private int InternalRead() + { + return m_FileStream.Call("read"); + } + + private int InternalRead(int length, out byte[] result) + { +#if UNITY_2019_2_OR_NEWER +#pragma warning disable CS0618 +#endif + IntPtr resultPtr = AndroidJNI.NewByteArray(length); +#if UNITY_2019_2_OR_NEWER +#pragma warning restore CS0618 +#endif + int offset = 0; + int bytesLeft = length; + while (bytesLeft > 0) + { + s_InternalReadArgs[0] = new jvalue() { l = resultPtr }; + s_InternalReadArgs[1] = new jvalue() { i = offset }; + s_InternalReadArgs[2] = new jvalue() { i = bytesLeft }; + int bytesRead = AndroidJNI.CallIntMethod(m_FileStreamRawObject, s_InternalReadMethodId, s_InternalReadArgs); + if (bytesRead <= 0) + { + break; + } + + offset += bytesRead; + bytesLeft -= bytesRead; + } + +#if UNITY_2019_2_OR_NEWER +#pragma warning disable CS0618 +#endif + result = AndroidJNI.FromByteArray(resultPtr); +#if UNITY_2019_2_OR_NEWER +#pragma warning restore CS0618 +#endif + AndroidJNI.DeleteLocalRef(resultPtr); + return offset; + } + + private void InternalReset() + { + m_FileStream.Call("reset"); + } + + private long InternalSkip(long offset) + { + return m_FileStream.Call("skip", offset); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/AndroidFileSystemStream.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/AndroidFileSystemStream.cs.meta new file mode 100644 index 0000000..a44dc07 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/AndroidFileSystemStream.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e91d57307e5c7674c855d299cfb466b6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/DefaultFileSystemHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/DefaultFileSystemHelper.cs new file mode 100644 index 0000000..1704e2a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/DefaultFileSystemHelper.cs @@ -0,0 +1,39 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.FileSystem; +using System; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认文件系统辅助器。 + /// + public class DefaultFileSystemHelper : FileSystemHelperBase + { + private const string AndroidFileSystemPrefixString = "jar:"; + + /// + /// 创建文件系统流。 + /// + /// 要加载的文件系统的完整路径。 + /// 要加载的文件系统的访问方式。 + /// 是否创建新的文件系统流。 + /// 创建的文件系统流。 + public override FileSystemStream CreateFileSystemStream(string fullPath, FileSystemAccess access, bool createNew) + { + if (fullPath.StartsWith(AndroidFileSystemPrefixString, StringComparison.Ordinal)) + { + return new AndroidFileSystemStream(fullPath, access, createNew); + } + else + { + return new CommonFileSystemStream(fullPath, access, createNew); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/DefaultFileSystemHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/DefaultFileSystemHelper.cs.meta new file mode 100644 index 0000000..37f3edf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/DefaultFileSystemHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ab61553d44f971447856311f2f7aef44 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/FileSystemComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/FileSystemComponent.cs new file mode 100644 index 0000000..8e8407b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/FileSystemComponent.cs @@ -0,0 +1,146 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.FileSystem; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 文件系统件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/File System")] + public sealed class FileSystemComponent : GameFrameworkComponent + { + private IFileSystemManager m_FileSystemManager = null; + + [SerializeField] + private string m_FileSystemHelperTypeName = "UnityGameFramework.Runtime.DefaultFileSystemHelper"; + + [SerializeField] + private FileSystemHelperBase m_CustomFileSystemHelper = null; + + /// + /// 获取文件系统数量。 + /// + public int Count + { + get + { + return m_FileSystemManager.Count; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_FileSystemManager = GameFrameworkEntry.GetModule(); + if (m_FileSystemManager == null) + { + Log.Fatal("File system manager is invalid."); + return; + } + + FileSystemHelperBase fileSystemHelper = Helper.CreateHelper(m_FileSystemHelperTypeName, m_CustomFileSystemHelper); + if (fileSystemHelper == null) + { + Log.Error("Can not create fileSystem helper."); + return; + } + + fileSystemHelper.name = "FileSystem Helper"; + Transform transform = fileSystemHelper.transform; + transform.SetParent(this.transform); + transform.localScale = Vector3.one; + + m_FileSystemManager.SetFileSystemHelper(fileSystemHelper); + } + + private void Start() + { + } + + /// + /// 检查是否存在文件系统。 + /// + /// 要检查的文件系统的完整路径。 + /// 是否存在文件系统。 + public bool HasFileSystem(string fullPath) + { + return m_FileSystemManager.HasFileSystem(fullPath); + } + + /// + /// 获取文件系统。 + /// + /// 要获取的文件系统的完整路径。 + /// 获取的文件系统。 + public IFileSystem GetFileSystem(string fullPath) + { + return m_FileSystemManager.GetFileSystem(fullPath); + } + + /// + /// 创建文件系统。 + /// + /// 要创建的文件系统的完整路径。 + /// 要创建的文件系统的访问方式。 + /// 要创建的文件系统的最大文件数量。 + /// 要创建的文件系统的最大块数据数量。 + /// 创建的文件系统。 + public IFileSystem CreateFileSystem(string fullPath, FileSystemAccess access, int maxFileCount, int maxBlockCount) + { + return m_FileSystemManager.CreateFileSystem(fullPath, access, maxFileCount, maxBlockCount); + } + + /// + /// 加载文件系统。 + /// + /// 要加载的文件系统的完整路径。 + /// 要加载的文件系统的访问方式。 + /// 加载的文件系统。 + public IFileSystem LoadFileSystem(string fullPath, FileSystemAccess access) + { + return m_FileSystemManager.LoadFileSystem(fullPath, access); + } + + /// + /// 销毁文件系统。 + /// + /// 要销毁的文件系统。 + /// 是否删除文件系统对应的物理文件。 + public void DestroyFileSystem(IFileSystem fileSystem, bool deletePhysicalFile) + { + m_FileSystemManager.DestroyFileSystem(fileSystem, deletePhysicalFile); + } + + /// + /// 获取所有文件系统集合。 + /// + /// 获取的所有文件系统集合。 + public IFileSystem[] GetAllFileSystems() + { + return m_FileSystemManager.GetAllFileSystems(); + } + + /// + /// 获取所有文件系统集合。 + /// + /// 获取的所有文件系统集合。 + public void GetAllFileSystems(List results) + { + m_FileSystemManager.GetAllFileSystems(results); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/FileSystemComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/FileSystemComponent.cs.meta new file mode 100644 index 0000000..a714d8f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/FileSystemComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fc49d78dad061a2418e134fc48856bc9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/FileSystemHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/FileSystemHelperBase.cs new file mode 100644 index 0000000..7c623b5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/FileSystemHelperBase.cs @@ -0,0 +1,27 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.FileSystem; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 文件系统辅助器基类。 + /// + public abstract class FileSystemHelperBase : MonoBehaviour, IFileSystemHelper + { + /// + /// 创建文件系统流。 + /// + /// 要加载的文件系统的完整路径。 + /// 要加载的文件系统的访问方式。 + /// 是否创建新的文件系统流。 + /// 创建的文件系统流。 + public abstract FileSystemStream CreateFileSystemStream(string fullPath, FileSystemAccess access, bool createNew); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/FileSystemHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/FileSystemHelperBase.cs.meta new file mode 100644 index 0000000..62d330d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/FileSystem/FileSystemHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 40934320d6b918548891a29641dc0a20 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Fsm.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Fsm.meta new file mode 100644 index 0000000..c47f972 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Fsm.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 82c3050d1857b3e47be8bb68926c81cf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Fsm/FsmComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Fsm/FsmComponent.cs new file mode 100644 index 0000000..4dbf996 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Fsm/FsmComponent.cs @@ -0,0 +1,269 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Fsm; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 有限状态机组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/FSM")] + public sealed class FsmComponent : GameFrameworkComponent + { + private IFsmManager m_FsmManager = null; + + /// + /// 获取有限状态机数量。 + /// + public int Count + { + get + { + return m_FsmManager.Count; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_FsmManager = GameFrameworkEntry.GetModule(); + if (m_FsmManager == null) + { + Log.Fatal("FSM manager is invalid."); + return; + } + } + + private void Start() + { + } + + /// + /// 检查是否存在有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 是否存在有限状态机。 + public bool HasFsm() where T : class + { + return m_FsmManager.HasFsm(); + } + + /// + /// 检查是否存在有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 是否存在有限状态机。 + public bool HasFsm(Type ownerType) + { + return m_FsmManager.HasFsm(ownerType); + } + + /// + /// 检查是否存在有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 是否存在有限状态机。 + public bool HasFsm(string name) where T : class + { + return m_FsmManager.HasFsm(name); + } + + /// + /// 检查是否存在有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 是否存在有限状态机。 + public bool HasFsm(Type ownerType, string name) + { + return m_FsmManager.HasFsm(ownerType, name); + } + + /// + /// 获取有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要获取的有限状态机。 + public IFsm GetFsm() where T : class + { + return m_FsmManager.GetFsm(); + } + + /// + /// 获取有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要获取的有限状态机。 + public FsmBase GetFsm(Type ownerType) + { + return m_FsmManager.GetFsm(ownerType); + } + + /// + /// 获取有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 要获取的有限状态机。 + public IFsm GetFsm(string name) where T : class + { + return m_FsmManager.GetFsm(name); + } + + /// + /// 获取有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 要获取的有限状态机。 + public FsmBase GetFsm(Type ownerType, string name) + { + return m_FsmManager.GetFsm(ownerType, name); + } + + /// + /// 获取所有有限状态机。 + /// + public FsmBase[] GetAllFsms() + { + return m_FsmManager.GetAllFsms(); + } + + /// + /// 获取所有有限状态机。 + /// + /// 所有有限状态机。 + public void GetAllFsms(List results) + { + m_FsmManager.GetAllFsms(results); + } + + /// + /// 创建有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 要创建的有限状态机。 + public IFsm CreateFsm(T owner, params FsmState[] states) where T : class + { + return m_FsmManager.CreateFsm(owner, states); + } + + /// + /// 创建有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 要创建的有限状态机。 + public IFsm CreateFsm(string name, T owner, params FsmState[] states) where T : class + { + return m_FsmManager.CreateFsm(name, owner, states); + } + + /// + /// 创建有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 要创建的有限状态机。 + public IFsm CreateFsm(T owner, List> states) where T : class + { + return m_FsmManager.CreateFsm(owner, states); + } + + /// + /// 创建有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 有限状态机名称。 + /// 有限状态机持有者。 + /// 有限状态机状态集合。 + /// 要创建的有限状态机。 + public IFsm CreateFsm(string name, T owner, List> states) where T : class + { + return m_FsmManager.CreateFsm(name, owner, states); + } + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 是否销毁有限状态机成功。 + public bool DestroyFsm() where T : class + { + return m_FsmManager.DestroyFsm(); + } + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 是否销毁有限状态机成功。 + public bool DestroyFsm(Type ownerType) + { + return m_FsmManager.DestroyFsm(ownerType); + } + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要销毁的有限状态机名称。 + /// 是否销毁有限状态机成功。 + public bool DestroyFsm(string name) where T : class + { + return m_FsmManager.DestroyFsm(name); + } + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要销毁的有限状态机名称。 + /// 是否销毁有限状态机成功。 + public bool DestroyFsm(Type ownerType, string name) + { + return m_FsmManager.DestroyFsm(ownerType, name); + } + + /// + /// 销毁有限状态机。 + /// + /// 有限状态机持有者类型。 + /// 要销毁的有限状态机。 + /// 是否销毁有限状态机成功。 + public bool DestroyFsm(IFsm fsm) where T : class + { + return m_FsmManager.DestroyFsm(fsm); + } + + /// + /// 销毁有限状态机。 + /// + /// 要销毁的有限状态机。 + /// 是否销毁有限状态机成功。 + public bool DestroyFsm(FsmBase fsm) + { + return m_FsmManager.DestroyFsm(fsm); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Fsm/FsmComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Fsm/FsmComponent.cs.meta new file mode 100644 index 0000000..adbbf83 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Fsm/FsmComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ac872c3ce4121bb46a74927b35780534 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/GameFramework.prefab b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/GameFramework.prefab new file mode 100644 index 0000000..5d2dbbc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/GameFramework.prefab @@ -0,0 +1,1190 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &105264 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 447378} + - component: {fileID: 11472694} + m_Layer: 0 + m_Name: FSM + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &447378 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 105264} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11472694 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 105264} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ac872c3ce4121bb46a74927b35780534, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &108464 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 432002} + - component: {fileID: 11497722} + m_Layer: 0 + m_Name: Resource + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &432002 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 108464} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11497722 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 108464} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7eff66e40586ec14d8a301d416f17f1e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_ResourceMode: 1 + m_ReadWritePathType: 0 + m_MinUnloadUnusedAssetsInterval: 60 + m_MaxUnloadUnusedAssetsInterval: 300 + m_AssetAutoReleaseInterval: 60 + m_AssetCapacity: 64 + m_AssetExpireTime: 60 + m_AssetPriority: 10000 + m_ResourceAutoReleaseInterval: 60 + m_ResourceCapacity: 16 + m_ResourceExpireTime: 60 + m_ResourcePriority: 20000 + m_UpdatePrefixUri: + m_GenerateReadWriteVersionListLength: 1048576 + m_UpdateRetryCount: 3 + m_InstanceRoot: {fileID: 0} + m_ResourceHelperTypeName: UnityGameFramework.Runtime.DefaultResourceHelper + m_CustomResourceHelper: {fileID: 0} + m_LoadResourceAgentHelperTypeName: UnityGameFramework.Runtime.DefaultLoadResourceAgentHelper + m_CustomLoadResourceAgentHelper: {fileID: 0} + m_LoadResourceAgentHelperCount: 3 + HotUpdateScripts: + OtherHotUpdateScripts: +--- !u!1 &109252 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 472962} + - component: {fileID: 11461470} + m_Layer: 0 + m_Name: Localization + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &472962 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 109252} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11461470 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 109252} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 706e6317a59f61044b2805be79f6b284, type: 3} + m_Name: + m_EditorClassIdentifier: + m_EnableLoadDictionaryUpdateEvent: 0 + m_EnableLoadDictionaryDependencyAssetEvent: 0 + m_LocalizationHelperTypeName: UnityGameFramework.Runtime.DefaultLocalizationHelper + m_CustomLocalizationHelper: {fileID: 0} + m_CachedBytesSize: 0 +--- !u!1 &109548 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 472238} + - component: {fileID: 11420954} + m_Layer: 0 + m_Name: Download + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &472238 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 109548} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11420954 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 109548} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9259de0854ba2624aa59aca15c6af063, type: 3} + m_Name: + m_EditorClassIdentifier: + m_InstanceRoot: {fileID: 0} + m_DownloadAgentHelperTypeName: UnityGameFramework.Runtime.UnityWebRequestDownloadAgentHelper + m_CustomDownloadAgentHelper: {fileID: 0} + m_DownloadAgentHelperCount: 3 + m_Timeout: 30 + m_FlushSize: 1048576 +--- !u!1 &110832 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 449550} + - component: {fileID: 11494652} + m_Layer: 0 + m_Name: Entity + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &449550 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 110832} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11494652 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 110832} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 58aa63e99dabf9c4fb61a9ec4ac4d8ca, type: 3} + m_Name: + m_EditorClassIdentifier: + m_EnableShowEntityUpdateEvent: 0 + m_EnableShowEntityDependencyAssetEvent: 0 + m_InstanceRoot: {fileID: 0} + m_EntityHelperTypeName: UnityGameFramework.Runtime.DefaultEntityHelper + m_CustomEntityHelper: {fileID: 0} + m_EntityGroupHelperTypeName: UnityGameFramework.Runtime.DefaultEntityGroupHelper + m_CustomEntityGroupHelper: {fileID: 0} + m_EntityGroups: [] +--- !u!1 &116470 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 433714} + - component: {fileID: 11499388} + - component: {fileID: 11463816} + m_Layer: 0 + m_Name: GameFramework + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &433714 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 116470} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 436184} + - {fileID: 455962} + - {fileID: 465000} + - {fileID: 404872} + - {fileID: 472238} + - {fileID: 449550} + - {fileID: 401796} + - {fileID: 429090} + - {fileID: 447378} + - {fileID: 472962} + - {fileID: 486648} + - {fileID: 431700} + - {fileID: 407686} + - {fileID: 461836} + - {fileID: 432002} + - {fileID: 449996} + - {fileID: 490662} + - {fileID: 463618} + - {fileID: 430602} + - {fileID: 450964} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11499388 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 116470} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f98acd7d3bd2bf54dadf9644f60e5cb9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_EditorResourceMode: 1 + m_EditorLanguage: 0 + m_TextHelperTypeName: + m_VersionHelperTypeName: + m_LogHelperTypeName: + m_CompressionHelperTypeName: + m_JsonHelperTypeName: + m_FrameRate: 30 + m_GameSpeed: 1 + m_RunInBackground: 1 + m_NeverSleep: 1 +--- !u!114 &11463816 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 116470} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c26ec20b78ec32048bfb6c0ff875d8cd, type: 3} + m_Name: + m_EditorClassIdentifier: + m_EnableCachedAssets: 1 + m_LoadAssetCountPerFrame: 1 + m_MinLoadAssetRandomDelaySeconds: 0 + m_MaxLoadAssetRandomDelaySeconds: 0 +--- !u!1 &118246 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 429090} + - component: {fileID: 11417814} + m_Layer: 0 + m_Name: File System + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &429090 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118246} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11417814 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 118246} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fc49d78dad061a2418e134fc48856bc9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_FileSystemHelperTypeName: UnityGameFramework.Runtime.DefaultFileSystemHelper + m_CustomFileSystemHelper: {fileID: 0} +--- !u!1 &119488 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 404872} + - component: {fileID: 11402440} + m_Layer: 0 + m_Name: Debugger + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &404872 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 119488} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11402440 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 119488} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f05eaceeebe870a4595e51f998ed518b, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Skin: {fileID: 0} + m_ActiveWindow: 0 + m_ShowFullWindow: 0 + m_ConsoleWindow: + m_LockScroll: 1 + m_MaxLine: 100 + m_InfoFilter: 1 + m_WarningFilter: 1 + m_ErrorFilter: 1 + m_FatalFilter: 1 + m_InfoColor: + serializedVersion: 2 + rgba: 4294967295 + m_WarningColor: + serializedVersion: 2 + rgba: 4278512639 + m_ErrorColor: + serializedVersion: 2 + rgba: 4278190335 + m_FatalColor: + serializedVersion: 2 + rgba: 4281545650 +--- !u!1 &126534 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 450964} + - component: {fileID: 11447244} + m_Layer: 0 + m_Name: Web Request + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &450964 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 126534} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11447244 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 126534} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 02988897571ac8b49a59c1a50037bd88, type: 3} + m_Name: + m_EditorClassIdentifier: + m_InstanceRoot: {fileID: 0} + m_WebRequestAgentHelperTypeName: UnityGameFramework.Runtime.UnityWebRequestAgentHelper + m_CustomWebRequestAgentHelper: {fileID: 0} + m_WebRequestAgentHelperCount: 1 + m_Timeout: 30 +--- !u!1 &132194 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 490662} + - component: {fileID: 11459312} + m_Layer: 0 + m_Name: Setting + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &490662 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 132194} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11459312 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 132194} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3c6e05d8d843cd94bb9aa026ed5dc517, type: 3} + m_Name: + m_EditorClassIdentifier: + m_SettingHelperTypeName: UnityGameFramework.Runtime.DefaultSettingHelper + m_CustomSettingHelper: {fileID: 0} +--- !u!1 &137260 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 436184} + - component: {fileID: 11485274} + m_Layer: 0 + m_Name: Config + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &436184 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 137260} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11485274 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 137260} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3e847b2b3e22e9b4792ca7ea6e1714c6, type: 3} + m_Name: + m_EditorClassIdentifier: + m_EnableLoadConfigUpdateEvent: 0 + m_EnableLoadConfigDependencyAssetEvent: 0 + m_ConfigHelperTypeName: UnityGameFramework.Runtime.DefaultConfigHelper + m_CustomConfigHelper: {fileID: 0} + m_CachedBytesSize: 0 +--- !u!1 &139170 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 407686} + - component: {fileID: 11405216} + m_Layer: 0 + m_Name: Procedure + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &407686 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 139170} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11405216 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 139170} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 959bca2b68d03954897f38b1dbb00303, type: 3} + m_Name: + m_EditorClassIdentifier: + m_AvailableProcedureTypeNames: [] + m_EntranceProcedureTypeName: +--- !u!1 &140694 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 463618} + - component: {fileID: 11413340} + m_Layer: 0 + m_Name: Sound + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &463618 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 140694} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11413340 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 140694} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ed5533de69c4e5a4dabc7c23fce1fa98, type: 3} + m_Name: + m_EditorClassIdentifier: + m_EnablePlaySoundUpdateEvent: 0 + m_EnablePlaySoundDependencyAssetEvent: 0 + m_InstanceRoot: {fileID: 0} + m_AudioMixer: {fileID: 0} + m_SoundHelperTypeName: UnityGameFramework.Runtime.DefaultSoundHelper + m_CustomSoundHelper: {fileID: 0} + m_SoundGroupHelperTypeName: UnityGameFramework.Runtime.DefaultSoundGroupHelper + m_CustomSoundGroupHelper: {fileID: 0} + m_SoundAgentHelperTypeName: UnityGameFramework.Runtime.DefaultSoundAgentHelper + m_CustomSoundAgentHelper: {fileID: 0} + m_SoundGroups: [] +--- !u!1 &151938 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 401796} + - component: {fileID: 11457798} + m_Layer: 0 + m_Name: Event + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &401796 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 151938} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11457798 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 151938} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d7daf8320a3d04046b4bbd7c47307914, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &159784 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 431700} + - component: {fileID: 11402158} + m_Layer: 0 + m_Name: Object Pool + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &431700 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 159784} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11402158 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 159784} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1e28a727443c86c40aeb42ff20e0a343, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &167768 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 430602} + - component: {fileID: 11454530} + m_Layer: 0 + m_Name: UI + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &430602 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 167768} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 2378499584788586608} + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11454530 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 167768} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4a1ef15380caaed42b55022cadc93649, type: 3} + m_Name: + m_EditorClassIdentifier: + m_EnableOpenUIFormSuccessEvent: 1 + m_EnableOpenUIFormFailureEvent: 1 + m_EnableOpenUIFormUpdateEvent: 0 + m_EnableOpenUIFormDependencyAssetEvent: 0 + m_EnableCloseUIFormCompleteEvent: 1 + m_InstanceAutoReleaseInterval: 60 + m_InstanceCapacity: 16 + m_InstanceExpireTime: 60 + m_InstancePriority: 0 + m_InstanceRoot: {fileID: 0} + m_UIFormHelperTypeName: UnityGameFramework.Runtime.DefaultUIFormHelper + m_CustomUIFormHelper: {fileID: 0} + m_UIGroupHelperTypeName: UnityGameFramework.Runtime.DefaultUIGroupHelper + m_CustomUIGroupHelper: {fileID: 0} + m_UIGroups: [] +--- !u!1 &176370 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 486648} + - component: {fileID: 11431030} + m_Layer: 0 + m_Name: Network + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &486648 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 176370} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11431030 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 176370} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7afc859893311c34a8d8c2c426ab192d, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &178960 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 455962} + - component: {fileID: 11447582} + m_Layer: 0 + m_Name: Data Node + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &455962 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 178960} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11447582 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 178960} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 67038fd9feefc894aa31ae3869a45b72, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &179612 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 465000} + - component: {fileID: 11451924} + m_Layer: 0 + m_Name: Data Table + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &465000 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 179612} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11451924 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 179612} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 54066418ab853614483ea44b531049f0, type: 3} + m_Name: + m_EditorClassIdentifier: + m_EnableLoadDataTableUpdateEvent: 0 + m_EnableLoadDataTableDependencyAssetEvent: 0 + m_DataTableHelperTypeName: UnityGameFramework.Runtime.DefaultDataTableHelper + m_CustomDataTableHelper: {fileID: 0} + m_CachedBytesSize: 0 +--- !u!1 &180508 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 449996} + - component: {fileID: 11418144} + m_Layer: 0 + m_Name: Scene + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &449996 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 180508} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11418144 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 180508} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b6242b052eb207b40b22e8fe77a315ba, type: 3} + m_Name: + m_EditorClassIdentifier: + m_EnableLoadSceneUpdateEvent: 1 + m_EnableLoadSceneDependencyAssetEvent: 1 +--- !u!1 &189908 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 461836} + - component: {fileID: 11461162} + m_Layer: 0 + m_Name: Reference Pool + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &461836 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 189908} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 433714} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11461162 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 189908} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8ae4d40d7e878bc498492dc9c410d071, type: 3} + m_Name: + m_EditorClassIdentifier: + m_EnableStrictCheck: 0 +--- !u!1 &6165926768569987664 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2378499584788586608} + - component: {fileID: 1899184134033788353} + - component: {fileID: 7534603576128669706} + - component: {fileID: 1017202406165695093} + m_Layer: 5 + m_Name: UI Form Instances + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2378499584788586608 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6165926768569987664} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 430602} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!223 &1899184134033788353 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6165926768569987664} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 1 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 0 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!114 &7534603576128669706 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6165926768569987664} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 1 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 1080, y: 1920} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!114 &1017202406165695093 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6165926768569987664} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/GameFramework.prefab.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/GameFramework.prefab.meta new file mode 100644 index 0000000..2361c78 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/GameFramework.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: adb3eb1c35fcff14f89fba7b05c9d71c +NativeFormatImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization.meta new file mode 100644 index 0000000..972188f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 53c22c721e664fb45b53af7ab274c8af +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/DefaultLocalizationHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/DefaultLocalizationHelper.cs new file mode 100644 index 0000000..b6e3e22 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/DefaultLocalizationHelper.cs @@ -0,0 +1,238 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Localization; +using System; +using System.IO; +using System.Text; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认本地化辅助器。 + /// + public class DefaultLocalizationHelper : LocalizationHelperBase + { + private static readonly string[] ColumnSplitSeparator = new string[] { "\t" }; + private static readonly string BytesAssetExtension = ".bytes"; + private const int ColumnCount = 4; + + private ResourceComponent m_ResourceComponent = null; + + /// + /// 获取系统语言。 + /// + public override Language SystemLanguage + { + get + { + switch (Application.systemLanguage) + { + case UnityEngine.SystemLanguage.Afrikaans: return Language.Afrikaans; + case UnityEngine.SystemLanguage.Arabic: return Language.Arabic; + case UnityEngine.SystemLanguage.Basque: return Language.Basque; + case UnityEngine.SystemLanguage.Belarusian: return Language.Belarusian; + case UnityEngine.SystemLanguage.Bulgarian: return Language.Bulgarian; + case UnityEngine.SystemLanguage.Catalan: return Language.Catalan; + case UnityEngine.SystemLanguage.Chinese: return Language.ChineseSimplified; + case UnityEngine.SystemLanguage.ChineseSimplified: return Language.ChineseSimplified; + case UnityEngine.SystemLanguage.ChineseTraditional: return Language.ChineseTraditional; + case UnityEngine.SystemLanguage.Czech: return Language.Czech; + case UnityEngine.SystemLanguage.Danish: return Language.Danish; + case UnityEngine.SystemLanguage.Dutch: return Language.Dutch; + case UnityEngine.SystemLanguage.English: return Language.English; + case UnityEngine.SystemLanguage.Estonian: return Language.Estonian; + case UnityEngine.SystemLanguage.Faroese: return Language.Faroese; + case UnityEngine.SystemLanguage.Finnish: return Language.Finnish; + case UnityEngine.SystemLanguage.French: return Language.French; + case UnityEngine.SystemLanguage.German: return Language.German; + case UnityEngine.SystemLanguage.Greek: return Language.Greek; + case UnityEngine.SystemLanguage.Hebrew: return Language.Hebrew; + case UnityEngine.SystemLanguage.Hungarian: return Language.Hungarian; + case UnityEngine.SystemLanguage.Icelandic: return Language.Icelandic; + case UnityEngine.SystemLanguage.Indonesian: return Language.Indonesian; + case UnityEngine.SystemLanguage.Italian: return Language.Italian; + case UnityEngine.SystemLanguage.Japanese: return Language.Japanese; + case UnityEngine.SystemLanguage.Korean: return Language.Korean; + case UnityEngine.SystemLanguage.Latvian: return Language.Latvian; + case UnityEngine.SystemLanguage.Lithuanian: return Language.Lithuanian; + case UnityEngine.SystemLanguage.Norwegian: return Language.Norwegian; + case UnityEngine.SystemLanguage.Polish: return Language.Polish; + case UnityEngine.SystemLanguage.Portuguese: return Language.PortuguesePortugal; + case UnityEngine.SystemLanguage.Romanian: return Language.Romanian; + case UnityEngine.SystemLanguage.Russian: return Language.Russian; + case UnityEngine.SystemLanguage.SerboCroatian: return Language.SerboCroatian; + case UnityEngine.SystemLanguage.Slovak: return Language.Slovak; + case UnityEngine.SystemLanguage.Slovenian: return Language.Slovenian; + case UnityEngine.SystemLanguage.Spanish: return Language.Spanish; + case UnityEngine.SystemLanguage.Swedish: return Language.Swedish; + case UnityEngine.SystemLanguage.Thai: return Language.Thai; + case UnityEngine.SystemLanguage.Turkish: return Language.Turkish; + case UnityEngine.SystemLanguage.Ukrainian: return Language.Ukrainian; + case UnityEngine.SystemLanguage.Unknown: return Language.Unspecified; + case UnityEngine.SystemLanguage.Vietnamese: return Language.Vietnamese; + default: return Language.Unspecified; + } + } + } + + /// + /// 读取字典。 + /// + /// 本地化管理器。 + /// 字典资源名称。 + /// 字典资源。 + /// 用户自定义数据。 + /// 是否读取字典成功。 + public override bool ReadData(ILocalizationManager localizationManager, string dictionaryAssetName, object dictionaryAsset, object userData) + { + TextAsset dictionaryTextAsset = dictionaryAsset as TextAsset; + if (dictionaryTextAsset != null) + { + if (dictionaryAssetName.EndsWith(BytesAssetExtension, StringComparison.Ordinal)) + { + return localizationManager.ParseData(dictionaryTextAsset.bytes, userData); + } + else + { + return localizationManager.ParseData(dictionaryTextAsset.text, userData); + } + } + + Log.Warning("Dictionary asset '{0}' is invalid.", dictionaryAssetName); + return false; + } + + /// + /// 读取字典。 + /// + /// 本地化管理器。 + /// 字典资源名称。 + /// 字典二进制流。 + /// 字典二进制流的起始位置。 + /// 字典二进制流的长度。 + /// 用户自定义数据。 + /// 是否读取字典成功。 + public override bool ReadData(ILocalizationManager localizationManager, string dictionaryAssetName, byte[] dictionaryBytes, int startIndex, int length, object userData) + { + if (dictionaryAssetName.EndsWith(BytesAssetExtension, StringComparison.Ordinal)) + { + return localizationManager.ParseData(dictionaryBytes, startIndex, length, userData); + } + else + { + return localizationManager.ParseData(Utility.Converter.GetString(dictionaryBytes, startIndex, length), userData); + } + } + + /// + /// 解析字典。 + /// + /// 本地化管理器。 + /// 要解析的字典字符串。 + /// 用户自定义数据。 + /// 是否解析字典成功。 + public override bool ParseData(ILocalizationManager localizationManager, string dictionaryString, object userData) + { + try + { + int position = 0; + string dictionaryLineString = null; + while ((dictionaryLineString = dictionaryString.ReadLine(ref position)) != null) + { + if (dictionaryLineString[0] == '#') + { + continue; + } + + string[] splitedLine = dictionaryLineString.Split(ColumnSplitSeparator, StringSplitOptions.None); + if (splitedLine.Length != ColumnCount) + { + Log.Warning("Can not parse dictionary line string '{0}' which column count is invalid.", dictionaryLineString); + return false; + } + + string dictionaryKey = splitedLine[1]; + string dictionaryValue = splitedLine[3]; + if (!localizationManager.AddRawString(dictionaryKey, dictionaryValue)) + { + Log.Warning("Can not add raw string with dictionary key '{0}' which may be invalid or duplicate.", dictionaryKey); + return false; + } + } + + return true; + } + catch (Exception exception) + { + Log.Warning("Can not parse dictionary string with exception '{0}'.", exception); + return false; + } + } + + /// + /// 解析字典。 + /// + /// 本地化管理器。 + /// 要解析的字典二进制流。 + /// 字典二进制流的起始位置。 + /// 字典二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析字典成功。 + public override bool ParseData(ILocalizationManager localizationManager, byte[] dictionaryBytes, int startIndex, int length, object userData) + { + try + { + using (MemoryStream memoryStream = new MemoryStream(dictionaryBytes, startIndex, length, false)) + { + using (BinaryReader binaryReader = new BinaryReader(memoryStream, Encoding.UTF8)) + { + while (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length) + { + string dictionaryKey = binaryReader.ReadString(); + string dictionaryValue = binaryReader.ReadString(); + if (!localizationManager.AddRawString(dictionaryKey, dictionaryValue)) + { + Log.Warning("Can not add raw string with dictionary key '{0}' which may be invalid or duplicate.", dictionaryKey); + return false; + } + } + } + } + + return true; + } + catch (Exception exception) + { + Log.Warning("Can not parse dictionary bytes with exception '{0}'.", exception); + return false; + } + } + + /// + /// 释放字典资源。 + /// + /// 本地化管理器。 + /// 要释放的字典资源。 + public override void ReleaseDataAsset(ILocalizationManager localizationManager, object dictionaryAsset) + { + m_ResourceComponent.UnloadAsset(dictionaryAsset); + } + + private void Start() + { + m_ResourceComponent = GameEntry.GetComponent(); + if (m_ResourceComponent == null) + { + Log.Fatal("Resource component is invalid."); + return; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/DefaultLocalizationHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/DefaultLocalizationHelper.cs.meta new file mode 100644 index 0000000..86e3ed7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/DefaultLocalizationHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 57465d541030d834b9d764c79af94e2e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryDependencyAssetEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryDependencyAssetEventArgs.cs new file mode 100644 index 0000000..3d3ab19 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryDependencyAssetEventArgs.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载字典时加载依赖资源事件。 + /// + public sealed class LoadDictionaryDependencyAssetEventArgs : GameEventArgs + { + /// + /// 加载字典时加载依赖资源事件编号。 + /// + public static readonly int EventId = typeof(LoadDictionaryDependencyAssetEventArgs).GetHashCode(); + + /// + /// 初始化加载字典时加载依赖资源事件的新实例。 + /// + public LoadDictionaryDependencyAssetEventArgs() + { + DictionaryAssetName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + + /// + /// 获取加载字典时加载依赖资源事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取字典资源名称。 + /// + public string DictionaryAssetName + { + get; + private set; + } + + /// + /// 获取被加载的依赖资源名称。 + /// + public string DependencyAssetName + { + get; + private set; + } + + /// + /// 获取当前已加载依赖资源数量。 + /// + public int LoadedCount + { + get; + private set; + } + + /// + /// 获取总共加载依赖资源数量。 + /// + public int TotalCount + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载字典时加载依赖资源事件。 + /// + /// 内部事件。 + /// 创建的加载字典时加载依赖资源事件。 + public static LoadDictionaryDependencyAssetEventArgs Create(ReadDataDependencyAssetEventArgs e) + { + LoadDictionaryDependencyAssetEventArgs loadDictionaryDependencyAssetEventArgs = ReferencePool.Acquire(); + loadDictionaryDependencyAssetEventArgs.DictionaryAssetName = e.DataAssetName; + loadDictionaryDependencyAssetEventArgs.DependencyAssetName = e.DependencyAssetName; + loadDictionaryDependencyAssetEventArgs.LoadedCount = e.LoadedCount; + loadDictionaryDependencyAssetEventArgs.TotalCount = e.TotalCount; + loadDictionaryDependencyAssetEventArgs.UserData = e.UserData; + return loadDictionaryDependencyAssetEventArgs; + } + + /// + /// 清理加载字典时加载依赖资源事件。 + /// + public override void Clear() + { + DictionaryAssetName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryDependencyAssetEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryDependencyAssetEventArgs.cs.meta new file mode 100644 index 0000000..d392e63 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryDependencyAssetEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1b3481fe69ce20a49ad4735ec0d2b9dc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryFailureEventArgs.cs new file mode 100644 index 0000000..ed8415e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryFailureEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载字典失败事件。 + /// + public sealed class LoadDictionaryFailureEventArgs : GameEventArgs + { + /// + /// 加载字典失败事件编号。 + /// + public static readonly int EventId = typeof(LoadDictionaryFailureEventArgs).GetHashCode(); + + /// + /// 初始化加载字典失败事件的新实例。 + /// + public LoadDictionaryFailureEventArgs() + { + DictionaryAssetName = null; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取加载字典失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取字典资源名称。 + /// + public string DictionaryAssetName + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载字典失败事件。 + /// + /// 内部事件。 + /// 创建的加载字典失败事件。 + public static LoadDictionaryFailureEventArgs Create(ReadDataFailureEventArgs e) + { + LoadDictionaryFailureEventArgs loadDictionaryFailureEventArgs = ReferencePool.Acquire(); + loadDictionaryFailureEventArgs.DictionaryAssetName = e.DataAssetName; + loadDictionaryFailureEventArgs.ErrorMessage = e.ErrorMessage; + loadDictionaryFailureEventArgs.UserData = e.UserData; + return loadDictionaryFailureEventArgs; + } + + /// + /// 清理加载字典失败事件。 + /// + public override void Clear() + { + DictionaryAssetName = null; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryFailureEventArgs.cs.meta new file mode 100644 index 0000000..c91b52e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 82e68c5abc85cb346b4dd03c73bb8c10 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionarySuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionarySuccessEventArgs.cs new file mode 100644 index 0000000..cfd7153 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionarySuccessEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载字典成功事件。 + /// + public sealed class LoadDictionarySuccessEventArgs : GameEventArgs + { + /// + /// 加载字典成功事件编号。 + /// + public static readonly int EventId = typeof(LoadDictionarySuccessEventArgs).GetHashCode(); + + /// + /// 初始化加载字典成功事件的新实例。 + /// + public LoadDictionarySuccessEventArgs() + { + DictionaryAssetName = null; + Duration = 0f; + UserData = null; + } + + /// + /// 获取加载字典成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取字典资源名称。 + /// + public string DictionaryAssetName + { + get; + private set; + } + + /// + /// 获取加载持续时间。 + /// + public float Duration + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载字典成功事件。 + /// + /// 内部事件。 + /// 创建的加载字典成功事件。 + public static LoadDictionarySuccessEventArgs Create(ReadDataSuccessEventArgs e) + { + LoadDictionarySuccessEventArgs loadDictionarySuccessEventArgs = ReferencePool.Acquire(); + loadDictionarySuccessEventArgs.DictionaryAssetName = e.DataAssetName; + loadDictionarySuccessEventArgs.Duration = e.Duration; + loadDictionarySuccessEventArgs.UserData = e.UserData; + return loadDictionarySuccessEventArgs; + } + + /// + /// 清理加载字典成功事件。 + /// + public override void Clear() + { + DictionaryAssetName = null; + Duration = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionarySuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionarySuccessEventArgs.cs.meta new file mode 100644 index 0000000..ee1df06 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionarySuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 21fad28624e6eca4e86242e3fe512359 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryUpdateEventArgs.cs new file mode 100644 index 0000000..115d1be --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryUpdateEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载字典更新事件。 + /// + public sealed class LoadDictionaryUpdateEventArgs : GameEventArgs + { + /// + /// 加载字典更新事件编号。 + /// + public static readonly int EventId = typeof(LoadDictionaryUpdateEventArgs).GetHashCode(); + + /// + /// 初始化加载字典更新事件的新实例。 + /// + public LoadDictionaryUpdateEventArgs() + { + DictionaryAssetName = null; + Progress = 0f; + UserData = null; + } + + /// + /// 获取加载字典更新事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取字典资源名称。 + /// + public string DictionaryAssetName + { + get; + private set; + } + + /// + /// 获取加载字典进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载字典更新事件。 + /// + /// 内部事件。 + /// 创建的加载字典更新事件。 + public static LoadDictionaryUpdateEventArgs Create(ReadDataUpdateEventArgs e) + { + LoadDictionaryUpdateEventArgs loadDictionaryUpdateEventArgs = ReferencePool.Acquire(); + loadDictionaryUpdateEventArgs.DictionaryAssetName = e.DataAssetName; + loadDictionaryUpdateEventArgs.Progress = e.Progress; + loadDictionaryUpdateEventArgs.UserData = e.UserData; + return loadDictionaryUpdateEventArgs; + } + + /// + /// 清理加载字典更新事件。 + /// + public override void Clear() + { + DictionaryAssetName = null; + Progress = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryUpdateEventArgs.cs.meta new file mode 100644 index 0000000..df04e44 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LoadDictionaryUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 067358629da8fc440b396eea65bb6434 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LocalizationComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LocalizationComponent.cs new file mode 100644 index 0000000..02e7a4b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LocalizationComponent.cs @@ -0,0 +1,789 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Localization; +using GameFramework.Resource; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 本地化组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Localization")] + public sealed class LocalizationComponent : GameFrameworkComponent + { + private const int DefaultPriority = 0; + + private ILocalizationManager m_LocalizationManager = null; + private EventComponent m_EventComponent = null; + + [SerializeField] + private bool m_EnableLoadDictionaryUpdateEvent = false; + + [SerializeField] + private bool m_EnableLoadDictionaryDependencyAssetEvent = false; + + [SerializeField] + private string m_LocalizationHelperTypeName = "UnityGameFramework.Runtime.DefaultLocalizationHelper"; + + [SerializeField] + private LocalizationHelperBase m_CustomLocalizationHelper = null; + + [SerializeField] + private int m_CachedBytesSize = 0; + + /// + /// 获取或设置本地化语言。 + /// + public Language Language + { + get + { + return m_LocalizationManager.Language; + } + set + { + m_LocalizationManager.Language = value; + } + } + + /// + /// 获取系统语言。 + /// + public Language SystemLanguage + { + get + { + return m_LocalizationManager.SystemLanguage; + } + } + + /// + /// 获取字典数量。 + /// + public int DictionaryCount + { + get + { + return m_LocalizationManager.DictionaryCount; + } + } + + /// + /// 获取缓冲二进制流的大小。 + /// + public int CachedBytesSize + { + get + { + return m_LocalizationManager.CachedBytesSize; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_LocalizationManager = GameFrameworkEntry.GetModule(); + if (m_LocalizationManager == null) + { + Log.Fatal("Localization manager is invalid."); + return; + } + + m_LocalizationManager.ReadDataSuccess += OnReadDataSuccess; + m_LocalizationManager.ReadDataFailure += OnReadDataFailure; + + if (m_EnableLoadDictionaryUpdateEvent) + { + m_LocalizationManager.ReadDataUpdate += OnReadDataUpdate; + } + + if (m_EnableLoadDictionaryDependencyAssetEvent) + { + m_LocalizationManager.ReadDataDependencyAsset += OnReadDataDependencyAsset; + } + } + + private void Start() + { + BaseComponent baseComponent = GameEntry.GetComponent(); + if (baseComponent == null) + { + Log.Fatal("Base component is invalid."); + return; + } + + m_EventComponent = GameEntry.GetComponent(); + if (m_EventComponent == null) + { + Log.Fatal("Event component is invalid."); + return; + } + + if (baseComponent.EditorResourceMode) + { + m_LocalizationManager.SetResourceManager(baseComponent.EditorResourceHelper); + } + else + { + m_LocalizationManager.SetResourceManager(GameFrameworkEntry.GetModule()); + } + + LocalizationHelperBase localizationHelper = Helper.CreateHelper(m_LocalizationHelperTypeName, m_CustomLocalizationHelper); + if (localizationHelper == null) + { + Log.Error("Can not create localization helper."); + return; + } + + localizationHelper.name = "Localization Helper"; + Transform transform = localizationHelper.transform; + transform.SetParent(this.transform); + transform.localScale = Vector3.one; + + m_LocalizationManager.SetDataProviderHelper(localizationHelper); + m_LocalizationManager.SetLocalizationHelper(localizationHelper); + m_LocalizationManager.Language = baseComponent.EditorResourceMode && baseComponent.EditorLanguage != Language.Unspecified ? baseComponent.EditorLanguage : m_LocalizationManager.SystemLanguage; + if (m_CachedBytesSize > 0) + { + EnsureCachedBytesSize(m_CachedBytesSize); + } + } + + /// + /// 确保二进制流缓存分配足够大小的内存并缓存。 + /// + /// 要确保二进制流缓存分配内存的大小。 + public void EnsureCachedBytesSize(int ensureSize) + { + m_LocalizationManager.EnsureCachedBytesSize(ensureSize); + } + + /// + /// 释放缓存的二进制流。 + /// + public void FreeCachedBytes() + { + m_LocalizationManager.FreeCachedBytes(); + } + + /// + /// 读取字典。 + /// + /// 字典资源名称。 + public void ReadData(string dictionaryAssetName) + { + m_LocalizationManager.ReadData(dictionaryAssetName); + } + + /// + /// 读取字典。 + /// + /// 字典资源名称。 + /// 加载字典资源的优先级。 + public void ReadData(string dictionaryAssetName, int priority) + { + m_LocalizationManager.ReadData(dictionaryAssetName, priority); + } + + /// + /// 读取字典。 + /// + /// 字典资源名称。 + /// 用户自定义数据。 + public void ReadData(string dictionaryAssetName, object userData) + { + m_LocalizationManager.ReadData(dictionaryAssetName, userData); + } + + /// + /// 读取字典。 + /// + /// 字典资源名称。 + /// 加载字典资源的优先级。 + /// 用户自定义数据。 + public void ReadData(string dictionaryAssetName, int priority, object userData) + { + m_LocalizationManager.ReadData(dictionaryAssetName, priority, userData); + } + + /// + /// 解析字典。 + /// + /// 要解析的字典字符串。 + /// 是否解析字典成功。 + public bool ParseData(string dictionaryString) + { + return m_LocalizationManager.ParseData(dictionaryString); + } + + /// + /// 解析字典。 + /// + /// 要解析的字典字符串。 + /// 用户自定义数据。 + /// 是否解析字典成功。 + public bool ParseData(string dictionaryString, object userData) + { + return m_LocalizationManager.ParseData(dictionaryString, userData); + } + + /// + /// 解析字典。 + /// + /// 要解析的字典二进制流。 + /// 是否解析字典成功。 + public bool ParseData(byte[] dictionaryBytes) + { + return m_LocalizationManager.ParseData(dictionaryBytes); + } + + /// + /// 解析字典。 + /// + /// 要解析的字典二进制流。 + /// 用户自定义数据。 + /// 是否解析字典成功。 + public bool ParseData(byte[] dictionaryBytes, object userData) + { + return m_LocalizationManager.ParseData(dictionaryBytes, userData); + } + + /// + /// 解析字典。 + /// + /// 要解析的字典二进制流。 + /// 字典二进制流的起始位置。 + /// 字典二进制流的长度。 + /// 是否解析字典成功。 + public bool ParseData(byte[] dictionaryBytes, int startIndex, int length) + { + return m_LocalizationManager.ParseData(dictionaryBytes, startIndex, length); + } + + /// + /// 解析字典。 + /// + /// 要解析的字典二进制流。 + /// 字典二进制流的起始位置。 + /// 字典二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析字典成功。 + public bool ParseData(byte[] dictionaryBytes, int startIndex, int length, object userData) + { + return m_LocalizationManager.ParseData(dictionaryBytes, startIndex, length, userData); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典主键。 + /// 要获取的字典内容字符串。 + public string GetString(string key) + { + return m_LocalizationManager.GetString(key); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数的类型。 + /// 字典主键。 + /// 字典参数。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T arg) + { + return m_LocalizationManager.GetString(key, arg); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2) + { + return m_LocalizationManager.GetString(key, arg1, arg2); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4, arg5); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4, arg5, arg6); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典参数 13 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 字典参数 13。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典参数 13 的类型。 + /// 字典参数 14 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 字典参数 13。 + /// 字典参数 14。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典参数 13 的类型。 + /// 字典参数 14 的类型。 + /// 字典参数 15 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 字典参数 13。 + /// 字典参数 14。 + /// 字典参数 15。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); + } + + /// + /// 根据字典主键获取字典内容字符串。 + /// + /// 字典参数 1 的类型。 + /// 字典参数 2 的类型。 + /// 字典参数 3 的类型。 + /// 字典参数 4 的类型。 + /// 字典参数 5 的类型。 + /// 字典参数 6 的类型。 + /// 字典参数 7 的类型。 + /// 字典参数 8 的类型。 + /// 字典参数 9 的类型。 + /// 字典参数 10 的类型。 + /// 字典参数 11 的类型。 + /// 字典参数 12 的类型。 + /// 字典参数 13 的类型。 + /// 字典参数 14 的类型。 + /// 字典参数 15 的类型。 + /// 字典参数 16 的类型。 + /// 字典主键。 + /// 字典参数 1。 + /// 字典参数 2。 + /// 字典参数 3。 + /// 字典参数 4。 + /// 字典参数 5。 + /// 字典参数 6。 + /// 字典参数 7。 + /// 字典参数 8。 + /// 字典参数 9。 + /// 字典参数 10。 + /// 字典参数 11。 + /// 字典参数 12。 + /// 字典参数 13。 + /// 字典参数 14。 + /// 字典参数 15。 + /// 字典参数 16。 + /// 要获取的字典内容字符串。 + public string GetString(string key, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + return m_LocalizationManager.GetString(key, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); + } + + /// + /// 是否存在字典。 + /// + /// 字典主键。 + /// 是否存在字典。 + public bool HasRawString(string key) + { + return m_LocalizationManager.HasRawString(key); + } + + /// + /// 根据字典主键获取字典值。 + /// + /// 字典主键。 + /// 字典值。 + public string GetRawString(string key) + { + return m_LocalizationManager.GetRawString(key); + } + + /// + /// 移除字典。 + /// + /// 字典主键。 + /// 是否移除字典成功。 + public bool RemoveRawString(string key) + { + return m_LocalizationManager.RemoveRawString(key); + } + + /// + /// 清空所有字典。 + /// + public void RemoveAllRawStrings() + { + m_LocalizationManager.RemoveAllRawStrings(); + } + + private void OnReadDataSuccess(object sender, ReadDataSuccessEventArgs e) + { + m_EventComponent.Fire(this, LoadDictionarySuccessEventArgs.Create(e)); + } + + private void OnReadDataFailure(object sender, ReadDataFailureEventArgs e) + { + Log.Warning("Load dictionary failure, asset name '{0}', error message '{1}'.", e.DataAssetName, e.ErrorMessage); + m_EventComponent.Fire(this, LoadDictionaryFailureEventArgs.Create(e)); + } + + private void OnReadDataUpdate(object sender, ReadDataUpdateEventArgs e) + { + m_EventComponent.Fire(this, LoadDictionaryUpdateEventArgs.Create(e)); + } + + private void OnReadDataDependencyAsset(object sender, ReadDataDependencyAssetEventArgs e) + { + m_EventComponent.Fire(this, LoadDictionaryDependencyAssetEventArgs.Create(e)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LocalizationComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LocalizationComponent.cs.meta new file mode 100644 index 0000000..4a6e097 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LocalizationComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 706e6317a59f61044b2805be79f6b284 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LocalizationHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LocalizationHelperBase.cs new file mode 100644 index 0000000..65f6839 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LocalizationHelperBase.cs @@ -0,0 +1,76 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Localization; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 本地化辅助器基类。 + /// + public abstract class LocalizationHelperBase : MonoBehaviour, IDataProviderHelper, ILocalizationHelper + { + /// + /// 获取系统语言。 + /// + public abstract Language SystemLanguage + { + get; + } + + /// + /// 读取字典。 + /// + /// 本地化管理器。 + /// 字典资源名称。 + /// 字典资源。 + /// 用户自定义数据。 + /// 是否读取字典成功。 + public abstract bool ReadData(ILocalizationManager localizationManager, string dictionaryAssetName, object dictionaryAsset, object userData); + + /// + /// 读取字典。 + /// + /// 本地化管理器。 + /// 字典资源名称。 + /// 字典二进制流。 + /// 字典二进制流的起始位置。 + /// 字典二进制流的长度。 + /// 用户自定义数据。 + /// 是否读取字典成功。 + public abstract bool ReadData(ILocalizationManager localizationManager, string dictionaryAssetName, byte[] dictionaryBytes, int startIndex, int length, object userData); + + /// + /// 解析字典。 + /// + /// 本地化管理器。 + /// 要解析的字典字符串。 + /// 用户自定义数据。 + /// 是否解析字典成功。 + public abstract bool ParseData(ILocalizationManager localizationManager, string dictionaryString, object userData); + + /// + /// 解析字典。 + /// + /// 本地化管理器。 + /// 要解析的字典二进制流。 + /// 字典二进制流的起始位置。 + /// 字典二进制流的长度。 + /// 用户自定义数据。 + /// 是否解析字典成功。 + public abstract bool ParseData(ILocalizationManager localizationManager, byte[] dictionaryBytes, int startIndex, int length, object userData); + + /// + /// 释放字典资源。 + /// + /// 本地化管理器。 + /// 要释放的字典资源。 + public abstract void ReleaseDataAsset(ILocalizationManager localizationManager, object dictionaryAsset); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LocalizationHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LocalizationHelperBase.cs.meta new file mode 100644 index 0000000..da9a632 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Localization/LocalizationHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 91f20cfd35b8d804ab29f8c3bc25fed8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network.meta new file mode 100644 index 0000000..99172e1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e6bed9f3b15b3d64190301c8d908142a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkClosedEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkClosedEventArgs.cs new file mode 100644 index 0000000..0bb2e06 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkClosedEventArgs.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using GameFramework.Network; + +namespace UnityGameFramework.Runtime +{ + /// + /// 网络连接关闭事件。 + /// + public sealed class NetworkClosedEventArgs : GameEventArgs + { + /// + /// 网络连接关闭事件编号。 + /// + public static readonly int EventId = typeof(NetworkClosedEventArgs).GetHashCode(); + + /// + /// 初始化网络连接关闭事件的新实例。 + /// + public NetworkClosedEventArgs() + { + NetworkChannel = null; + } + + /// + /// 获取网络连接关闭事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取网络频道。 + /// + public INetworkChannel NetworkChannel + { + get; + private set; + } + + /// + /// 创建网络连接关闭事件。 + /// + /// 内部事件。 + /// 创建的网络连接关闭事件。 + public static NetworkClosedEventArgs Create(GameFramework.Network.NetworkClosedEventArgs e) + { + NetworkClosedEventArgs networkClosedEventArgs = ReferencePool.Acquire(); + networkClosedEventArgs.NetworkChannel = e.NetworkChannel; + return networkClosedEventArgs; + } + + /// + /// 清理网络连接关闭事件。 + /// + public override void Clear() + { + NetworkChannel = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkClosedEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkClosedEventArgs.cs.meta new file mode 100644 index 0000000..44d3041 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkClosedEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 47e152dade5b74240ae4e03d817452cf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkComponent.cs new file mode 100644 index 0000000..9ae415b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkComponent.cs @@ -0,0 +1,152 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Network; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 网络组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Network")] + public sealed class NetworkComponent : GameFrameworkComponent + { + private INetworkManager m_NetworkManager = null; + private EventComponent m_EventComponent = null; + + /// + /// 获取网络频道数量。 + /// + public int NetworkChannelCount + { + get + { + return m_NetworkManager.NetworkChannelCount; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_NetworkManager = GameFrameworkEntry.GetModule(); + if (m_NetworkManager == null) + { + Log.Fatal("Network manager is invalid."); + return; + } + + m_NetworkManager.NetworkConnected += OnNetworkConnected; + m_NetworkManager.NetworkClosed += OnNetworkClosed; + m_NetworkManager.NetworkMissHeartBeat += OnNetworkMissHeartBeat; + m_NetworkManager.NetworkError += OnNetworkError; + m_NetworkManager.NetworkCustomError += OnNetworkCustomError; + } + + private void Start() + { + m_EventComponent = GameEntry.GetComponent(); + if (m_EventComponent == null) + { + Log.Fatal("Event component is invalid."); + return; + } + } + + /// + /// 检查是否存在网络频道。 + /// + /// 网络频道名称。 + /// 是否存在网络频道。 + public bool HasNetworkChannel(string name) + { + return m_NetworkManager.HasNetworkChannel(name); + } + + /// + /// 获取网络频道。 + /// + /// 网络频道名称。 + /// 要获取的网络频道。 + public INetworkChannel GetNetworkChannel(string name) + { + return m_NetworkManager.GetNetworkChannel(name); + } + + /// + /// 获取所有网络频道。 + /// + /// 所有网络频道。 + public INetworkChannel[] GetAllNetworkChannels() + { + return m_NetworkManager.GetAllNetworkChannels(); + } + + /// + /// 获取所有网络频道。 + /// + /// 所有网络频道。 + public void GetAllNetworkChannels(List results) + { + m_NetworkManager.GetAllNetworkChannels(results); + } + + /// + /// 创建网络频道。 + /// + /// 网络频道名称。 + /// 网络服务类型。 + /// 网络频道辅助器。 + /// 要创建的网络频道。 + public INetworkChannel CreateNetworkChannel(string name, ServiceType serviceType, INetworkChannelHelper networkChannelHelper) + { + return m_NetworkManager.CreateNetworkChannel(name, serviceType, networkChannelHelper); + } + + /// + /// 销毁网络频道。 + /// + /// 网络频道名称。 + /// 是否销毁网络频道成功。 + public bool DestroyNetworkChannel(string name) + { + return m_NetworkManager.DestroyNetworkChannel(name); + } + + private void OnNetworkConnected(object sender, GameFramework.Network.NetworkConnectedEventArgs e) + { + m_EventComponent.Fire(this, NetworkConnectedEventArgs.Create(e)); + } + + private void OnNetworkClosed(object sender, GameFramework.Network.NetworkClosedEventArgs e) + { + m_EventComponent.Fire(this, NetworkClosedEventArgs.Create(e)); + } + + private void OnNetworkMissHeartBeat(object sender, GameFramework.Network.NetworkMissHeartBeatEventArgs e) + { + m_EventComponent.Fire(this, NetworkMissHeartBeatEventArgs.Create(e)); + } + + private void OnNetworkError(object sender, GameFramework.Network.NetworkErrorEventArgs e) + { + m_EventComponent.Fire(this, NetworkErrorEventArgs.Create(e)); + } + + private void OnNetworkCustomError(object sender, GameFramework.Network.NetworkCustomErrorEventArgs e) + { + m_EventComponent.Fire(this, NetworkCustomErrorEventArgs.Create(e)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkComponent.cs.meta new file mode 100644 index 0000000..ebf97f2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7afc859893311c34a8d8c2c426ab192d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkConnectedEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkConnectedEventArgs.cs new file mode 100644 index 0000000..c537376 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkConnectedEventArgs.cs @@ -0,0 +1,84 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using GameFramework.Network; + +namespace UnityGameFramework.Runtime +{ + /// + /// 网络连接成功事件。 + /// + public sealed class NetworkConnectedEventArgs : GameEventArgs + { + /// + /// 网络连接成功事件编号。 + /// + public static readonly int EventId = typeof(NetworkConnectedEventArgs).GetHashCode(); + + /// + /// 初始化网络连接成功事件的新实例。 + /// + public NetworkConnectedEventArgs() + { + NetworkChannel = null; + UserData = null; + } + + /// + /// 获取网络连接成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取网络频道。 + /// + public INetworkChannel NetworkChannel + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建网络连接成功事件。 + /// + /// 内部事件。 + /// 创建的网络连接成功事件。 + public static NetworkConnectedEventArgs Create(GameFramework.Network.NetworkConnectedEventArgs e) + { + NetworkConnectedEventArgs networkConnectedEventArgs = ReferencePool.Acquire(); + networkConnectedEventArgs.NetworkChannel = e.NetworkChannel; + networkConnectedEventArgs.UserData = e.UserData; + return networkConnectedEventArgs; + } + + /// + /// 清理网络连接成功事件。 + /// + public override void Clear() + { + NetworkChannel = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkConnectedEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkConnectedEventArgs.cs.meta new file mode 100644 index 0000000..ac34ffc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkConnectedEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 980f3ac1c6457c64281b99ea2fc94384 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkCustomErrorEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkCustomErrorEventArgs.cs new file mode 100644 index 0000000..e9977e7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkCustomErrorEventArgs.cs @@ -0,0 +1,84 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using GameFramework.Network; + +namespace UnityGameFramework.Runtime +{ + /// + /// 用户自定义网络错误事件。 + /// + public sealed class NetworkCustomErrorEventArgs : GameEventArgs + { + /// + /// 用户自定义网络错误事件编号。 + /// + public static readonly int EventId = typeof(NetworkCustomErrorEventArgs).GetHashCode(); + + /// + /// 初始化用户自定义网络错误事件的新实例。 + /// + public NetworkCustomErrorEventArgs() + { + NetworkChannel = null; + CustomErrorData = null; + } + + /// + /// 获取用户自定义网络错误事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取网络频道。 + /// + public INetworkChannel NetworkChannel + { + get; + private set; + } + + /// + /// 获取用户自定义错误数据。 + /// + public object CustomErrorData + { + get; + private set; + } + + /// + /// 创建用户自定义网络错误事件。 + /// + /// 内部事件。 + /// 创建的用户自定义网络错误事件。 + public static NetworkCustomErrorEventArgs Create(GameFramework.Network.NetworkCustomErrorEventArgs e) + { + NetworkCustomErrorEventArgs networkCustomErrorEventArgs = ReferencePool.Acquire(); + networkCustomErrorEventArgs.NetworkChannel = e.NetworkChannel; + networkCustomErrorEventArgs.CustomErrorData = e.CustomErrorData; + return networkCustomErrorEventArgs; + } + + /// + /// 清理用户自定义网络错误事件。 + /// + public override void Clear() + { + NetworkChannel = null; + CustomErrorData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkCustomErrorEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkCustomErrorEventArgs.cs.meta new file mode 100644 index 0000000..2edeecd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkCustomErrorEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a95c49efb7b92094a98ac60c420c06f1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkErrorEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkErrorEventArgs.cs new file mode 100644 index 0000000..5997e22 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkErrorEventArgs.cs @@ -0,0 +1,107 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using GameFramework.Network; +using System.Net.Sockets; + +namespace UnityGameFramework.Runtime +{ + /// + /// 网络错误事件。 + /// + public sealed class NetworkErrorEventArgs : GameEventArgs + { + /// + /// 网络错误事件编号。 + /// + public static readonly int EventId = typeof(NetworkErrorEventArgs).GetHashCode(); + + /// + /// 初始化网络错误事件的新实例。 + /// + public NetworkErrorEventArgs() + { + NetworkChannel = null; + ErrorCode = NetworkErrorCode.Unknown; + ErrorMessage = null; + } + + /// + /// 获取网络错误事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取网络频道。 + /// + public INetworkChannel NetworkChannel + { + get; + private set; + } + + /// + /// 获取错误码。 + /// + public NetworkErrorCode ErrorCode + { + get; + private set; + } + + /// + /// 获取 Socket 错误码。 + /// + public SocketError SocketErrorCode + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 创建网络错误事件。 + /// + /// 内部事件。 + /// 创建的网络错误事件。 + public static NetworkErrorEventArgs Create(GameFramework.Network.NetworkErrorEventArgs e) + { + NetworkErrorEventArgs networkErrorEventArgs = ReferencePool.Acquire(); + networkErrorEventArgs.NetworkChannel = e.NetworkChannel; + networkErrorEventArgs.ErrorCode = e.ErrorCode; + networkErrorEventArgs.SocketErrorCode = e.SocketErrorCode; + networkErrorEventArgs.ErrorMessage = e.ErrorMessage; + return networkErrorEventArgs; + } + + /// + /// 清理网络错误事件。 + /// + public override void Clear() + { + NetworkChannel = null; + ErrorCode = NetworkErrorCode.Unknown; + ErrorMessage = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkErrorEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkErrorEventArgs.cs.meta new file mode 100644 index 0000000..32e4efd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkErrorEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bf09e20028671e24b97571df241445f5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkMissHeartBeatEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkMissHeartBeatEventArgs.cs new file mode 100644 index 0000000..d327bc6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkMissHeartBeatEventArgs.cs @@ -0,0 +1,84 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using GameFramework.Network; + +namespace UnityGameFramework.Runtime +{ + /// + /// 网络心跳包丢失事件。 + /// + public sealed class NetworkMissHeartBeatEventArgs : GameEventArgs + { + /// + /// 网络心跳包丢失事件编号。 + /// + public static readonly int EventId = typeof(NetworkMissHeartBeatEventArgs).GetHashCode(); + + /// + /// 初始化网络心跳包丢失事件的新实例。 + /// + public NetworkMissHeartBeatEventArgs() + { + NetworkChannel = null; + MissCount = 0; + } + + /// + /// 获取网络心跳包丢失事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取网络频道。 + /// + public INetworkChannel NetworkChannel + { + get; + private set; + } + + /// + /// 获取心跳包已丢失次数。 + /// + public int MissCount + { + get; + private set; + } + + /// + /// 创建网络心跳包丢失事件。 + /// + /// 内部事件。 + /// 创建的网络心跳包丢失事件。 + public static NetworkMissHeartBeatEventArgs Create(GameFramework.Network.NetworkMissHeartBeatEventArgs e) + { + NetworkMissHeartBeatEventArgs networkMissHeartBeatEventArgs = ReferencePool.Acquire(); + networkMissHeartBeatEventArgs.NetworkChannel = e.NetworkChannel; + networkMissHeartBeatEventArgs.MissCount = e.MissCount; + return networkMissHeartBeatEventArgs; + } + + /// + /// 清理网络心跳包丢失事件。 + /// + public override void Clear() + { + NetworkChannel = null; + MissCount = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkMissHeartBeatEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkMissHeartBeatEventArgs.cs.meta new file mode 100644 index 0000000..24947f1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Network/NetworkMissHeartBeatEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc1159a2cf0027947b397dbabbf4da4d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ObjectPool.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ObjectPool.meta new file mode 100644 index 0000000..2aad6b6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ObjectPool.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 82475e8acda14d045a5eee8e09f6bd9b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ObjectPool/ObjectPoolComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ObjectPool/ObjectPoolComponent.cs new file mode 100644 index 0000000..4f0cec0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ObjectPool/ObjectPoolComponent.cs @@ -0,0 +1,1033 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.ObjectPool; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 对象池组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Object Pool")] + public sealed class ObjectPoolComponent : GameFrameworkComponent + { + private IObjectPoolManager m_ObjectPoolManager = null; + + /// + /// 获取对象池数量。 + /// + public int Count + { + get + { + return m_ObjectPoolManager.Count; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_ObjectPoolManager = GameFrameworkEntry.GetModule(); + if (m_ObjectPoolManager == null) + { + Log.Fatal("Object pool manager is invalid."); + return; + } + } + + private void Start() + { + } + + /// + /// 检查是否存在对象池。 + /// + /// 对象类型。 + /// 是否存在对象池。 + public bool HasObjectPool() where T : ObjectBase + { + return m_ObjectPoolManager.HasObjectPool(); + } + + /// + /// 检查是否存在对象池。 + /// + /// 对象类型。 + /// 是否存在对象池。 + public bool HasObjectPool(Type objectType) + { + return m_ObjectPoolManager.HasObjectPool(objectType); + } + + /// + /// 检查是否存在对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 是否存在对象池。 + public bool HasObjectPool(string name) where T : ObjectBase + { + return m_ObjectPoolManager.HasObjectPool(name); + } + + /// + /// 检查是否存在对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 是否存在对象池。 + public bool HasObjectPool(Type objectType, string name) + { + return m_ObjectPoolManager.HasObjectPool(objectType, name); + } + + /// + /// 检查是否存在对象池。 + /// + /// 要检查的条件。 + /// 是否存在对象池。 + public bool HasObjectPool(Predicate condition) + { + return m_ObjectPoolManager.HasObjectPool(condition); + } + + /// + /// 获取对象池。 + /// + /// 对象类型。 + /// 要获取的对象池。 + public IObjectPool GetObjectPool() where T : ObjectBase + { + return m_ObjectPoolManager.GetObjectPool(); + } + + /// + /// 获取对象池。 + /// + /// 对象类型。 + /// 要获取的对象池。 + public ObjectPoolBase GetObjectPool(Type objectType) + { + return m_ObjectPoolManager.GetObjectPool(objectType); + } + + /// + /// 获取对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要获取的对象池。 + public IObjectPool GetObjectPool(string name) where T : ObjectBase + { + return m_ObjectPoolManager.GetObjectPool(name); + } + + /// + /// 获取对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要获取的对象池。 + public ObjectPoolBase GetObjectPool(Type objectType, string name) + { + return m_ObjectPoolManager.GetObjectPool(objectType, name); + } + + /// + /// 获取对象池。 + /// + /// 要检查的条件。 + /// 要获取的对象池。 + public ObjectPoolBase GetObjectPool(Predicate condition) + { + return m_ObjectPoolManager.GetObjectPool(condition); + } + + /// + /// 获取对象池。 + /// + /// 要检查的条件。 + /// 要获取的对象池。 + public ObjectPoolBase[] GetObjectPools(Predicate condition) + { + return m_ObjectPoolManager.GetObjectPools(condition); + } + + /// + /// 获取对象池。 + /// + /// 要检查的条件。 + /// 要获取的对象池。 + public void GetObjectPools(Predicate condition, List results) + { + m_ObjectPoolManager.GetObjectPools(condition, results); + } + + /// + /// 获取所有对象池。 + /// + public ObjectPoolBase[] GetAllObjectPools() + { + return m_ObjectPoolManager.GetAllObjectPools(); + } + + /// + /// 获取所有对象池。 + /// + /// 所有对象池。 + public void GetAllObjectPools(List results) + { + m_ObjectPoolManager.GetAllObjectPools(results); + } + + /// + /// 获取所有对象池。 + /// + /// 是否根据对象池的优先级排序。 + /// 所有对象池。 + public ObjectPoolBase[] GetAllObjectPools(bool sort) + { + return m_ObjectPoolManager.GetAllObjectPools(sort); + } + + /// + /// 获取所有对象池。 + /// + /// 是否根据对象池的优先级排序。 + /// 所有对象池。 + public void GetAllObjectPools(bool sort, List results) + { + m_ObjectPoolManager.GetAllObjectPools(sort, results); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool() where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(name); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, name); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(int capacity) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(capacity); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, int capacity) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, capacity); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(float expireTime) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(expireTime); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, float expireTime) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, expireTime); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, int capacity) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(name, capacity); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, int capacity) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, name, capacity); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, float expireTime) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(name, expireTime); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, float expireTime) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, name, expireTime); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(int capacity, float expireTime) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(capacity, expireTime); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, int capacity, float expireTime) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, capacity, expireTime); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(int capacity, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(capacity, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, int capacity, int priority) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, capacity, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(float expireTime, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, float expireTime, int priority) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, int capacity, float expireTime) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(name, capacity, expireTime); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, int capacity, float expireTime) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, name, capacity, expireTime); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, int capacity, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(name, capacity, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, int capacity, int priority) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, name, capacity, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, float expireTime, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(name, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, float expireTime, int priority) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, name, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(int capacity, float expireTime, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(capacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, int capacity, float expireTime, int priority) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, capacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, int capacity, float expireTime, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(name, capacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, int capacity, float expireTime, int priority) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, name, capacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public IObjectPool CreateSingleSpawnObjectPool(string name, float autoReleaseInterval, int capacity, float expireTime, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(name, autoReleaseInterval, capacity, expireTime, priority); + } + + /// + /// 创建允许单次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许单次获取的对象池。 + public ObjectPoolBase CreateSingleSpawnObjectPool(Type objectType, string name, float autoReleaseInterval, int capacity, float expireTime, int priority) + { + return m_ObjectPoolManager.CreateSingleSpawnObjectPool(objectType, name, autoReleaseInterval, capacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool() where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(name); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, name); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(int capacity) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(capacity); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, int capacity) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, capacity); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(float expireTime) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(expireTime); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, float expireTime) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, expireTime); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, int capacity) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(name, capacity); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, int capacity) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, name, capacity); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, float expireTime) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(name, expireTime); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, float expireTime) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, name, expireTime); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(int capacity, float expireTime) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(capacity, expireTime); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, int capacity, float expireTime) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, capacity, expireTime); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(int capacity, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(capacity, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, int capacity, int priority) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, capacity, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(float expireTime, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, float expireTime, int priority) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, int capacity, float expireTime) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(name, capacity, expireTime); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, int capacity, float expireTime) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, name, capacity, expireTime); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, int capacity, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(name, capacity, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, int capacity, int priority) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, name, capacity, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, float expireTime, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(name, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, float expireTime, int priority) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, name, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(int capacity, float expireTime, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(capacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, int capacity, float expireTime, int priority) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, capacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, int capacity, float expireTime, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(name, capacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, int capacity, float expireTime, int priority) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, name, capacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public IObjectPool CreateMultiSpawnObjectPool(string name, float autoReleaseInterval, int capacity, float expireTime, int priority) where T : ObjectBase + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(name, autoReleaseInterval, capacity, expireTime, priority); + } + + /// + /// 创建允许多次获取的对象池。 + /// + /// 对象类型。 + /// 对象池名称。 + /// 对象池自动释放可释放对象的间隔秒数。 + /// 对象池的容量。 + /// 对象池对象过期秒数。 + /// 对象池的优先级。 + /// 要创建的允许多次获取的对象池。 + public ObjectPoolBase CreateMultiSpawnObjectPool(Type objectType, string name, float autoReleaseInterval, int capacity, float expireTime, int priority) + { + return m_ObjectPoolManager.CreateMultiSpawnObjectPool(objectType, name, autoReleaseInterval, capacity, expireTime, priority); + } + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 是否销毁对象池成功。 + public bool DestroyObjectPool() where T : ObjectBase + { + return m_ObjectPoolManager.DestroyObjectPool(); + } + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 是否销毁对象池成功。 + public bool DestroyObjectPool(Type objectType) + { + return m_ObjectPoolManager.DestroyObjectPool(objectType); + } + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 要销毁的对象池名称。 + /// 是否销毁对象池成功。 + public bool DestroyObjectPool(string name) where T : ObjectBase + { + return m_ObjectPoolManager.DestroyObjectPool(name); + } + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 要销毁的对象池名称。 + /// 是否销毁对象池成功。 + public bool DestroyObjectPool(Type objectType, string name) + { + return m_ObjectPoolManager.DestroyObjectPool(objectType, name); + } + + /// + /// 销毁对象池。 + /// + /// 对象类型。 + /// 要销毁的对象池。 + /// 是否销毁对象池成功。 + public bool DestroyObjectPool(IObjectPool objectPool) where T : ObjectBase + { + return m_ObjectPoolManager.DestroyObjectPool(objectPool); + } + + /// + /// 销毁对象池。 + /// + /// 要销毁的对象池。 + /// 是否销毁对象池成功。 + public bool DestroyObjectPool(ObjectPoolBase objectPool) + { + return m_ObjectPoolManager.DestroyObjectPool(objectPool); + } + + /// + /// 释放对象池中的可释放对象。 + /// + public void Release() + { + Log.Info("Object pool release..."); + m_ObjectPoolManager.Release(); + } + + /// + /// 释放对象池中的所有未使用对象。 + /// + public void ReleaseAllUnused() + { + Log.Info("Object pool release all unused..."); + m_ObjectPoolManager.ReleaseAllUnused(); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ObjectPool/ObjectPoolComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ObjectPool/ObjectPoolComponent.cs.meta new file mode 100644 index 0000000..432ece2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ObjectPool/ObjectPoolComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1e28a727443c86c40aeb42ff20e0a343 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Procedure.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Procedure.meta new file mode 100644 index 0000000..7bad022 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Procedure.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1311dfda55b638740a95b1bba894a2e8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Procedure/ProcedureComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Procedure/ProcedureComponent.cs new file mode 100644 index 0000000..6b19257 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Procedure/ProcedureComponent.cs @@ -0,0 +1,162 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Fsm; +using GameFramework.Procedure; +using System; +using System.Collections; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 流程组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Procedure")] + public sealed class ProcedureComponent : GameFrameworkComponent + { + private IProcedureManager m_ProcedureManager = null; + private ProcedureBase m_EntranceProcedure = null; + + [SerializeField] + private string[] m_AvailableProcedureTypeNames = null; + //private string[] m_AvailableProcedureTypeNames = new string[] + //{ + // "ProcedureCheckResources", + // "ProcedureCheckVersion", + // "ProcedureInitResources", + // "ProcedureLaunch", + // "ProcedureMenu", + // "ProcedurePreload", + // "ProcedureSplash", + // "ProcedureUpdateResources", + // "ProcedureUpdateVersion", + // "ProcedureVerifyResources", + //}; + + [SerializeField] + private string m_EntranceProcedureTypeName = null; + //private string m_EntranceProcedureTypeName = "ProcedureLaunch"; + + /// + /// 获取当前流程。 + /// + public ProcedureBase CurrentProcedure + { + get + { + return m_ProcedureManager.CurrentProcedure; + } + } + + /// + /// 获取当前流程持续时间。 + /// + public float CurrentProcedureTime + { + get + { + return m_ProcedureManager.CurrentProcedureTime; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_ProcedureManager = GameFrameworkEntry.GetModule(); + if (m_ProcedureManager == null) + { + Log.Fatal("Procedure manager is invalid."); + return; + } + } + + private IEnumerator Start() + { + ProcedureBase[] procedures = new ProcedureBase[m_AvailableProcedureTypeNames.Length]; + for (int i = 0; i < m_AvailableProcedureTypeNames.Length; i++) + { + Type procedureType = Utility.Assembly.GetType(m_AvailableProcedureTypeNames[i]); + if (procedureType == null) + { + Log.Error("Can not find procedure type '{0}'.", m_AvailableProcedureTypeNames[i]); + yield break; + } + + procedures[i] = (ProcedureBase)Activator.CreateInstance(procedureType); + if (procedures[i] == null) + { + Log.Error("Can not create procedure instance '{0}'.", m_AvailableProcedureTypeNames[i]); + yield break; + } + + if (m_EntranceProcedureTypeName == m_AvailableProcedureTypeNames[i]) + { + m_EntranceProcedure = procedures[i]; + } + } + + if (m_EntranceProcedure == null) + { + Log.Error("Entrance procedure is invalid."); + yield break; + } + + m_ProcedureManager.Initialize(GameFrameworkEntry.GetModule(), procedures); + + yield return new WaitForEndOfFrame(); + + m_ProcedureManager.StartProcedure(m_EntranceProcedure.GetType()); + } + + /// + /// 是否存在流程。 + /// + /// 要检查的流程类型。 + /// 是否存在流程。 + public bool HasProcedure() where T : ProcedureBase + { + return m_ProcedureManager.HasProcedure(); + } + + /// + /// 是否存在流程。 + /// + /// 要检查的流程类型。 + /// 是否存在流程。 + public bool HasProcedure(Type procedureType) + { + return m_ProcedureManager.HasProcedure(procedureType); + } + + /// + /// 获取流程。 + /// + /// 要获取的流程类型。 + /// 要获取的流程。 + public ProcedureBase GetProcedure() where T : ProcedureBase + { + return m_ProcedureManager.GetProcedure(); + } + + /// + /// 获取流程。 + /// + /// 要获取的流程类型。 + /// 要获取的流程。 + public ProcedureBase GetProcedure(Type procedureType) + { + return m_ProcedureManager.GetProcedure(procedureType); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Procedure/ProcedureComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Procedure/ProcedureComponent.cs.meta new file mode 100644 index 0000000..fb371df --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Procedure/ProcedureComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 959bca2b68d03954897f38b1dbb00303 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool.meta new file mode 100644 index 0000000..86555f9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d8ddcb97e04c6d94aaabafc2ae83cb2b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool/ReferencePoolComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool/ReferencePoolComponent.cs new file mode 100644 index 0000000..818d8ad --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool/ReferencePoolComponent.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 引用池组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/ReferencePool")] + public sealed class ReferencePoolComponent : GameFrameworkComponent + { + [SerializeField] + private ReferenceStrictCheckType m_EnableStrictCheck = ReferenceStrictCheckType.AlwaysEnable; + + /// + /// 获取或设置是否开启强制检查。 + /// + public bool EnableStrictCheck + { + get + { + return ReferencePool.EnableStrictCheck; + } + set + { + ReferencePool.EnableStrictCheck = value; + if (value) + { + Log.Info("Strict checking is enabled for the Reference Pool. It will drastically affect the performance."); + } + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + } + + private void Start() + { + switch (m_EnableStrictCheck) + { + case ReferenceStrictCheckType.AlwaysEnable: + EnableStrictCheck = true; + break; + + case ReferenceStrictCheckType.OnlyEnableWhenDevelopment: + EnableStrictCheck = Debug.isDebugBuild; + break; + + case ReferenceStrictCheckType.OnlyEnableInEditor: + EnableStrictCheck = Application.isEditor; + break; + + default: + EnableStrictCheck = false; + break; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool/ReferencePoolComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool/ReferencePoolComponent.cs.meta new file mode 100644 index 0000000..df72488 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool/ReferencePoolComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8ae4d40d7e878bc498492dc9c410d071 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool/ReferenceStrictCheckType.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool/ReferenceStrictCheckType.cs new file mode 100644 index 0000000..4293c90 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool/ReferenceStrictCheckType.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Runtime +{ + /// + /// 引用强制检查类型。 + /// + public enum ReferenceStrictCheckType : byte + { + /// + /// 总是启用。 + /// + AlwaysEnable = 0, + + /// + /// 仅在开发模式时启用。 + /// + OnlyEnableWhenDevelopment, + + /// + /// 仅在编辑器中启用。 + /// + OnlyEnableInEditor, + + /// + /// 总是禁用。 + /// + AlwaysDisable, + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool/ReferenceStrictCheckType.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool/ReferenceStrictCheckType.cs.meta new file mode 100644 index 0000000..bd6c893 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/ReferencePool/ReferenceStrictCheckType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1abf21b782f0fec40bd37a5f17124b83 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource.meta new file mode 100644 index 0000000..da52a6e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bfb05af2569429d4c9181594977155d9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.LocalVersionListDeserializeCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.LocalVersionListDeserializeCallback.cs new file mode 100644 index 0000000..bdafd50 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.LocalVersionListDeserializeCallback.cs @@ -0,0 +1,114 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System.IO; +using System.Text; + +namespace UnityGameFramework.Runtime +{ + /// + /// 内置版本资源列表序列化器。 + /// + public static partial class BuiltinVersionListSerializer + { + /// + /// 反序列化本地版本资源列表(版本 0)回调函数。 + /// + /// 指定流。 + /// 反序列化的本地版本资源列表(版本 0)。 + public static LocalVersionList LocalVersionListDeserializeCallback_V0(Stream stream) + { + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + byte[] encryptBytes = binaryReader.ReadBytes(CachedHashBytesLength); + int resourceCount = binaryReader.ReadInt32(); + LocalVersionList.Resource[] resources = resourceCount > 0 ? new LocalVersionList.Resource[resourceCount] : null; + for (int i = 0; i < resourceCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + string variant = binaryReader.ReadEncryptedString(encryptBytes); + byte loadType = binaryReader.ReadByte(); + int length = binaryReader.ReadInt32(); + int hashCode = binaryReader.ReadInt32(); + resources[i] = new LocalVersionList.Resource(name, variant, null, loadType, length, hashCode); + } + + return new LocalVersionList(resources, null); + } + } + + /// + /// 反序列化本地版本资源列表(版本 1)回调函数。 + /// + /// 指定流。 + /// 反序列化的本地版本资源列表(版本 1)。 + public static LocalVersionList LocalVersionListDeserializeCallback_V1(Stream stream) + { + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + byte[] encryptBytes = binaryReader.ReadBytes(CachedHashBytesLength); + int resourceCount = binaryReader.Read7BitEncodedInt32(); + LocalVersionList.Resource[] resources = resourceCount > 0 ? new LocalVersionList.Resource[resourceCount] : null; + for (int i = 0; i < resourceCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + string variant = binaryReader.ReadEncryptedString(encryptBytes); + string extension = binaryReader.ReadEncryptedString(encryptBytes) ?? DefaultExtension; + byte loadType = binaryReader.ReadByte(); + int length = binaryReader.Read7BitEncodedInt32(); + int hashCode = binaryReader.ReadInt32(); + resources[i] = new LocalVersionList.Resource(name, variant, extension, loadType, length, hashCode); + } + + return new LocalVersionList(resources, null); + } + } + + /// + /// 反序列化本地版本资源列表(版本 2)回调函数。 + /// + /// 指定流。 + /// 反序列化的本地版本资源列表(版本 2)。 + public static LocalVersionList LocalVersionListDeserializeCallback_V2(Stream stream) + { + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + byte[] encryptBytes = binaryReader.ReadBytes(CachedHashBytesLength); + int resourceCount = binaryReader.Read7BitEncodedInt32(); + LocalVersionList.Resource[] resources = resourceCount > 0 ? new LocalVersionList.Resource[resourceCount] : null; + for (int i = 0; i < resourceCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + string variant = binaryReader.ReadEncryptedString(encryptBytes); + string extension = binaryReader.ReadEncryptedString(encryptBytes) ?? DefaultExtension; + byte loadType = binaryReader.ReadByte(); + int length = binaryReader.Read7BitEncodedInt32(); + int hashCode = binaryReader.ReadInt32(); + resources[i] = new LocalVersionList.Resource(name, variant, extension, loadType, length, hashCode); + } + + int fileSystemCount = binaryReader.Read7BitEncodedInt32(); + LocalVersionList.FileSystem[] fileSystems = fileSystemCount > 0 ? new LocalVersionList.FileSystem[fileSystemCount] : null; + for (int i = 0; i < fileSystemCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int resourceIndexCount = binaryReader.Read7BitEncodedInt32(); + int[] resourceIndexes = resourceIndexCount > 0 ? new int[resourceIndexCount] : null; + for (int j = 0; j < resourceIndexCount; j++) + { + resourceIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + fileSystems[i] = new LocalVersionList.FileSystem(name, resourceIndexes); + } + + return new LocalVersionList(resources, fileSystems); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.LocalVersionListDeserializeCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.LocalVersionListDeserializeCallback.cs.meta new file mode 100644 index 0000000..c57ed16 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.LocalVersionListDeserializeCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: df66ad097f961904fb7bca9ea86b226f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.LocalVersionListSerializeCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.LocalVersionListSerializeCallback.cs new file mode 100644 index 0000000..faabcc5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.LocalVersionListSerializeCallback.cs @@ -0,0 +1,135 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Resource; +using System; +using System.IO; +using System.Text; + +namespace UnityGameFramework.Runtime +{ + /// + /// 内置版本资源列表序列化器。 + /// + public static partial class BuiltinVersionListSerializer + { + /// + /// 序列化本地版本资源列表(版本 0)回调函数。 + /// + /// 目标流。 + /// 要序列化的本地版本资源列表(版本 0)。 + /// 是否序列化本地版本资源列表(版本 0)成功。 + public static bool LocalVersionListSerializeCallback_V0(Stream stream, LocalVersionList versionList) + { + if (!versionList.IsValid) + { + return false; + } + + Utility.Random.GetRandomBytes(s_CachedHashBytes); + using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.UTF8)) + { + binaryWriter.Write(s_CachedHashBytes); + LocalVersionList.Resource[] resources = versionList.GetResources(); + binaryWriter.Write(resources.Length); + foreach (LocalVersionList.Resource resource in resources) + { + binaryWriter.WriteEncryptedString(resource.Name, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Variant, s_CachedHashBytes); + binaryWriter.Write(resource.LoadType); + binaryWriter.Write(resource.Length); + binaryWriter.Write(resource.HashCode); + } + } + + Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength); + return true; + } + + /// + /// 序列化本地版本资源列表(版本 1)回调函数。 + /// + /// 目标流。 + /// 要序列化的本地版本资源列表(版本 1)。 + /// 是否序列化本地版本资源列表(版本 1)成功。 + public static bool LocalVersionListSerializeCallback_V1(Stream stream, LocalVersionList versionList) + { + if (!versionList.IsValid) + { + return false; + } + + Utility.Random.GetRandomBytes(s_CachedHashBytes); + using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.UTF8)) + { + binaryWriter.Write(s_CachedHashBytes); + LocalVersionList.Resource[] resources = versionList.GetResources(); + binaryWriter.Write7BitEncodedInt32(resources.Length); + foreach (LocalVersionList.Resource resource in resources) + { + binaryWriter.WriteEncryptedString(resource.Name, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Variant, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Extension != DefaultExtension ? resource.Extension : null, s_CachedHashBytes); + binaryWriter.Write(resource.LoadType); + binaryWriter.Write7BitEncodedInt32(resource.Length); + binaryWriter.Write(resource.HashCode); + } + } + + Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength); + return true; + } + + /// + /// 序列化本地版本资源列表(版本 2)回调函数。 + /// + /// 目标流。 + /// 要序列化的本地版本资源列表(版本 2)。 + /// 是否序列化本地版本资源列表(版本 2)成功。 + public static bool LocalVersionListSerializeCallback_V2(Stream stream, LocalVersionList versionList) + { + if (!versionList.IsValid) + { + return false; + } + + Utility.Random.GetRandomBytes(s_CachedHashBytes); + using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.UTF8)) + { + binaryWriter.Write(s_CachedHashBytes); + LocalVersionList.Resource[] resources = versionList.GetResources(); + binaryWriter.Write7BitEncodedInt32(resources.Length); + foreach (LocalVersionList.Resource resource in resources) + { + binaryWriter.WriteEncryptedString(resource.Name, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Variant, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Extension != DefaultExtension ? resource.Extension : null, s_CachedHashBytes); + binaryWriter.Write(resource.LoadType); + binaryWriter.Write7BitEncodedInt32(resource.Length); + binaryWriter.Write(resource.HashCode); + } + + LocalVersionList.FileSystem[] fileSystems = versionList.GetFileSystems(); + binaryWriter.Write7BitEncodedInt32(fileSystems.Length); + foreach (LocalVersionList.FileSystem fileSystem in fileSystems) + { + binaryWriter.WriteEncryptedString(fileSystem.Name, s_CachedHashBytes); + int[] resourceIndexes = fileSystem.GetResourceIndexes(); + binaryWriter.Write7BitEncodedInt32(resourceIndexes.Length); + foreach (int resourceIndex in resourceIndexes) + { + binaryWriter.Write7BitEncodedInt32(resourceIndex); + } + } + } + + Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength); + return true; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.LocalVersionListSerializeCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.LocalVersionListSerializeCallback.cs.meta new file mode 100644 index 0000000..f9df195 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.LocalVersionListSerializeCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7633b95b6d880174bbf537a35e918141 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.PackageVersionListDeserializeCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.PackageVersionListDeserializeCallback.cs new file mode 100644 index 0000000..665a758 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.PackageVersionListDeserializeCallback.cs @@ -0,0 +1,264 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Resource; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace UnityGameFramework.Runtime +{ + /// + /// 内置版本资源列表序列化器。 + /// + public static partial class BuiltinVersionListSerializer + { + /// + /// 反序列化单机模式版本资源列表(版本 0)回调函数。 + /// + /// 指定流。 + /// 反序列化的单机模式版本资源列表(版本 0)。 + public static PackageVersionList PackageVersionListDeserializeCallback_V0(Stream stream) + { + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + byte[] encryptBytes = binaryReader.ReadBytes(CachedHashBytesLength); + string applicableGameVersion = binaryReader.ReadEncryptedString(encryptBytes); + int internalResourceVersion = binaryReader.ReadInt32(); + int assetCount = binaryReader.ReadInt32(); + PackageVersionList.Asset[] assets = assetCount > 0 ? new PackageVersionList.Asset[assetCount] : null; + int resourceCount = binaryReader.ReadInt32(); + PackageVersionList.Resource[] resources = resourceCount > 0 ? new PackageVersionList.Resource[resourceCount] : null; + string[][] resourceToAssetNames = new string[resourceCount][]; + List> assetNameToDependencyAssetNames = new List>(assetCount); + for (int i = 0; i < resourceCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + string variant = binaryReader.ReadEncryptedString(encryptBytes); + byte loadType = binaryReader.ReadByte(); + int length = binaryReader.ReadInt32(); + int hashCode = binaryReader.ReadInt32(); + Utility.Converter.GetBytes(hashCode, s_CachedHashBytes); + + int assetNameCount = binaryReader.ReadInt32(); + string[] assetNames = new string[assetNameCount]; + for (int j = 0; j < assetNameCount; j++) + { + assetNames[j] = binaryReader.ReadEncryptedString(s_CachedHashBytes); + int dependencyAssetNameCount = binaryReader.ReadInt32(); + string[] dependencyAssetNames = dependencyAssetNameCount > 0 ? new string[dependencyAssetNameCount] : null; + for (int k = 0; k < dependencyAssetNameCount; k++) + { + dependencyAssetNames[k] = binaryReader.ReadEncryptedString(s_CachedHashBytes); + } + + assetNameToDependencyAssetNames.Add(new KeyValuePair(assetNames[j], dependencyAssetNames)); + } + + resourceToAssetNames[i] = assetNames; + resources[i] = new PackageVersionList.Resource(name, variant, null, loadType, length, hashCode, assetNameCount > 0 ? new int[assetNameCount] : null); + } + + assetNameToDependencyAssetNames.Sort(AssetNameToDependencyAssetNamesComparer); + Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength); + int index = 0; + foreach (KeyValuePair i in assetNameToDependencyAssetNames) + { + if (i.Value != null) + { + int[] dependencyAssetIndexes = new int[i.Value.Length]; + for (int j = 0; j < i.Value.Length; j++) + { + dependencyAssetIndexes[j] = GetAssetNameIndex(assetNameToDependencyAssetNames, i.Value[j]); + } + + assets[index++] = new PackageVersionList.Asset(i.Key, dependencyAssetIndexes); + } + else + { + assets[index++] = new PackageVersionList.Asset(i.Key, null); + } + } + + for (int i = 0; i < resources.Length; i++) + { + int[] assetIndexes = resources[i].GetAssetIndexes(); + for (int j = 0; j < assetIndexes.Length; j++) + { + assetIndexes[j] = GetAssetNameIndex(assetNameToDependencyAssetNames, resourceToAssetNames[i][j]); + } + } + + int resourceGroupCount = binaryReader.ReadInt32(); + PackageVersionList.ResourceGroup[] resourceGroups = resourceGroupCount > 0 ? new PackageVersionList.ResourceGroup[resourceGroupCount] : null; + for (int i = 0; i < resourceGroupCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int resourceIndexCount = binaryReader.ReadInt32(); + int[] resourceIndexes = resourceIndexCount > 0 ? new int[resourceIndexCount] : null; + for (int j = 0; j < resourceIndexCount; j++) + { + resourceIndexes[j] = binaryReader.ReadUInt16(); + } + + resourceGroups[i] = new PackageVersionList.ResourceGroup(name, resourceIndexes); + } + + return new PackageVersionList(applicableGameVersion, internalResourceVersion, assets, resources, null, resourceGroups); + } + } + + /// + /// 反序列化单机模式版本资源列表(版本 1)回调函数。 + /// + /// 指定流。 + /// 反序列化的单机模式版本资源列表(版本 1)。 + public static PackageVersionList PackageVersionListDeserializeCallback_V1(Stream stream) + { + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + byte[] encryptBytes = binaryReader.ReadBytes(CachedHashBytesLength); + string applicableGameVersion = binaryReader.ReadEncryptedString(encryptBytes); + int internalResourceVersion = binaryReader.Read7BitEncodedInt32(); + int assetCount = binaryReader.Read7BitEncodedInt32(); + PackageVersionList.Asset[] assets = assetCount > 0 ? new PackageVersionList.Asset[assetCount] : null; + for (int i = 0; i < assetCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int dependencyAssetCount = binaryReader.Read7BitEncodedInt32(); + int[] dependencyAssetIndexes = dependencyAssetCount > 0 ? new int[dependencyAssetCount] : null; + for (int j = 0; j < dependencyAssetCount; j++) + { + dependencyAssetIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + assets[i] = new PackageVersionList.Asset(name, dependencyAssetIndexes); + } + + int resourceCount = binaryReader.Read7BitEncodedInt32(); + PackageVersionList.Resource[] resources = resourceCount > 0 ? new PackageVersionList.Resource[resourceCount] : null; + for (int i = 0; i < resourceCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + string variant = binaryReader.ReadEncryptedString(encryptBytes); + string extension = binaryReader.ReadEncryptedString(encryptBytes) ?? DefaultExtension; + byte loadType = binaryReader.ReadByte(); + int length = binaryReader.Read7BitEncodedInt32(); + int hashCode = binaryReader.ReadInt32(); + int assetIndexCount = binaryReader.Read7BitEncodedInt32(); + int[] assetIndexes = assetIndexCount > 0 ? new int[assetIndexCount] : null; + for (int j = 0; j < assetIndexCount; j++) + { + assetIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + resources[i] = new PackageVersionList.Resource(name, variant, extension, loadType, length, hashCode, assetIndexes); + } + + int resourceGroupCount = binaryReader.Read7BitEncodedInt32(); + PackageVersionList.ResourceGroup[] resourceGroups = resourceGroupCount > 0 ? new PackageVersionList.ResourceGroup[resourceGroupCount] : null; + for (int i = 0; i < resourceGroupCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int resourceIndexCount = binaryReader.Read7BitEncodedInt32(); + int[] resourceIndexes = resourceIndexCount > 0 ? new int[resourceIndexCount] : null; + for (int j = 0; j < resourceIndexCount; j++) + { + resourceIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + resourceGroups[i] = new PackageVersionList.ResourceGroup(name, resourceIndexes); + } + + return new PackageVersionList(applicableGameVersion, internalResourceVersion, assets, resources, null, resourceGroups); + } + } + + /// + /// 反序列化单机模式版本资源列表(版本 2)回调函数。 + /// + /// 指定流。 + /// 反序列化的单机模式版本资源列表(版本 2)。 + public static PackageVersionList PackageVersionListDeserializeCallback_V2(Stream stream) + { + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + byte[] encryptBytes = binaryReader.ReadBytes(CachedHashBytesLength); + string applicableGameVersion = binaryReader.ReadEncryptedString(encryptBytes); + int internalResourceVersion = binaryReader.Read7BitEncodedInt32(); + int assetCount = binaryReader.Read7BitEncodedInt32(); + PackageVersionList.Asset[] assets = assetCount > 0 ? new PackageVersionList.Asset[assetCount] : null; + for (int i = 0; i < assetCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int dependencyAssetCount = binaryReader.Read7BitEncodedInt32(); + int[] dependencyAssetIndexes = dependencyAssetCount > 0 ? new int[dependencyAssetCount] : null; + for (int j = 0; j < dependencyAssetCount; j++) + { + dependencyAssetIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + assets[i] = new PackageVersionList.Asset(name, dependencyAssetIndexes); + } + + int resourceCount = binaryReader.Read7BitEncodedInt32(); + PackageVersionList.Resource[] resources = resourceCount > 0 ? new PackageVersionList.Resource[resourceCount] : null; + for (int i = 0; i < resourceCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + string variant = binaryReader.ReadEncryptedString(encryptBytes); + string extension = binaryReader.ReadEncryptedString(encryptBytes) ?? DefaultExtension; + byte loadType = binaryReader.ReadByte(); + int length = binaryReader.Read7BitEncodedInt32(); + int hashCode = binaryReader.ReadInt32(); + int assetIndexCount = binaryReader.Read7BitEncodedInt32(); + int[] assetIndexes = assetIndexCount > 0 ? new int[assetIndexCount] : null; + for (int j = 0; j < assetIndexCount; j++) + { + assetIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + resources[i] = new PackageVersionList.Resource(name, variant, extension, loadType, length, hashCode, assetIndexes); + } + + int fileSystemCount = binaryReader.Read7BitEncodedInt32(); + PackageVersionList.FileSystem[] fileSystems = fileSystemCount > 0 ? new PackageVersionList.FileSystem[fileSystemCount] : null; + for (int i = 0; i < fileSystemCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int resourceIndexCount = binaryReader.Read7BitEncodedInt32(); + int[] resourceIndexes = resourceIndexCount > 0 ? new int[resourceIndexCount] : null; + for (int j = 0; j < resourceIndexCount; j++) + { + resourceIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + fileSystems[i] = new PackageVersionList.FileSystem(name, resourceIndexes); + } + + int resourceGroupCount = binaryReader.Read7BitEncodedInt32(); + PackageVersionList.ResourceGroup[] resourceGroups = resourceGroupCount > 0 ? new PackageVersionList.ResourceGroup[resourceGroupCount] : null; + for (int i = 0; i < resourceGroupCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int resourceIndexCount = binaryReader.Read7BitEncodedInt32(); + int[] resourceIndexes = resourceIndexCount > 0 ? new int[resourceIndexCount] : null; + for (int j = 0; j < resourceIndexCount; j++) + { + resourceIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + resourceGroups[i] = new PackageVersionList.ResourceGroup(name, resourceIndexes); + } + + return new PackageVersionList(applicableGameVersion, internalResourceVersion, assets, resources, fileSystems, resourceGroups); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.PackageVersionListDeserializeCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.PackageVersionListDeserializeCallback.cs.meta new file mode 100644 index 0000000..9d5ad27 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.PackageVersionListDeserializeCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 55d016c3660f4fa458c20847cf59aa16 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.PackageVersionListSerializeCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.PackageVersionListSerializeCallback.cs new file mode 100644 index 0000000..f07b3fd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.PackageVersionListSerializeCallback.cs @@ -0,0 +1,239 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Resource; +using System; +using System.IO; +using System.Text; + +namespace UnityGameFramework.Runtime +{ + /// + /// 内置版本资源列表序列化器。 + /// + public static partial class BuiltinVersionListSerializer + { +#if UNITY_EDITOR + + /// + /// 序列化单机模式版本资源列表(版本 0)回调函数。 + /// + /// 目标流。 + /// 要序列化的单机模式版本资源列表(版本 0)。 + /// 是否序列化单机模式版本资源列表(版本 0)成功。 + public static bool PackageVersionListSerializeCallback_V0(Stream stream, PackageVersionList versionList) + { + if (!versionList.IsValid) + { + return false; + } + + Utility.Random.GetRandomBytes(s_CachedHashBytes); + using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.UTF8)) + { + binaryWriter.Write(s_CachedHashBytes); + binaryWriter.WriteEncryptedString(versionList.ApplicableGameVersion, s_CachedHashBytes); + binaryWriter.Write(versionList.InternalResourceVersion); + PackageVersionList.Asset[] assets = versionList.GetAssets(); + binaryWriter.Write(assets.Length); + PackageVersionList.Resource[] resources = versionList.GetResources(); + binaryWriter.Write(resources.Length); + foreach (PackageVersionList.Resource resource in resources) + { + binaryWriter.WriteEncryptedString(resource.Name, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Variant, s_CachedHashBytes); + binaryWriter.Write(resource.LoadType); + binaryWriter.Write(resource.Length); + binaryWriter.Write(resource.HashCode); + int[] assetIndexes = resource.GetAssetIndexes(); + binaryWriter.Write(assetIndexes.Length); + byte[] hashBytes = new byte[CachedHashBytesLength]; + foreach (int assetIndex in assetIndexes) + { + Utility.Converter.GetBytes(resource.HashCode, hashBytes); + PackageVersionList.Asset asset = assets[assetIndex]; + binaryWriter.WriteEncryptedString(asset.Name, hashBytes); + int[] dependencyAssetIndexes = asset.GetDependencyAssetIndexes(); + binaryWriter.Write(dependencyAssetIndexes.Length); + foreach (int dependencyAssetIndex in dependencyAssetIndexes) + { + binaryWriter.WriteEncryptedString(assets[dependencyAssetIndex].Name, hashBytes); + } + } + } + + PackageVersionList.ResourceGroup[] resourceGroups = versionList.GetResourceGroups(); + binaryWriter.Write(resourceGroups.Length); + foreach (PackageVersionList.ResourceGroup resourceGroup in resourceGroups) + { + binaryWriter.WriteEncryptedString(resourceGroup.Name, s_CachedHashBytes); + int[] resourceIndexes = resourceGroup.GetResourceIndexes(); + binaryWriter.Write(resourceIndexes.Length); + foreach (ushort resourceIndex in resourceIndexes) + { + binaryWriter.Write(resourceIndex); + } + } + } + + Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength); + return true; + } + + /// + /// 序列化单机模式版本资源列表(版本 1)回调函数。 + /// + /// 目标流。 + /// 要序列化的单机模式版本资源列表(版本 1)。 + /// 是否序列化单机模式版本资源列表(版本 1)成功。 + public static bool PackageVersionListSerializeCallback_V1(Stream stream, PackageVersionList versionList) + { + if (!versionList.IsValid) + { + return false; + } + + Utility.Random.GetRandomBytes(s_CachedHashBytes); + using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.UTF8)) + { + binaryWriter.Write(s_CachedHashBytes); + binaryWriter.WriteEncryptedString(versionList.ApplicableGameVersion, s_CachedHashBytes); + binaryWriter.Write7BitEncodedInt32(versionList.InternalResourceVersion); + PackageVersionList.Asset[] assets = versionList.GetAssets(); + binaryWriter.Write7BitEncodedInt32(assets.Length); + foreach (PackageVersionList.Asset asset in assets) + { + binaryWriter.WriteEncryptedString(asset.Name, s_CachedHashBytes); + int[] dependencyAssetIndexes = asset.GetDependencyAssetIndexes(); + binaryWriter.Write7BitEncodedInt32(dependencyAssetIndexes.Length); + foreach (int dependencyAssetIndex in dependencyAssetIndexes) + { + binaryWriter.Write7BitEncodedInt32(dependencyAssetIndex); + } + } + + PackageVersionList.Resource[] resources = versionList.GetResources(); + binaryWriter.Write7BitEncodedInt32(resources.Length); + foreach (PackageVersionList.Resource resource in resources) + { + binaryWriter.WriteEncryptedString(resource.Name, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Variant, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Extension != DefaultExtension ? resource.Extension : null, s_CachedHashBytes); + binaryWriter.Write(resource.LoadType); + binaryWriter.Write7BitEncodedInt32(resource.Length); + binaryWriter.Write(resource.HashCode); + int[] assetIndexes = resource.GetAssetIndexes(); + binaryWriter.Write7BitEncodedInt32(assetIndexes.Length); + foreach (int assetIndex in assetIndexes) + { + binaryWriter.Write7BitEncodedInt32(assetIndex); + } + } + + PackageVersionList.ResourceGroup[] resourceGroups = versionList.GetResourceGroups(); + binaryWriter.Write7BitEncodedInt32(resourceGroups.Length); + foreach (PackageVersionList.ResourceGroup resourceGroup in resourceGroups) + { + binaryWriter.WriteEncryptedString(resourceGroup.Name, s_CachedHashBytes); + int[] resourceIndexes = resourceGroup.GetResourceIndexes(); + binaryWriter.Write7BitEncodedInt32(resourceIndexes.Length); + foreach (int resourceIndex in resourceIndexes) + { + binaryWriter.Write7BitEncodedInt32(resourceIndex); + } + } + } + + Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength); + return true; + } + + /// + /// 序列化单机模式版本资源列表(版本 2)回调函数。 + /// + /// 目标流。 + /// 要序列化的单机模式版本资源列表(版本 2)。 + /// 是否序列化单机模式版本资源列表(版本 2)成功。 + public static bool PackageVersionListSerializeCallback_V2(Stream stream, PackageVersionList versionList) + { + if (!versionList.IsValid) + { + return false; + } + + Utility.Random.GetRandomBytes(s_CachedHashBytes); + using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.UTF8)) + { + binaryWriter.Write(s_CachedHashBytes); + binaryWriter.WriteEncryptedString(versionList.ApplicableGameVersion, s_CachedHashBytes); + binaryWriter.Write7BitEncodedInt32(versionList.InternalResourceVersion); + PackageVersionList.Asset[] assets = versionList.GetAssets(); + binaryWriter.Write7BitEncodedInt32(assets.Length); + foreach (PackageVersionList.Asset asset in assets) + { + binaryWriter.WriteEncryptedString(asset.Name, s_CachedHashBytes); + int[] dependencyAssetIndexes = asset.GetDependencyAssetIndexes(); + binaryWriter.Write7BitEncodedInt32(dependencyAssetIndexes.Length); + foreach (int dependencyAssetIndex in dependencyAssetIndexes) + { + binaryWriter.Write7BitEncodedInt32(dependencyAssetIndex); + } + } + + PackageVersionList.Resource[] resources = versionList.GetResources(); + binaryWriter.Write7BitEncodedInt32(resources.Length); + foreach (PackageVersionList.Resource resource in resources) + { + binaryWriter.WriteEncryptedString(resource.Name, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Variant, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Extension != DefaultExtension ? resource.Extension : null, s_CachedHashBytes); + binaryWriter.Write(resource.LoadType); + binaryWriter.Write7BitEncodedInt32(resource.Length); + binaryWriter.Write(resource.HashCode); + int[] assetIndexes = resource.GetAssetIndexes(); + binaryWriter.Write7BitEncodedInt32(assetIndexes.Length); + foreach (int assetIndex in assetIndexes) + { + binaryWriter.Write7BitEncodedInt32(assetIndex); + } + } + + PackageVersionList.FileSystem[] fileSystems = versionList.GetFileSystems(); + binaryWriter.Write7BitEncodedInt32(fileSystems.Length); + foreach (PackageVersionList.FileSystem fileSystem in fileSystems) + { + binaryWriter.WriteEncryptedString(fileSystem.Name, s_CachedHashBytes); + int[] resourceIndexes = fileSystem.GetResourceIndexes(); + binaryWriter.Write7BitEncodedInt32(resourceIndexes.Length); + foreach (int resourceIndex in resourceIndexes) + { + binaryWriter.Write7BitEncodedInt32(resourceIndex); + } + } + + PackageVersionList.ResourceGroup[] resourceGroups = versionList.GetResourceGroups(); + binaryWriter.Write7BitEncodedInt32(resourceGroups.Length); + foreach (PackageVersionList.ResourceGroup resourceGroup in resourceGroups) + { + binaryWriter.WriteEncryptedString(resourceGroup.Name, s_CachedHashBytes); + int[] resourceIndexes = resourceGroup.GetResourceIndexes(); + binaryWriter.Write7BitEncodedInt32(resourceIndexes.Length); + foreach (int resourceIndex in resourceIndexes) + { + binaryWriter.Write7BitEncodedInt32(resourceIndex); + } + } + } + + Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength); + return true; + } + +#endif + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.PackageVersionListSerializeCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.PackageVersionListSerializeCallback.cs.meta new file mode 100644 index 0000000..39b29ad --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.PackageVersionListSerializeCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3f1e0304275244949890ac3aa8a7f236 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.ResourcePackVersionListDeserializeCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.ResourcePackVersionListDeserializeCallback.cs new file mode 100644 index 0000000..a95bceb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.ResourcePackVersionListDeserializeCallback.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System.IO; +using System.Text; + +namespace UnityGameFramework.Runtime +{ + /// + /// 内置版本资源列表序列化器。 + /// + public static partial class BuiltinVersionListSerializer + { + /// + /// 反序列化资源包版本资源列表(版本 0)回调函数。 + /// + /// 指定流。 + /// 反序列化的资源包版本资源列表(版本 0)。 + public static ResourcePackVersionList ResourcePackVersionListDeserializeCallback_V0(Stream stream) + { + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + byte[] encryptBytes = binaryReader.ReadBytes(CachedHashBytesLength); + int dataOffset = binaryReader.ReadInt32(); + long dataLength = binaryReader.ReadInt64(); + int dataHashCode = binaryReader.ReadInt32(); + int resourceCount = binaryReader.Read7BitEncodedInt32(); + ResourcePackVersionList.Resource[] resources = resourceCount > 0 ? new ResourcePackVersionList.Resource[resourceCount] : null; + for (int i = 0; i < resourceCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + string variant = binaryReader.ReadEncryptedString(encryptBytes); + string extension = binaryReader.ReadEncryptedString(encryptBytes) ?? DefaultExtension; + byte loadType = binaryReader.ReadByte(); + long offset = binaryReader.Read7BitEncodedInt64(); + int length = binaryReader.Read7BitEncodedInt32(); + int hashCode = binaryReader.ReadInt32(); + int compressedLength = binaryReader.Read7BitEncodedInt32(); + int compressedHashCode = binaryReader.ReadInt32(); + resources[i] = new ResourcePackVersionList.Resource(name, variant, extension, loadType, offset, length, hashCode, compressedLength, compressedHashCode); + } + + return new ResourcePackVersionList(dataOffset, dataLength, dataHashCode, resources); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.ResourcePackVersionListDeserializeCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.ResourcePackVersionListDeserializeCallback.cs.meta new file mode 100644 index 0000000..45413f9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.ResourcePackVersionListDeserializeCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 03b37f88eb002e740881c81bba3ac02b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.ResourcePackVersionListSerializeCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.ResourcePackVersionListSerializeCallback.cs new file mode 100644 index 0000000..b2514fb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.ResourcePackVersionListSerializeCallback.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Resource; +using System; +using System.IO; +using System.Text; + +namespace UnityGameFramework.Runtime +{ + /// + /// 内置版本资源列表序列化器。 + /// + public static partial class BuiltinVersionListSerializer + { +#if UNITY_EDITOR + + /// + /// 序列化资源包版本资源列表(版本 0)回调函数。 + /// + /// 目标流。 + /// 要序列化的资源包版本资源列表(版本 0)。 + /// 是否序列化资源包版本资源列表(版本 0)成功。 + public static bool ResourcePackVersionListSerializeCallback_V0(Stream stream, ResourcePackVersionList versionList) + { + if (!versionList.IsValid) + { + return false; + } + + Utility.Random.GetRandomBytes(s_CachedHashBytes); + using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.UTF8)) + { + binaryWriter.Write(s_CachedHashBytes); + binaryWriter.Write(versionList.Offset); + binaryWriter.Write(versionList.Length); + binaryWriter.Write(versionList.HashCode); + ResourcePackVersionList.Resource[] resources = versionList.GetResources(); + binaryWriter.Write7BitEncodedInt32(resources.Length); + foreach (ResourcePackVersionList.Resource resource in resources) + { + binaryWriter.WriteEncryptedString(resource.Name, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Variant, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Extension != DefaultExtension ? resource.Extension : null, s_CachedHashBytes); + binaryWriter.Write(resource.LoadType); + binaryWriter.Write7BitEncodedInt64(resource.Offset); + binaryWriter.Write7BitEncodedInt32(resource.Length); + binaryWriter.Write(resource.HashCode); + binaryWriter.Write7BitEncodedInt32(resource.CompressedLength); + binaryWriter.Write(resource.CompressedHashCode); + } + } + + Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength); + return true; + } + +#endif + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.ResourcePackVersionListSerializeCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.ResourcePackVersionListSerializeCallback.cs.meta new file mode 100644 index 0000000..415e921 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.ResourcePackVersionListSerializeCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8bff196dc370ba048b548e0be53dc26f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback.cs new file mode 100644 index 0000000..91d05a4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback.cs @@ -0,0 +1,270 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Resource; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace UnityGameFramework.Runtime +{ + /// + /// 内置版本资源列表序列化器。 + /// + public static partial class BuiltinVersionListSerializer + { + /// + /// 反序列化可更新模式版本资源列表(版本 0)回调函数。 + /// + /// 指定流。 + /// 反序列化的可更新模式版本资源列表(版本 0)。 + public static UpdatableVersionList UpdatableVersionListDeserializeCallback_V0(Stream stream) + { + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + byte[] encryptBytes = binaryReader.ReadBytes(CachedHashBytesLength); + string applicableGameVersion = binaryReader.ReadEncryptedString(encryptBytes); + int internalResourceVersion = binaryReader.ReadInt32(); + int assetCount = binaryReader.ReadInt32(); + UpdatableVersionList.Asset[] assets = assetCount > 0 ? new UpdatableVersionList.Asset[assetCount] : null; + int resourceCount = binaryReader.ReadInt32(); + UpdatableVersionList.Resource[] resources = resourceCount > 0 ? new UpdatableVersionList.Resource[resourceCount] : null; + string[][] resourceToAssetNames = new string[resourceCount][]; + List> assetNameToDependencyAssetNames = new List>(assetCount); + for (int i = 0; i < resourceCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + string variant = binaryReader.ReadEncryptedString(encryptBytes); + byte loadType = binaryReader.ReadByte(); + int length = binaryReader.ReadInt32(); + int hashCode = binaryReader.ReadInt32(); + int compressedLength = binaryReader.ReadInt32(); + int compressedHashCode = binaryReader.ReadInt32(); + Utility.Converter.GetBytes(hashCode, s_CachedHashBytes); + + int assetNameCount = binaryReader.ReadInt32(); + string[] assetNames = assetNameCount > 0 ? new string[assetNameCount] : null; + for (int j = 0; j < assetNameCount; j++) + { + assetNames[j] = binaryReader.ReadEncryptedString(s_CachedHashBytes); + int dependencyAssetNameCount = binaryReader.ReadInt32(); + string[] dependencyAssetNames = dependencyAssetNameCount > 0 ? new string[dependencyAssetNameCount] : null; + for (int k = 0; k < dependencyAssetNameCount; k++) + { + dependencyAssetNames[k] = binaryReader.ReadEncryptedString(s_CachedHashBytes); + } + + assetNameToDependencyAssetNames.Add(new KeyValuePair(assetNames[j], dependencyAssetNames)); + } + + resourceToAssetNames[i] = assetNames; + resources[i] = new UpdatableVersionList.Resource(name, variant, null, loadType, length, hashCode, compressedLength, compressedHashCode, assetNameCount > 0 ? new int[assetNameCount] : null); + } + + assetNameToDependencyAssetNames.Sort(AssetNameToDependencyAssetNamesComparer); + Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength); + int index = 0; + foreach (KeyValuePair i in assetNameToDependencyAssetNames) + { + if (i.Value != null) + { + int[] dependencyAssetIndexes = new int[i.Value.Length]; + for (int j = 0; j < i.Value.Length; j++) + { + dependencyAssetIndexes[j] = GetAssetNameIndex(assetNameToDependencyAssetNames, i.Value[j]); + } + + assets[index++] = new UpdatableVersionList.Asset(i.Key, dependencyAssetIndexes); + } + else + { + assets[index++] = new UpdatableVersionList.Asset(i.Key, null); + } + } + + for (int i = 0; i < resources.Length; i++) + { + int[] assetIndexes = resources[i].GetAssetIndexes(); + for (int j = 0; j < assetIndexes.Length; j++) + { + assetIndexes[j] = GetAssetNameIndex(assetNameToDependencyAssetNames, resourceToAssetNames[i][j]); + } + } + + int resourceGroupCount = binaryReader.ReadInt32(); + UpdatableVersionList.ResourceGroup[] resourceGroups = resourceGroupCount > 0 ? new UpdatableVersionList.ResourceGroup[resourceGroupCount] : null; + for (int i = 0; i < resourceGroupCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int resourceIndexCount = binaryReader.ReadInt32(); + int[] resourceIndexes = resourceIndexCount > 0 ? new int[resourceIndexCount] : null; + for (int j = 0; j < resourceIndexCount; j++) + { + resourceIndexes[j] = binaryReader.ReadUInt16(); + } + + resourceGroups[i] = new UpdatableVersionList.ResourceGroup(name, resourceIndexes); + } + + return new UpdatableVersionList(applicableGameVersion, internalResourceVersion, assets, resources, null, resourceGroups); + } + } + + /// + /// 反序列化可更新模式版本资源列表(版本 1)回调函数。 + /// + /// 指定流。 + /// 反序列化的可更新模式版本资源列表(版本 1)。 + public static UpdatableVersionList UpdatableVersionListDeserializeCallback_V1(Stream stream) + { + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + byte[] encryptBytes = binaryReader.ReadBytes(CachedHashBytesLength); + string applicableGameVersion = binaryReader.ReadEncryptedString(encryptBytes); + int internalResourceVersion = binaryReader.Read7BitEncodedInt32(); + int assetCount = binaryReader.Read7BitEncodedInt32(); + UpdatableVersionList.Asset[] assets = assetCount > 0 ? new UpdatableVersionList.Asset[assetCount] : null; + for (int i = 0; i < assetCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int dependencyAssetCount = binaryReader.Read7BitEncodedInt32(); + int[] dependencyAssetIndexes = dependencyAssetCount > 0 ? new int[dependencyAssetCount] : null; + for (int j = 0; j < dependencyAssetCount; j++) + { + dependencyAssetIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + assets[i] = new UpdatableVersionList.Asset(name, dependencyAssetIndexes); + } + + int resourceCount = binaryReader.Read7BitEncodedInt32(); + UpdatableVersionList.Resource[] resources = resourceCount > 0 ? new UpdatableVersionList.Resource[resourceCount] : null; + for (int i = 0; i < resourceCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + string variant = binaryReader.ReadEncryptedString(encryptBytes); + string extension = binaryReader.ReadEncryptedString(encryptBytes) ?? DefaultExtension; + byte loadType = binaryReader.ReadByte(); + int length = binaryReader.Read7BitEncodedInt32(); + int hashCode = binaryReader.ReadInt32(); + int compressedLength = binaryReader.Read7BitEncodedInt32(); + int compressedHashCode = binaryReader.ReadInt32(); + int assetIndexCount = binaryReader.Read7BitEncodedInt32(); + int[] assetIndexes = assetIndexCount > 0 ? new int[assetIndexCount] : null; + for (int j = 0; j < assetIndexCount; j++) + { + assetIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + resources[i] = new UpdatableVersionList.Resource(name, variant, extension, loadType, length, hashCode, compressedLength, compressedHashCode, assetIndexes); + } + + int resourceGroupCount = binaryReader.Read7BitEncodedInt32(); + UpdatableVersionList.ResourceGroup[] resourceGroups = resourceGroupCount > 0 ? new UpdatableVersionList.ResourceGroup[resourceGroupCount] : null; + for (int i = 0; i < resourceGroupCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int resourceIndexCount = binaryReader.Read7BitEncodedInt32(); + int[] resourceIndexes = resourceIndexCount > 0 ? new int[resourceIndexCount] : null; + for (int j = 0; j < resourceIndexCount; j++) + { + resourceIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + resourceGroups[i] = new UpdatableVersionList.ResourceGroup(name, resourceIndexes); + } + + return new UpdatableVersionList(applicableGameVersion, internalResourceVersion, assets, resources, null, resourceGroups); + } + } + + /// + /// 反序列化可更新模式版本资源列表(版本 2)回调函数。 + /// + /// 指定流。 + /// 反序列化的可更新模式版本资源列表(版本 2)。 + public static UpdatableVersionList UpdatableVersionListDeserializeCallback_V2(Stream stream) + { + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + byte[] encryptBytes = binaryReader.ReadBytes(CachedHashBytesLength); + string applicableGameVersion = binaryReader.ReadEncryptedString(encryptBytes); + int internalResourceVersion = binaryReader.Read7BitEncodedInt32(); + int assetCount = binaryReader.Read7BitEncodedInt32(); + UpdatableVersionList.Asset[] assets = assetCount > 0 ? new UpdatableVersionList.Asset[assetCount] : null; + for (int i = 0; i < assetCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int dependencyAssetCount = binaryReader.Read7BitEncodedInt32(); + int[] dependencyAssetIndexes = dependencyAssetCount > 0 ? new int[dependencyAssetCount] : null; + for (int j = 0; j < dependencyAssetCount; j++) + { + dependencyAssetIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + assets[i] = new UpdatableVersionList.Asset(name, dependencyAssetIndexes); + } + + int resourceCount = binaryReader.Read7BitEncodedInt32(); + UpdatableVersionList.Resource[] resources = resourceCount > 0 ? new UpdatableVersionList.Resource[resourceCount] : null; + for (int i = 0; i < resourceCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + string variant = binaryReader.ReadEncryptedString(encryptBytes); + string extension = binaryReader.ReadEncryptedString(encryptBytes) ?? DefaultExtension; + byte loadType = binaryReader.ReadByte(); + int length = binaryReader.Read7BitEncodedInt32(); + int hashCode = binaryReader.ReadInt32(); + int compressedLength = binaryReader.Read7BitEncodedInt32(); + int compressedHashCode = binaryReader.ReadInt32(); + int assetIndexCount = binaryReader.Read7BitEncodedInt32(); + int[] assetIndexes = assetIndexCount > 0 ? new int[assetIndexCount] : null; + for (int j = 0; j < assetIndexCount; j++) + { + assetIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + resources[i] = new UpdatableVersionList.Resource(name, variant, extension, loadType, length, hashCode, compressedLength, compressedHashCode, assetIndexes); + } + + int fileSystemCount = binaryReader.Read7BitEncodedInt32(); + UpdatableVersionList.FileSystem[] fileSystems = fileSystemCount > 0 ? new UpdatableVersionList.FileSystem[fileSystemCount] : null; + for (int i = 0; i < fileSystemCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int resourceIndexCount = binaryReader.Read7BitEncodedInt32(); + int[] resourceIndexes = resourceIndexCount > 0 ? new int[resourceIndexCount] : null; + for (int j = 0; j < resourceIndexCount; j++) + { + resourceIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + fileSystems[i] = new UpdatableVersionList.FileSystem(name, resourceIndexes); + } + + int resourceGroupCount = binaryReader.Read7BitEncodedInt32(); + UpdatableVersionList.ResourceGroup[] resourceGroups = resourceGroupCount > 0 ? new UpdatableVersionList.ResourceGroup[resourceGroupCount] : null; + for (int i = 0; i < resourceGroupCount; i++) + { + string name = binaryReader.ReadEncryptedString(encryptBytes); + int resourceIndexCount = binaryReader.Read7BitEncodedInt32(); + int[] resourceIndexes = resourceIndexCount > 0 ? new int[resourceIndexCount] : null; + for (int j = 0; j < resourceIndexCount; j++) + { + resourceIndexes[j] = binaryReader.Read7BitEncodedInt32(); + } + + resourceGroups[i] = new UpdatableVersionList.ResourceGroup(name, resourceIndexes); + } + + return new UpdatableVersionList(applicableGameVersion, internalResourceVersion, assets, resources, fileSystems, resourceGroups); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback.cs.meta new file mode 100644 index 0000000..91ac6ff --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f8075a91786219b4db1b77aa406a81e8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback.cs new file mode 100644 index 0000000..bc7782a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback.cs @@ -0,0 +1,245 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Resource; +using System; +using System.IO; +using System.Text; + +namespace UnityGameFramework.Runtime +{ + /// + /// 内置版本资源列表序列化器。 + /// + public static partial class BuiltinVersionListSerializer + { +#if UNITY_EDITOR + + /// + /// 序列化可更新模式版本资源列表(版本 0)回调函数。 + /// + /// 目标流。 + /// 要序列化的可更新模式版本资源列表(版本 0)。 + /// 是否序列化可更新模式版本资源列表(版本 0)成功。 + public static bool UpdatableVersionListSerializeCallback_V0(Stream stream, UpdatableVersionList versionList) + { + if (!versionList.IsValid) + { + return false; + } + + Utility.Random.GetRandomBytes(s_CachedHashBytes); + using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.UTF8)) + { + binaryWriter.Write(s_CachedHashBytes); + binaryWriter.WriteEncryptedString(versionList.ApplicableGameVersion, s_CachedHashBytes); + binaryWriter.Write(versionList.InternalResourceVersion); + UpdatableVersionList.Asset[] assets = versionList.GetAssets(); + binaryWriter.Write(assets.Length); + UpdatableVersionList.Resource[] resources = versionList.GetResources(); + binaryWriter.Write(resources.Length); + foreach (UpdatableVersionList.Resource resource in resources) + { + binaryWriter.WriteEncryptedString(resource.Name, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Variant, s_CachedHashBytes); + binaryWriter.Write(resource.LoadType); + binaryWriter.Write(resource.Length); + binaryWriter.Write(resource.HashCode); + binaryWriter.Write(resource.CompressedLength); + binaryWriter.Write(resource.CompressedHashCode); + int[] assetIndexes = resource.GetAssetIndexes(); + binaryWriter.Write(assetIndexes.Length); + byte[] hashBytes = new byte[CachedHashBytesLength]; + foreach (int assetIndex in assetIndexes) + { + Utility.Converter.GetBytes(resource.HashCode, hashBytes); + UpdatableVersionList.Asset asset = assets[assetIndex]; + binaryWriter.WriteEncryptedString(asset.Name, hashBytes); + int[] dependencyAssetIndexes = asset.GetDependencyAssetIndexes(); + binaryWriter.Write(dependencyAssetIndexes.Length); + foreach (int dependencyAssetIndex in dependencyAssetIndexes) + { + binaryWriter.WriteEncryptedString(assets[dependencyAssetIndex].Name, hashBytes); + } + } + } + + UpdatableVersionList.ResourceGroup[] resourceGroups = versionList.GetResourceGroups(); + binaryWriter.Write(resourceGroups.Length); + foreach (UpdatableVersionList.ResourceGroup resourceGroup in resourceGroups) + { + binaryWriter.WriteEncryptedString(resourceGroup.Name, s_CachedHashBytes); + int[] resourceIndexes = resourceGroup.GetResourceIndexes(); + binaryWriter.Write(resourceIndexes.Length); + foreach (ushort resourceIndex in resourceIndexes) + { + binaryWriter.Write(resourceIndex); + } + } + } + + Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength); + return true; + } + + /// + /// 序列化可更新模式版本资源列表(版本 1)回调函数。 + /// + /// 目标流。 + /// 要序列化的可更新模式版本资源列表(版本 1)。 + /// 是否序列化可更新模式版本资源列表(版本 1)成功。 + public static bool UpdatableVersionListSerializeCallback_V1(Stream stream, UpdatableVersionList versionList) + { + if (!versionList.IsValid) + { + return false; + } + + Utility.Random.GetRandomBytes(s_CachedHashBytes); + using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.UTF8)) + { + binaryWriter.Write(s_CachedHashBytes); + binaryWriter.WriteEncryptedString(versionList.ApplicableGameVersion, s_CachedHashBytes); + binaryWriter.Write7BitEncodedInt32(versionList.InternalResourceVersion); + UpdatableVersionList.Asset[] assets = versionList.GetAssets(); + binaryWriter.Write7BitEncodedInt32(assets.Length); + foreach (UpdatableVersionList.Asset asset in assets) + { + binaryWriter.WriteEncryptedString(asset.Name, s_CachedHashBytes); + int[] dependencyAssetIndexes = asset.GetDependencyAssetIndexes(); + binaryWriter.Write7BitEncodedInt32(dependencyAssetIndexes.Length); + foreach (int dependencyAssetIndex in dependencyAssetIndexes) + { + binaryWriter.Write7BitEncodedInt32(dependencyAssetIndex); + } + } + + UpdatableVersionList.Resource[] resources = versionList.GetResources(); + binaryWriter.Write7BitEncodedInt32(resources.Length); + foreach (UpdatableVersionList.Resource resource in resources) + { + binaryWriter.WriteEncryptedString(resource.Name, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Variant, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Extension != DefaultExtension ? resource.Extension : null, s_CachedHashBytes); + binaryWriter.Write(resource.LoadType); + binaryWriter.Write7BitEncodedInt32(resource.Length); + binaryWriter.Write(resource.HashCode); + binaryWriter.Write7BitEncodedInt32(resource.CompressedLength); + binaryWriter.Write(resource.CompressedHashCode); + int[] assetIndexes = resource.GetAssetIndexes(); + binaryWriter.Write7BitEncodedInt32(assetIndexes.Length); + foreach (int assetIndex in assetIndexes) + { + binaryWriter.Write7BitEncodedInt32(assetIndex); + } + } + + UpdatableVersionList.ResourceGroup[] resourceGroups = versionList.GetResourceGroups(); + binaryWriter.Write7BitEncodedInt32(resourceGroups.Length); + foreach (UpdatableVersionList.ResourceGroup resourceGroup in resourceGroups) + { + binaryWriter.WriteEncryptedString(resourceGroup.Name, s_CachedHashBytes); + int[] resourceIndexes = resourceGroup.GetResourceIndexes(); + binaryWriter.Write7BitEncodedInt32(resourceIndexes.Length); + foreach (int resourceIndex in resourceIndexes) + { + binaryWriter.Write7BitEncodedInt32(resourceIndex); + } + } + } + + Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength); + return true; + } + + /// + /// 序列化可更新模式版本资源列表(版本 2)回调函数。 + /// + /// 目标流。 + /// 要序列化的可更新模式版本资源列表(版本 2)。 + /// 是否序列化可更新模式版本资源列表(版本 2)成功。 + public static bool UpdatableVersionListSerializeCallback_V2(Stream stream, UpdatableVersionList versionList) + { + if (!versionList.IsValid) + { + return false; + } + + Utility.Random.GetRandomBytes(s_CachedHashBytes); + using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.UTF8)) + { + binaryWriter.Write(s_CachedHashBytes); + binaryWriter.WriteEncryptedString(versionList.ApplicableGameVersion, s_CachedHashBytes); + binaryWriter.Write7BitEncodedInt32(versionList.InternalResourceVersion); + UpdatableVersionList.Asset[] assets = versionList.GetAssets(); + binaryWriter.Write7BitEncodedInt32(assets.Length); + foreach (UpdatableVersionList.Asset asset in assets) + { + binaryWriter.WriteEncryptedString(asset.Name, s_CachedHashBytes); + int[] dependencyAssetIndexes = asset.GetDependencyAssetIndexes(); + binaryWriter.Write7BitEncodedInt32(dependencyAssetIndexes.Length); + foreach (int dependencyAssetIndex in dependencyAssetIndexes) + { + binaryWriter.Write7BitEncodedInt32(dependencyAssetIndex); + } + } + + UpdatableVersionList.Resource[] resources = versionList.GetResources(); + binaryWriter.Write7BitEncodedInt32(resources.Length); + foreach (UpdatableVersionList.Resource resource in resources) + { + binaryWriter.WriteEncryptedString(resource.Name, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Variant, s_CachedHashBytes); + binaryWriter.WriteEncryptedString(resource.Extension != DefaultExtension ? resource.Extension : null, s_CachedHashBytes); + binaryWriter.Write(resource.LoadType); + binaryWriter.Write7BitEncodedInt32(resource.Length); + binaryWriter.Write(resource.HashCode); + binaryWriter.Write7BitEncodedInt32(resource.CompressedLength); + binaryWriter.Write(resource.CompressedHashCode); + int[] assetIndexes = resource.GetAssetIndexes(); + binaryWriter.Write7BitEncodedInt32(assetIndexes.Length); + foreach (int assetIndex in assetIndexes) + { + binaryWriter.Write7BitEncodedInt32(assetIndex); + } + } + + UpdatableVersionList.FileSystem[] fileSystems = versionList.GetFileSystems(); + binaryWriter.Write7BitEncodedInt32(fileSystems.Length); + foreach (UpdatableVersionList.FileSystem fileSystem in fileSystems) + { + binaryWriter.WriteEncryptedString(fileSystem.Name, s_CachedHashBytes); + int[] resourceIndexes = fileSystem.GetResourceIndexes(); + binaryWriter.Write7BitEncodedInt32(resourceIndexes.Length); + foreach (int resourceIndex in resourceIndexes) + { + binaryWriter.Write7BitEncodedInt32(resourceIndex); + } + } + + UpdatableVersionList.ResourceGroup[] resourceGroups = versionList.GetResourceGroups(); + binaryWriter.Write7BitEncodedInt32(resourceGroups.Length); + foreach (UpdatableVersionList.ResourceGroup resourceGroup in resourceGroups) + { + binaryWriter.WriteEncryptedString(resourceGroup.Name, s_CachedHashBytes); + int[] resourceIndexes = resourceGroup.GetResourceIndexes(); + binaryWriter.Write7BitEncodedInt32(resourceIndexes.Length); + foreach (int resourceIndex in resourceIndexes) + { + binaryWriter.Write7BitEncodedInt32(resourceIndex); + } + } + } + + Array.Clear(s_CachedHashBytes, 0, CachedHashBytesLength); + return true; + } + +#endif + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback.cs.meta new file mode 100644 index 0000000..b5a77e7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9730081343813f34e8835804bf32290f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback.cs new file mode 100644 index 0000000..025122c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.IO; +using System.Text; + +namespace UnityGameFramework.Runtime +{ + /// + /// 内置版本资源列表序列化器。 + /// + public static partial class BuiltinVersionListSerializer + { + /// + /// 尝试从可更新模式版本资源列表(版本 0)获取指定键的值回调函数。 + /// + /// 指定流。 + /// 指定键。 + /// 指定键的值。 + /// 从可更新模式版本资源列表(版本 0)获取指定键的值是否成功。 + public static bool UpdatableVersionListTryGetValueCallback_V0(Stream stream, string key, out object value) + { + value = null; + if (key != "InternalResourceVersion") + { + return false; + } + + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + binaryReader.BaseStream.Position += CachedHashBytesLength; + byte stringLength = binaryReader.ReadByte(); + binaryReader.BaseStream.Position += stringLength; + value = binaryReader.ReadInt32(); + } + + return true; + } + + /// + /// 尝试从可更新模式版本资源列表(版本 1 或版本 2)获取指定键的值回调函数。 + /// + /// 指定流。 + /// 指定键。 + /// 指定键的值。 + /// 从可更新模式版本资源列表(版本 1 或版本 2)获取指定键的值是否成功。 + public static bool UpdatableVersionListTryGetValueCallback_V1_V2(Stream stream, string key, out object value) + { + value = null; + if (key != "InternalResourceVersion") + { + return false; + } + + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + binaryReader.BaseStream.Position += CachedHashBytesLength; + byte stringLength = binaryReader.ReadByte(); + binaryReader.BaseStream.Position += stringLength; + value = binaryReader.Read7BitEncodedInt32(); + } + + return true; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback.cs.meta new file mode 100644 index 0000000..47c9a4d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c39515b9d8a0b0d4a9045edf9c8c1143 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.cs new file mode 100644 index 0000000..6f9279d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.cs @@ -0,0 +1,54 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System.Collections.Generic; + +namespace UnityGameFramework.Runtime +{ + /// + /// 内置版本资源列表序列化器。 + /// + public static partial class BuiltinVersionListSerializer + { + private const string DefaultExtension = "dat"; + private const int CachedHashBytesLength = 4; + private static readonly byte[] s_CachedHashBytes = new byte[CachedHashBytesLength]; + + private static int AssetNameToDependencyAssetNamesComparer(KeyValuePair a, KeyValuePair b) + { + return a.Key.CompareTo(b.Key); + } + + private static int GetAssetNameIndex(List> assetNameToDependencyAssetNames, string assetName) + { + return GetAssetNameIndexWithBinarySearch(assetNameToDependencyAssetNames, assetName, 0, assetNameToDependencyAssetNames.Count - 1); + } + + private static int GetAssetNameIndexWithBinarySearch(List> assetNameToDependencyAssetNames, string assetName, int leftIndex, int rightIndex) + { + if (leftIndex > rightIndex) + { + return -1; + } + + int middleIndex = (leftIndex + rightIndex) / 2; + if (assetNameToDependencyAssetNames[middleIndex].Key == assetName) + { + return middleIndex; + } + + if (assetNameToDependencyAssetNames[middleIndex].Key.CompareTo(assetName) > 0) + { + return GetAssetNameIndexWithBinarySearch(assetNameToDependencyAssetNames, assetName, leftIndex, middleIndex - 1); + } + else + { + return GetAssetNameIndexWithBinarySearch(assetNameToDependencyAssetNames, assetName, middleIndex + 1, rightIndex); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.cs.meta new file mode 100644 index 0000000..68a5296 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/BuiltinVersionListSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ca9f81a8ced0aa748b1a7a514ccf9948 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/DefaultLoadResourceAgentHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/DefaultLoadResourceAgentHelper.cs new file mode 100644 index 0000000..4d98e76 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/DefaultLoadResourceAgentHelper.cs @@ -0,0 +1,595 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.FileSystem; +using GameFramework.Resource; +using System; +using UnityEngine; +#if UNITY_5_4_OR_NEWER +using UnityEngine.Networking; +#endif +using UnityEngine.SceneManagement; +using Utility = GameFramework.Utility; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认加载资源代理辅助器。 + /// + public class DefaultLoadResourceAgentHelper : LoadResourceAgentHelperBase, IDisposable + { + private string m_FileFullPath = null; + private string m_FileName = null; + private string m_BytesFullPath = null; + private string m_AssetName = null; + private float m_LastProgress = 0f; + private bool m_Disposed = false; +#if UNITY_5_4_OR_NEWER + private UnityWebRequest m_UnityWebRequest = null; +#else + private WWW m_WWW = null; +#endif + private AssetBundleCreateRequest m_FileAssetBundleCreateRequest = null; + private AssetBundleCreateRequest m_BytesAssetBundleCreateRequest = null; + private AssetBundleRequest m_AssetBundleRequest = null; + private AsyncOperation m_AsyncOperation = null; + + private EventHandler m_LoadResourceAgentHelperUpdateEventHandler = null; + private EventHandler m_LoadResourceAgentHelperReadFileCompleteEventHandler = null; + private EventHandler m_LoadResourceAgentHelperReadBytesCompleteEventHandler = null; + private EventHandler m_LoadResourceAgentHelperParseBytesCompleteEventHandler = null; + private EventHandler m_LoadResourceAgentHelperLoadCompleteEventHandler = null; + private EventHandler m_LoadResourceAgentHelperErrorEventHandler = null; + + /// + /// 加载资源代理辅助器异步加载资源更新事件。 + /// + public override event EventHandler LoadResourceAgentHelperUpdate + { + add + { + m_LoadResourceAgentHelperUpdateEventHandler += value; + } + remove + { + m_LoadResourceAgentHelperUpdateEventHandler -= value; + } + } + + /// + /// 加载资源代理辅助器异步读取资源文件完成事件。 + /// + public override event EventHandler LoadResourceAgentHelperReadFileComplete + { + add + { + m_LoadResourceAgentHelperReadFileCompleteEventHandler += value; + } + remove + { + m_LoadResourceAgentHelperReadFileCompleteEventHandler -= value; + } + } + + /// + /// 加载资源代理辅助器异步读取资源二进制流完成事件。 + /// + public override event EventHandler LoadResourceAgentHelperReadBytesComplete + { + add + { + m_LoadResourceAgentHelperReadBytesCompleteEventHandler += value; + } + remove + { + m_LoadResourceAgentHelperReadBytesCompleteEventHandler -= value; + } + } + + /// + /// 加载资源代理辅助器异步将资源二进制流转换为加载对象完成事件。 + /// + public override event EventHandler LoadResourceAgentHelperParseBytesComplete + { + add + { + m_LoadResourceAgentHelperParseBytesCompleteEventHandler += value; + } + remove + { + m_LoadResourceAgentHelperParseBytesCompleteEventHandler -= value; + } + } + + /// + /// 加载资源代理辅助器异步加载资源完成事件。 + /// + public override event EventHandler LoadResourceAgentHelperLoadComplete + { + add + { + m_LoadResourceAgentHelperLoadCompleteEventHandler += value; + } + remove + { + m_LoadResourceAgentHelperLoadCompleteEventHandler -= value; + } + } + + /// + /// 加载资源代理辅助器错误事件。 + /// + public override event EventHandler LoadResourceAgentHelperError + { + add + { + m_LoadResourceAgentHelperErrorEventHandler += value; + } + remove + { + m_LoadResourceAgentHelperErrorEventHandler -= value; + } + } + + /// + /// 通过加载资源代理辅助器开始异步读取资源文件。 + /// + /// 要加载资源的完整路径名。 + public override void ReadFile(string fullPath) + { + if (m_LoadResourceAgentHelperReadFileCompleteEventHandler == null || m_LoadResourceAgentHelperUpdateEventHandler == null || m_LoadResourceAgentHelperErrorEventHandler == null) + { + Log.Fatal("Load resource agent helper handler is invalid."); + return; + } + + m_FileFullPath = fullPath; + m_FileAssetBundleCreateRequest = AssetBundle.LoadFromFileAsync(fullPath); + } + + /// + /// 通过加载资源代理辅助器开始异步读取资源文件。 + /// + /// 要加载资源的文件系统。 + /// 要加载资源的名称。 + public override void ReadFile(IFileSystem fileSystem, string name) + { +#if UNITY_5_3_5 || UNITY_5_3_6 || UNITY_5_3_7 || UNITY_5_3_8 || UNITY_5_4_OR_NEWER + if (m_LoadResourceAgentHelperReadFileCompleteEventHandler == null || m_LoadResourceAgentHelperUpdateEventHandler == null || m_LoadResourceAgentHelperErrorEventHandler == null) + { + Log.Fatal("Load resource agent helper handler is invalid."); + return; + } + + FileInfo fileInfo = fileSystem.GetFileInfo(name); + m_FileFullPath = fileSystem.FullPath; + m_FileName = name; + m_FileAssetBundleCreateRequest = AssetBundle.LoadFromFileAsync(fileSystem.FullPath, 0u, (ulong)fileInfo.Offset); +#else + Log.Fatal("Load from file async with offset is not supported, use Unity 5.3.5f1 or above."); +#endif + } + + /// + /// 通过加载资源代理辅助器开始异步读取资源二进制流。 + /// + /// 要加载资源的完整路径名。 + public override void ReadBytes(string fullPath) + { + if (m_LoadResourceAgentHelperReadBytesCompleteEventHandler == null || m_LoadResourceAgentHelperUpdateEventHandler == null || m_LoadResourceAgentHelperErrorEventHandler == null) + { + Log.Fatal("Load resource agent helper handler is invalid."); + return; + } + + m_BytesFullPath = fullPath; +#if UNITY_5_4_OR_NEWER + m_UnityWebRequest = UnityWebRequest.Get(Utility.Path.GetRemotePath(fullPath)); +#if UNITY_2017_2_OR_NEWER + m_UnityWebRequest.SendWebRequest(); +#else + m_UnityWebRequest.Send(); +#endif +#else + m_WWW = new WWW(Utility.Path.GetRemotePath(fullPath)); +#endif + } + + /// + /// 通过加载资源代理辅助器开始异步读取资源二进制流。 + /// + /// 要加载资源的文件系统。 + /// 要加载资源的名称。 + public override void ReadBytes(IFileSystem fileSystem, string name) + { + if (m_LoadResourceAgentHelperReadBytesCompleteEventHandler == null || m_LoadResourceAgentHelperUpdateEventHandler == null || m_LoadResourceAgentHelperErrorEventHandler == null) + { + Log.Fatal("Load resource agent helper handler is invalid."); + return; + } + + byte[] bytes = fileSystem.ReadFile(name); + LoadResourceAgentHelperReadBytesCompleteEventArgs loadResourceAgentHelperReadBytesCompleteEventArgs = LoadResourceAgentHelperReadBytesCompleteEventArgs.Create(bytes); + m_LoadResourceAgentHelperReadBytesCompleteEventHandler(this, loadResourceAgentHelperReadBytesCompleteEventArgs); + ReferencePool.Release(loadResourceAgentHelperReadBytesCompleteEventArgs); + } + + /// + /// 通过加载资源代理辅助器开始异步将资源二进制流转换为加载对象。 + /// + /// 要加载资源的二进制流。 + public override void ParseBytes(byte[] bytes) + { + if (m_LoadResourceAgentHelperParseBytesCompleteEventHandler == null || m_LoadResourceAgentHelperUpdateEventHandler == null || m_LoadResourceAgentHelperErrorEventHandler == null) + { + Log.Fatal("Load resource agent helper handler is invalid."); + return; + } + + m_BytesAssetBundleCreateRequest = AssetBundle.LoadFromMemoryAsync(bytes); + } + + /// + /// 通过加载资源代理辅助器开始异步加载资源。 + /// + /// 资源。 + /// 要加载的资源名称。 + /// 要加载资源的类型。 + /// 要加载的资源是否是场景。 + public override void LoadAsset(object resource, string assetName, Type assetType, bool isScene) + { + if (m_LoadResourceAgentHelperLoadCompleteEventHandler == null || m_LoadResourceAgentHelperUpdateEventHandler == null || m_LoadResourceAgentHelperErrorEventHandler == null) + { + Log.Fatal("Load resource agent helper handler is invalid."); + return; + } + + AssetBundle assetBundle = resource as AssetBundle; + if (assetBundle == null) + { + LoadResourceAgentHelperErrorEventArgs loadResourceAgentHelperErrorEventArgs = LoadResourceAgentHelperErrorEventArgs.Create(LoadResourceStatus.TypeError, "Can not load asset bundle from loaded resource which is not an asset bundle."); + m_LoadResourceAgentHelperErrorEventHandler(this, loadResourceAgentHelperErrorEventArgs); + ReferencePool.Release(loadResourceAgentHelperErrorEventArgs); + return; + } + + if (string.IsNullOrEmpty(assetName)) + { + LoadResourceAgentHelperErrorEventArgs loadResourceAgentHelperErrorEventArgs = LoadResourceAgentHelperErrorEventArgs.Create(LoadResourceStatus.AssetError, "Can not load asset from asset bundle which child name is invalid."); + m_LoadResourceAgentHelperErrorEventHandler(this, loadResourceAgentHelperErrorEventArgs); + ReferencePool.Release(loadResourceAgentHelperErrorEventArgs); + return; + } + + m_AssetName = assetName; + if (isScene) + { + int sceneNamePositionStart = assetName.LastIndexOf('/'); + int sceneNamePositionEnd = assetName.LastIndexOf('.'); + if (sceneNamePositionStart <= 0 || sceneNamePositionEnd <= 0 || sceneNamePositionStart > sceneNamePositionEnd) + { + LoadResourceAgentHelperErrorEventArgs loadResourceAgentHelperErrorEventArgs = LoadResourceAgentHelperErrorEventArgs.Create(LoadResourceStatus.AssetError, Utility.Text.Format("Scene name '{0}' is invalid.", assetName)); + m_LoadResourceAgentHelperErrorEventHandler(this, loadResourceAgentHelperErrorEventArgs); + ReferencePool.Release(loadResourceAgentHelperErrorEventArgs); + return; + } + + string sceneName = assetName.Substring(sceneNamePositionStart + 1, sceneNamePositionEnd - sceneNamePositionStart - 1); + m_AsyncOperation = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive); + } + else + { + if (assetType != null) + { + m_AssetBundleRequest = assetBundle.LoadAssetAsync(assetName, assetType); + } + else + { + m_AssetBundleRequest = assetBundle.LoadAssetAsync(assetName); + } + } + } + + /// + /// 重置加载资源代理辅助器。 + /// + public override void Reset() + { + m_FileFullPath = null; + m_FileName = null; + m_BytesFullPath = null; + m_AssetName = null; + m_LastProgress = 0f; + +#if UNITY_5_4_OR_NEWER + if (m_UnityWebRequest != null) + { + m_UnityWebRequest.Dispose(); + m_UnityWebRequest = null; + } +#else + if (m_WWW != null) + { + m_WWW.Dispose(); + m_WWW = null; + } +#endif + + m_FileAssetBundleCreateRequest = null; + m_BytesAssetBundleCreateRequest = null; + m_AssetBundleRequest = null; + m_AsyncOperation = null; + } + + /// + /// 释放资源。 + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// 释放资源。 + /// + /// 释放资源标记。 + protected virtual void Dispose(bool disposing) + { + if (m_Disposed) + { + return; + } + + if (disposing) + { +#if UNITY_5_4_OR_NEWER + if (m_UnityWebRequest != null) + { + m_UnityWebRequest.Dispose(); + m_UnityWebRequest = null; + } +#else + if (m_WWW != null) + { + m_WWW.Dispose(); + m_WWW = null; + } +#endif + } + + m_Disposed = true; + } + + private void Update() + { +#if UNITY_5_4_OR_NEWER + UpdateUnityWebRequest(); +#else + UpdateWWW(); +#endif + UpdateFileAssetBundleCreateRequest(); + UpdateBytesAssetBundleCreateRequest(); + UpdateAssetBundleRequest(); + UpdateAsyncOperation(); + } + +#if UNITY_5_4_OR_NEWER + private void UpdateUnityWebRequest() + { + if (m_UnityWebRequest != null) + { + if (m_UnityWebRequest.isDone) + { + if (string.IsNullOrEmpty(m_UnityWebRequest.error)) + { + LoadResourceAgentHelperReadBytesCompleteEventArgs loadResourceAgentHelperReadBytesCompleteEventArgs = LoadResourceAgentHelperReadBytesCompleteEventArgs.Create(m_UnityWebRequest.downloadHandler.data); + m_LoadResourceAgentHelperReadBytesCompleteEventHandler(this, loadResourceAgentHelperReadBytesCompleteEventArgs); + ReferencePool.Release(loadResourceAgentHelperReadBytesCompleteEventArgs); + m_UnityWebRequest.Dispose(); + m_UnityWebRequest = null; + m_BytesFullPath = null; + m_LastProgress = 0f; + } + else + { + bool isError = false; +#if UNITY_2020_2_OR_NEWER + isError = m_UnityWebRequest.result != UnityWebRequest.Result.Success; +#elif UNITY_2017_1_OR_NEWER + isError = m_UnityWebRequest.isNetworkError || m_UnityWebRequest.isHttpError; +#else + isError = m_UnityWebRequest.isError; +#endif + LoadResourceAgentHelperErrorEventArgs loadResourceAgentHelperErrorEventArgs = LoadResourceAgentHelperErrorEventArgs.Create(LoadResourceStatus.NotExist, Utility.Text.Format("Can not load asset bundle '{0}' with error message '{1}'.", m_BytesFullPath, isError ? m_UnityWebRequest.error : null)); + m_LoadResourceAgentHelperErrorEventHandler(this, loadResourceAgentHelperErrorEventArgs); + ReferencePool.Release(loadResourceAgentHelperErrorEventArgs); + } + } + else if (m_UnityWebRequest.downloadProgress != m_LastProgress) + { + m_LastProgress = m_UnityWebRequest.downloadProgress; + LoadResourceAgentHelperUpdateEventArgs loadResourceAgentHelperUpdateEventArgs = LoadResourceAgentHelperUpdateEventArgs.Create(LoadResourceProgress.ReadResource, m_UnityWebRequest.downloadProgress); + m_LoadResourceAgentHelperUpdateEventHandler(this, loadResourceAgentHelperUpdateEventArgs); + ReferencePool.Release(loadResourceAgentHelperUpdateEventArgs); + } + } + } +#else + private void UpdateWWW() + { + if (m_WWW != null) + { + if (m_WWW.isDone) + { + if (string.IsNullOrEmpty(m_WWW.error)) + { + LoadResourceAgentHelperReadBytesCompleteEventArgs loadResourceAgentHelperReadBytesCompleteEventArgs = LoadResourceAgentHelperReadBytesCompleteEventArgs.Create(m_WWW.bytes); + m_LoadResourceAgentHelperReadBytesCompleteEventHandler(this, loadResourceAgentHelperReadBytesCompleteEventArgs); + ReferencePool.Release(loadResourceAgentHelperReadBytesCompleteEventArgs); + m_WWW.Dispose(); + m_WWW = null; + m_BytesFullPath = null; + m_LastProgress = 0f; + } + else + { + LoadResourceAgentHelperErrorEventArgs loadResourceAgentHelperErrorEventArgs = LoadResourceAgentHelperErrorEventArgs.Create(LoadResourceStatus.NotExist, Utility.Text.Format("Can not load asset bundle '{0}' with error message '{1}'.", m_BytesFullPath, m_WWW.error)); + m_LoadResourceAgentHelperErrorEventHandler(this, loadResourceAgentHelperErrorEventArgs); + ReferencePool.Release(loadResourceAgentHelperErrorEventArgs); + } + } + else if (m_WWW.progress != m_LastProgress) + { + m_LastProgress = m_WWW.progress; + LoadResourceAgentHelperUpdateEventArgs loadResourceAgentHelperUpdateEventArgs = LoadResourceAgentHelperUpdateEventArgs.Create(LoadResourceProgress.ReadResource, m_WWW.progress); + m_LoadResourceAgentHelperUpdateEventHandler(this, loadResourceAgentHelperUpdateEventArgs); + ReferencePool.Release(loadResourceAgentHelperUpdateEventArgs); + } + } + } +#endif + + private void UpdateFileAssetBundleCreateRequest() + { + if (m_FileAssetBundleCreateRequest != null) + { + if (m_FileAssetBundleCreateRequest.isDone) + { + AssetBundle assetBundle = m_FileAssetBundleCreateRequest.assetBundle; + if (assetBundle != null) + { + AssetBundleCreateRequest oldFileAssetBundleCreateRequest = m_FileAssetBundleCreateRequest; + LoadResourceAgentHelperReadFileCompleteEventArgs loadResourceAgentHelperReadFileCompleteEventArgs = LoadResourceAgentHelperReadFileCompleteEventArgs.Create(assetBundle); + m_LoadResourceAgentHelperReadFileCompleteEventHandler(this, loadResourceAgentHelperReadFileCompleteEventArgs); + ReferencePool.Release(loadResourceAgentHelperReadFileCompleteEventArgs); + if (m_FileAssetBundleCreateRequest == oldFileAssetBundleCreateRequest) + { + m_FileAssetBundleCreateRequest = null; + m_LastProgress = 0f; + } + } + else + { + LoadResourceAgentHelperErrorEventArgs loadResourceAgentHelperErrorEventArgs = LoadResourceAgentHelperErrorEventArgs.Create(LoadResourceStatus.NotExist, Utility.Text.Format("Can not load asset bundle from file '{0}' which is not a valid asset bundle.", m_FileName == null ? m_FileFullPath : Utility.Text.Format("{0} | {1}", m_FileFullPath, m_FileName))); + m_LoadResourceAgentHelperErrorEventHandler(this, loadResourceAgentHelperErrorEventArgs); + ReferencePool.Release(loadResourceAgentHelperErrorEventArgs); + } + } + else if (m_FileAssetBundleCreateRequest.progress != m_LastProgress) + { + m_LastProgress = m_FileAssetBundleCreateRequest.progress; + LoadResourceAgentHelperUpdateEventArgs loadResourceAgentHelperUpdateEventArgs = LoadResourceAgentHelperUpdateEventArgs.Create(LoadResourceProgress.LoadResource, m_FileAssetBundleCreateRequest.progress); + m_LoadResourceAgentHelperUpdateEventHandler(this, loadResourceAgentHelperUpdateEventArgs); + ReferencePool.Release(loadResourceAgentHelperUpdateEventArgs); + } + } + } + + private void UpdateBytesAssetBundleCreateRequest() + { + if (m_BytesAssetBundleCreateRequest != null) + { + if (m_BytesAssetBundleCreateRequest.isDone) + { + AssetBundle assetBundle = m_BytesAssetBundleCreateRequest.assetBundle; + if (assetBundle != null) + { + AssetBundleCreateRequest oldBytesAssetBundleCreateRequest = m_BytesAssetBundleCreateRequest; + LoadResourceAgentHelperParseBytesCompleteEventArgs loadResourceAgentHelperParseBytesCompleteEventArgs = LoadResourceAgentHelperParseBytesCompleteEventArgs.Create(assetBundle); + m_LoadResourceAgentHelperParseBytesCompleteEventHandler(this, loadResourceAgentHelperParseBytesCompleteEventArgs); + ReferencePool.Release(loadResourceAgentHelperParseBytesCompleteEventArgs); + if (m_BytesAssetBundleCreateRequest == oldBytesAssetBundleCreateRequest) + { + m_BytesAssetBundleCreateRequest = null; + m_LastProgress = 0f; + } + } + else + { + LoadResourceAgentHelperErrorEventArgs loadResourceAgentHelperErrorEventArgs = LoadResourceAgentHelperErrorEventArgs.Create(LoadResourceStatus.NotExist, "Can not load asset bundle from memory which is not a valid asset bundle."); + m_LoadResourceAgentHelperErrorEventHandler(this, loadResourceAgentHelperErrorEventArgs); + ReferencePool.Release(loadResourceAgentHelperErrorEventArgs); + } + } + else if (m_BytesAssetBundleCreateRequest.progress != m_LastProgress) + { + m_LastProgress = m_BytesAssetBundleCreateRequest.progress; + LoadResourceAgentHelperUpdateEventArgs loadResourceAgentHelperUpdateEventArgs = LoadResourceAgentHelperUpdateEventArgs.Create(LoadResourceProgress.LoadResource, m_BytesAssetBundleCreateRequest.progress); + m_LoadResourceAgentHelperUpdateEventHandler(this, loadResourceAgentHelperUpdateEventArgs); + ReferencePool.Release(loadResourceAgentHelperUpdateEventArgs); + } + } + } + + private void UpdateAssetBundleRequest() + { + if (m_AssetBundleRequest != null) + { + if (m_AssetBundleRequest.isDone) + { + if (m_AssetBundleRequest.asset != null) + { + LoadResourceAgentHelperLoadCompleteEventArgs loadResourceAgentHelperLoadCompleteEventArgs = LoadResourceAgentHelperLoadCompleteEventArgs.Create(m_AssetBundleRequest.asset); + m_LoadResourceAgentHelperLoadCompleteEventHandler(this, loadResourceAgentHelperLoadCompleteEventArgs); + ReferencePool.Release(loadResourceAgentHelperLoadCompleteEventArgs); + m_AssetName = null; + m_LastProgress = 0f; + m_AssetBundleRequest = null; + } + else + { + LoadResourceAgentHelperErrorEventArgs loadResourceAgentHelperErrorEventArgs = LoadResourceAgentHelperErrorEventArgs.Create(LoadResourceStatus.AssetError, Utility.Text.Format("Can not load asset '{0}' from asset bundle which is not exist.", m_AssetName)); + m_LoadResourceAgentHelperErrorEventHandler(this, loadResourceAgentHelperErrorEventArgs); + ReferencePool.Release(loadResourceAgentHelperErrorEventArgs); + } + } + else if (m_AssetBundleRequest.progress != m_LastProgress) + { + m_LastProgress = m_AssetBundleRequest.progress; + LoadResourceAgentHelperUpdateEventArgs loadResourceAgentHelperUpdateEventArgs = LoadResourceAgentHelperUpdateEventArgs.Create(LoadResourceProgress.LoadAsset, m_AssetBundleRequest.progress); + m_LoadResourceAgentHelperUpdateEventHandler(this, loadResourceAgentHelperUpdateEventArgs); + ReferencePool.Release(loadResourceAgentHelperUpdateEventArgs); + } + } + } + + private void UpdateAsyncOperation() + { + if (m_AsyncOperation != null) + { + if (m_AsyncOperation.isDone) + { + if (m_AsyncOperation.allowSceneActivation) + { + SceneAsset sceneAsset = new SceneAsset(); + LoadResourceAgentHelperLoadCompleteEventArgs loadResourceAgentHelperLoadCompleteEventArgs = LoadResourceAgentHelperLoadCompleteEventArgs.Create(sceneAsset); + m_LoadResourceAgentHelperLoadCompleteEventHandler(this, loadResourceAgentHelperLoadCompleteEventArgs); + ReferencePool.Release(loadResourceAgentHelperLoadCompleteEventArgs); + m_AssetName = null; + m_LastProgress = 0f; + m_AsyncOperation = null; + } + else + { + LoadResourceAgentHelperErrorEventArgs loadResourceAgentHelperErrorEventArgs = LoadResourceAgentHelperErrorEventArgs.Create(LoadResourceStatus.AssetError, Utility.Text.Format("Can not load scene asset '{0}' from asset bundle.", m_AssetName)); + m_LoadResourceAgentHelperErrorEventHandler(this, loadResourceAgentHelperErrorEventArgs); + ReferencePool.Release(loadResourceAgentHelperErrorEventArgs); + } + } + else if (m_AsyncOperation.progress != m_LastProgress) + { + m_LastProgress = m_AsyncOperation.progress; + LoadResourceAgentHelperUpdateEventArgs loadResourceAgentHelperUpdateEventArgs = LoadResourceAgentHelperUpdateEventArgs.Create(LoadResourceProgress.LoadScene, m_AsyncOperation.progress); + m_LoadResourceAgentHelperUpdateEventHandler(this, loadResourceAgentHelperUpdateEventArgs); + ReferencePool.Release(loadResourceAgentHelperUpdateEventArgs); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/DefaultLoadResourceAgentHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/DefaultLoadResourceAgentHelper.cs.meta new file mode 100644 index 0000000..91c066e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/DefaultLoadResourceAgentHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9288c544ad6d5a84d8e3610015bc5d61 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/DefaultResourceHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/DefaultResourceHelper.cs new file mode 100644 index 0000000..e90f950 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/DefaultResourceHelper.cs @@ -0,0 +1,185 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using System; +using System.Collections; +using UnityEngine; +#if UNITY_5_4_OR_NEWER +using UnityEngine.Networking; +#endif +using UnityEngine.SceneManagement; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认资源辅助器。 + /// + public class DefaultResourceHelper : ResourceHelperBase + { + /// + /// 直接从指定文件路径加载数据流。 + /// + /// 文件路径。 + /// 加载数据流回调函数集。 + /// 用户自定义数据。 + public override void LoadBytes(string fileUri, LoadBytesCallbacks loadBytesCallbacks, object userData) + { + StartCoroutine(LoadBytesCo(fileUri, loadBytesCallbacks, userData)); + } + + /// + /// 卸载场景。 + /// + /// 场景资源名称。 + /// 卸载场景回调函数集。 + /// 用户自定义数据。 + public override void UnloadScene(string sceneAssetName, UnloadSceneCallbacks unloadSceneCallbacks, object userData) + { +#if UNITY_5_5_OR_NEWER + if (gameObject.activeInHierarchy) + { + StartCoroutine(UnloadSceneCo(sceneAssetName, unloadSceneCallbacks, userData)); + } + else + { + SceneManager.UnloadSceneAsync(SceneComponent.GetSceneName(sceneAssetName)); + } +#else + if (SceneManager.UnloadScene(SceneComponent.GetSceneName(sceneAssetName))) + { + if (unloadSceneCallbacks.UnloadSceneSuccessCallback != null) + { + unloadSceneCallbacks.UnloadSceneSuccessCallback(sceneAssetName, userData); + } + } + else + { + if (unloadSceneCallbacks.UnloadSceneFailureCallback != null) + { + unloadSceneCallbacks.UnloadSceneFailureCallback(sceneAssetName, userData); + } + } +#endif + } + + /// + /// 释放资源。 + /// + /// 要释放的资源。 + public override void Release(object objectToRelease) + { + AssetBundle assetBundle = objectToRelease as AssetBundle; + if (assetBundle != null) + { + assetBundle.Unload(true); + return; + } + + /* Unity 当前 Resources.UnloadAsset 在 iOS 设备上会导致一些诡异问题,先不用这部分 + SceneAsset sceneAsset = objectToRelease as SceneAsset; + if (sceneAsset != null) + { + return; + } + + Object unityObject = objectToRelease as Object; + if (unityObject == null) + { + Log.Warning("Asset is invalid."); + return; + } + + if (unityObject is GameObject || unityObject is MonoBehaviour) + { + // UnloadAsset may only be used on individual assets and can not be used on GameObject's / Components or AssetBundles. + return; + } + + Resources.UnloadAsset(unityObject); + */ + } + + private void Start() + { + } + + private IEnumerator LoadBytesCo(string fileUri, LoadBytesCallbacks loadBytesCallbacks, object userData) + { + bool isError = false; + byte[] bytes = null; + string errorMessage = null; + DateTime startTime = DateTime.UtcNow; + +#if UNITY_5_4_OR_NEWER + UnityWebRequest unityWebRequest = UnityWebRequest.Get(fileUri); +#if UNITY_2017_2_OR_NEWER + yield return unityWebRequest.SendWebRequest(); +#else + yield return unityWebRequest.Send(); +#endif + +#if UNITY_2020_2_OR_NEWER + isError = unityWebRequest.result != UnityWebRequest.Result.Success; +#elif UNITY_2017_1_OR_NEWER + isError = unityWebRequest.isNetworkError || unityWebRequest.isHttpError; +#else + isError = unityWebRequest.isError; +#endif + bytes = unityWebRequest.downloadHandler.data; + errorMessage = isError ? unityWebRequest.error : null; + unityWebRequest.Dispose(); +#else + WWW www = new WWW(fileUri); + yield return www; + + isError = !string.IsNullOrEmpty(www.error); + bytes = www.bytes; + errorMessage = www.error; + www.Dispose(); +#endif + + if (!isError) + { + float elapseSeconds = (float)(DateTime.UtcNow - startTime).TotalSeconds; + loadBytesCallbacks.LoadBytesSuccessCallback(fileUri, bytes, elapseSeconds, userData); + } + else if (loadBytesCallbacks.LoadBytesFailureCallback != null) + { + loadBytesCallbacks.LoadBytesFailureCallback(fileUri, errorMessage, userData); + } + } + +#if UNITY_5_5_OR_NEWER + private IEnumerator UnloadSceneCo(string sceneAssetName, UnloadSceneCallbacks unloadSceneCallbacks, object userData) + { + AsyncOperation asyncOperation = SceneManager.UnloadSceneAsync(SceneComponent.GetSceneName(sceneAssetName)); + if (asyncOperation == null) + { + yield break; + } + + yield return asyncOperation; + + if (asyncOperation.allowSceneActivation) + { + if (unloadSceneCallbacks.UnloadSceneSuccessCallback != null) + { + unloadSceneCallbacks.UnloadSceneSuccessCallback(sceneAssetName, userData); + } + } + else + { + if (unloadSceneCallbacks.UnloadSceneFailureCallback != null) + { + unloadSceneCallbacks.UnloadSceneFailureCallback(sceneAssetName, userData); + } + } + } +#endif + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/DefaultResourceHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/DefaultResourceHelper.cs.meta new file mode 100644 index 0000000..0cbaefd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/DefaultResourceHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 720e532446c14964a8fe343f1196793f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/EditorResourceComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/EditorResourceComponent.cs new file mode 100644 index 0000000..019115e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/EditorResourceComponent.cs @@ -0,0 +1,1867 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Download; +using GameFramework.FileSystem; +using GameFramework.ObjectPool; +using GameFramework.Resource; +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace UnityGameFramework.Runtime +{ + /// + /// 编辑器资源组件。 + /// + [DisallowMultipleComponent] + public sealed class EditorResourceComponent : MonoBehaviour, IResourceManager + { + private const int DefaultPriority = 0; + private static readonly int AssetsStringLength = "Assets".Length; + + [SerializeField] + private bool m_EnableCachedAssets = true; + + [SerializeField] + private int m_LoadAssetCountPerFrame = 1; + + [SerializeField] + private float m_MinLoadAssetRandomDelaySeconds = 0f; + + [SerializeField] + private float m_MaxLoadAssetRandomDelaySeconds = 0f; + + private string m_ReadOnlyPath = null; + private string m_ReadWritePath = null; + private Dictionary m_CachedAssets = null; + private GameFrameworkLinkedList m_LoadAssetInfos = null; + private GameFrameworkLinkedList m_LoadSceneInfos = null; + private GameFrameworkLinkedList m_UnloadSceneInfos = null; + + /// + /// 获取资源只读区路径。 + /// + public string ReadOnlyPath + { + get + { + return m_ReadOnlyPath; + } + } + + /// + /// 获取资源读写区路径。 + /// + public string ReadWritePath + { + get + { + return m_ReadWritePath; + } + } + + /// + /// 获取资源模式。 + /// + public ResourceMode ResourceMode + { + get + { + return ResourceMode.Unspecified; + } + } + + /// + /// 获取当前变体。 + /// + public string CurrentVariant + { + get + { + return null; + } + } + + /// + /// 获取单机模式版本资源列表序列化器。 + /// + public PackageVersionListSerializer PackageVersionListSerializer + { + get + { + throw new NotSupportedException("ReadWriteVersionListSerializer"); + } + } + + /// + /// 获取可更新模式版本资源列表序列化器。 + /// + public UpdatableVersionListSerializer UpdatableVersionListSerializer + { + get + { + throw new NotSupportedException("ReadWriteVersionListSerializer"); + } + } + + /// + /// 获取本地只读区版本资源列表序列化器。 + /// + public ReadOnlyVersionListSerializer ReadOnlyVersionListSerializer + { + get + { + throw new NotSupportedException("ReadWriteVersionListSerializer"); + } + } + + /// + /// 获取本地读写区版本资源列表序列化器。 + /// + public ReadWriteVersionListSerializer ReadWriteVersionListSerializer + { + get + { + throw new NotSupportedException("ReadWriteVersionListSerializer"); + } + } + + /// + /// 获取资源包版本资源列表序列化器。 + /// + public ResourcePackVersionListSerializer ResourcePackVersionListSerializer + { + get + { + throw new NotSupportedException("ResourcePackVersionListSerializer"); + } + } + + /// + /// 获取当前资源适用的游戏版本号。 + /// + public string ApplicableGameVersion + { + get + { + throw new NotSupportedException("ApplicableGameVersion"); + } + } + + /// + /// 获取当前内部资源版本号。 + /// + public int InternalResourceVersion + { + get + { + throw new NotSupportedException("InternalResourceVersion"); + } + } + + /// + /// 获取已准备完毕资源数量。 + /// + public int AssetCount + { + get + { + throw new NotSupportedException("AssetCount"); + } + } + + /// + /// 获取已准备完毕资源数量。 + /// + public int ResourceCount + { + get + { + throw new NotSupportedException("ResourceCount"); + } + } + + /// + /// 获取资源组个数。 + /// + public int ResourceGroupCount + { + get + { + throw new NotSupportedException("ResourceGroupCount"); + } + } + + /// + /// 获取或设置资源更新下载地址。 + /// + public string UpdatePrefixUri + { + get + { + throw new NotSupportedException("UpdatePrefixUri"); + } + set + { + throw new NotSupportedException("UpdatePrefixUri"); + } + } + + /// + /// 获取或设置每更新多少字节的资源,重新生成一次版本资源列表。 + /// + public int GenerateReadWriteVersionListLength + { + get + { + throw new NotSupportedException("GenerateReadWriteVersionListLength"); + } + set + { + throw new NotSupportedException("GenerateReadWriteVersionListLength"); + } + } + + /// + /// 获取正在应用的资源包路径。 + /// + public string ApplyingResourcePackPath + { + get + { + throw new NotSupportedException("ApplyingResourcePackPath"); + } + } + + /// + /// 获取等待应用资源数量。 + /// + public int ApplyWaitingCount + { + get + { + throw new NotSupportedException("ApplyWaitingCount"); + } + } + + /// + /// 获取或设置资源更新重试次数。 + /// + public int UpdateRetryCount + { + get + { + throw new NotSupportedException("UpdateRetryCount"); + } + set + { + throw new NotSupportedException("UpdateRetryCount"); + } + } + + /// + /// 获取正在更新的资源组。 + /// + public IResourceGroup UpdatingResourceGroup + { + get + { + throw new NotSupportedException("UpdatingResourceGroup"); + } + } + + /// + /// 获取等待更新资源个数。 + /// + public int UpdateWaitingCount + { + get + { + throw new NotSupportedException("UpdateWaitingCount"); + } + } + + /// + /// 获取使用时下载的等待更新资源数量。 + /// + public int UpdateWaitingWhilePlayingCount + { + get + { + throw new NotSupportedException("UpdateWaitingWhilePlayingCount"); + } + } + + /// + /// 获取候选更新资源数量。 + /// + public int UpdateCandidateCount + { + get + { + throw new NotSupportedException("UpdateCandidateCount"); + } + } + + /// + /// 获取加载资源代理总个数。 + /// + public int LoadTotalAgentCount + { + get + { + throw new NotSupportedException("LoadTotalAgentCount"); + } + } + + /// + /// 获取可用加载资源代理个数。 + /// + public int LoadFreeAgentCount + { + get + { + throw new NotSupportedException("LoadFreeAgentCount"); + } + } + + /// + /// 获取工作中加载资源代理个数。 + /// + public int LoadWorkingAgentCount + { + get + { + throw new NotSupportedException("LoadWorkingAgentCount"); + } + } + + /// + /// 获取等待加载资源任务个数。 + /// + public int LoadWaitingTaskCount + { + get + { + throw new NotSupportedException("LoadWaitingTaskCount"); + } + } + + /// + /// 获取或设置资源对象池自动释放可释放对象的间隔秒数。 + /// + public float AssetAutoReleaseInterval + { + get + { + throw new NotSupportedException("AssetAutoReleaseInterval"); + } + set + { + throw new NotSupportedException("AssetAutoReleaseInterval"); + } + } + + /// + /// 获取或设置资源对象池的容量。 + /// + public int AssetCapacity + { + get + { + throw new NotSupportedException("AssetCapacity"); + } + set + { + throw new NotSupportedException("AssetCapacity"); + } + } + + /// + /// 获取或设置资源对象池对象过期秒数。 + /// + public float AssetExpireTime + { + get + { + throw new NotSupportedException("AssetExpireTime"); + } + set + { + throw new NotSupportedException("AssetExpireTime"); + } + } + + /// + /// 获取或设置资源对象池的优先级。 + /// + public int AssetPriority + { + get + { + throw new NotSupportedException("AssetPriority"); + } + set + { + throw new NotSupportedException("AssetPriority"); + } + } + + /// + /// 获取或设置资源对象池自动释放可释放对象的间隔秒数。 + /// + public float ResourceAutoReleaseInterval + { + get + { + throw new NotSupportedException("ResourceAutoReleaseInterval"); + } + set + { + throw new NotSupportedException("ResourceAutoReleaseInterval"); + } + } + + /// + /// 获取或设置资源对象池的容量。 + /// + public int ResourceCapacity + { + get + { + throw new NotSupportedException("ResourceCapacity"); + } + set + { + throw new NotSupportedException("ResourceCapacity"); + } + } + + /// + /// 获取或设置资源对象池对象过期秒数。 + /// + public float ResourceExpireTime + { + get + { + throw new NotSupportedException("ResourceExpireTime"); + } + set + { + throw new NotSupportedException("ResourceExpireTime"); + } + } + + /// + /// 获取或设置资源对象池的优先级。 + /// + public int ResourcePriority + { + get + { + throw new NotSupportedException("ResourcePriority"); + } + set + { + throw new NotSupportedException("ResourcePriority"); + } + } + + /// + /// 获取等待编辑器加载的资源数量。 + /// + public int LoadWaitingAssetCount + { + get + { + return m_LoadAssetInfos.Count; + } + } + +#pragma warning disable 0067, 0414 + + /// + /// 资源校验开始事件。 + /// + public event EventHandler ResourceVerifyStart = null; + + /// + /// 资源校验成功事件。 + /// + public event EventHandler ResourceVerifySuccess = null; + + /// + /// 资源校验失败事件。 + /// + public event EventHandler ResourceVerifyFailure = null; + + /// + /// 资源应用开始事件。 + /// + public event EventHandler ResourceApplyStart = null; + + /// + /// 资源应用成功事件。 + /// + public event EventHandler ResourceApplySuccess = null; + + /// + /// 资源应用失败事件。 + /// + public event EventHandler ResourceApplyFailure = null; + + /// + /// 资源更新开始事件。 + /// + public event EventHandler ResourceUpdateStart = null; + + /// + /// 资源更新改变事件。 + /// + public event EventHandler ResourceUpdateChanged = null; + + /// + /// 资源更新成功事件。 + /// + public event EventHandler ResourceUpdateSuccess = null; + + /// + /// 资源更新失败事件。 + /// + public event EventHandler ResourceUpdateFailure = null; + + /// + /// 资源更新全部完成事件。 + /// + public event EventHandler ResourceUpdateAllComplete = null; + +#pragma warning restore 0067, 0414 + + private void Awake() + { + m_ReadOnlyPath = null; + m_ReadWritePath = null; + m_CachedAssets = new Dictionary(StringComparer.Ordinal); + m_LoadAssetInfos = new GameFrameworkLinkedList(); + m_LoadSceneInfos = new GameFrameworkLinkedList(); + m_UnloadSceneInfos = new GameFrameworkLinkedList(); + + BaseComponent baseComponent = GetComponent(); + if (baseComponent == null) + { + Log.Error("Can not find base component."); + return; + } + + if (baseComponent.EditorResourceMode) + { + baseComponent.EditorResourceHelper = this; + enabled = true; + } + else + { + enabled = false; + } + } + + private void Update() + { + if (m_LoadAssetInfos.Count > 0) + { + int count = 0; + LinkedListNode current = m_LoadAssetInfos.First; + while (current != null && count < m_LoadAssetCountPerFrame) + { + LoadAssetInfo loadAssetInfo = current.Value; + float elapseSeconds = (float)(DateTime.UtcNow - loadAssetInfo.StartTime).TotalSeconds; + if (elapseSeconds >= loadAssetInfo.DelaySeconds) + { + UnityEngine.Object asset = GetCachedAsset(loadAssetInfo.AssetName); + if (asset == null) + { +#if UNITY_EDITOR + if (loadAssetInfo.AssetType != null) + { + asset = UnityEditor.AssetDatabase.LoadAssetAtPath(loadAssetInfo.AssetName, loadAssetInfo.AssetType); + } + else + { + asset = UnityEditor.AssetDatabase.LoadMainAssetAtPath(loadAssetInfo.AssetName); + } + + if (m_EnableCachedAssets && asset != null) + { + m_CachedAssets.Add(loadAssetInfo.AssetName, asset); + } +#endif + } + + if (asset != null) + { + if (loadAssetInfo.LoadAssetCallbacks.LoadAssetSuccessCallback != null) + { + loadAssetInfo.LoadAssetCallbacks.LoadAssetSuccessCallback(loadAssetInfo.AssetName, asset, elapseSeconds, loadAssetInfo.UserData); + } + } + else + { + if (loadAssetInfo.LoadAssetCallbacks.LoadAssetFailureCallback != null) + { + loadAssetInfo.LoadAssetCallbacks.LoadAssetFailureCallback(loadAssetInfo.AssetName, LoadResourceStatus.AssetError, "Can not load this asset from asset database.", loadAssetInfo.UserData); + } + } + + LinkedListNode next = current.Next; + m_LoadAssetInfos.Remove(loadAssetInfo); + current = next; + count++; + } + else + { + if (loadAssetInfo.LoadAssetCallbacks.LoadAssetUpdateCallback != null) + { + loadAssetInfo.LoadAssetCallbacks.LoadAssetUpdateCallback(loadAssetInfo.AssetName, elapseSeconds / loadAssetInfo.DelaySeconds, loadAssetInfo.UserData); + } + + current = current.Next; + } + } + } + + if (m_LoadSceneInfos.Count > 0) + { + LinkedListNode current = m_LoadSceneInfos.First; + while (current != null) + { + LoadSceneInfo loadSceneInfo = current.Value; + if (loadSceneInfo.AsyncOperation.isDone) + { + if (loadSceneInfo.AsyncOperation.allowSceneActivation) + { + if (loadSceneInfo.LoadSceneCallbacks.LoadSceneSuccessCallback != null) + { + loadSceneInfo.LoadSceneCallbacks.LoadSceneSuccessCallback(loadSceneInfo.SceneAssetName, (float)(DateTime.UtcNow - loadSceneInfo.StartTime).TotalSeconds, loadSceneInfo.UserData); + } + } + else + { + if (loadSceneInfo.LoadSceneCallbacks.LoadSceneFailureCallback != null) + { + loadSceneInfo.LoadSceneCallbacks.LoadSceneFailureCallback(loadSceneInfo.SceneAssetName, LoadResourceStatus.AssetError, "Can not load this scene from asset database.", loadSceneInfo.UserData); + } + } + + LinkedListNode next = current.Next; + m_LoadSceneInfos.Remove(loadSceneInfo); + current = next; + } + else + { + if (loadSceneInfo.LoadSceneCallbacks.LoadSceneUpdateCallback != null) + { + loadSceneInfo.LoadSceneCallbacks.LoadSceneUpdateCallback(loadSceneInfo.SceneAssetName, loadSceneInfo.AsyncOperation.progress, loadSceneInfo.UserData); + } + + current = current.Next; + } + } + } + + if (m_UnloadSceneInfos.Count > 0) + { + LinkedListNode current = m_UnloadSceneInfos.First; + while (current != null) + { + UnloadSceneInfo unloadSceneInfo = current.Value; + if (unloadSceneInfo.AsyncOperation.isDone) + { + if (unloadSceneInfo.AsyncOperation.allowSceneActivation) + { + if (unloadSceneInfo.UnloadSceneCallbacks.UnloadSceneSuccessCallback != null) + { + unloadSceneInfo.UnloadSceneCallbacks.UnloadSceneSuccessCallback(unloadSceneInfo.SceneAssetName, unloadSceneInfo.UserData); + } + } + else + { + if (unloadSceneInfo.UnloadSceneCallbacks.UnloadSceneFailureCallback != null) + { + unloadSceneInfo.UnloadSceneCallbacks.UnloadSceneFailureCallback(unloadSceneInfo.SceneAssetName, unloadSceneInfo.UserData); + } + } + + LinkedListNode next = current.Next; + m_UnloadSceneInfos.Remove(unloadSceneInfo); + current = next; + } + else + { + current = current.Next; + } + } + } + } + + /// + /// 设置资源只读区路径。 + /// + /// 资源只读区路径。 + public void SetReadOnlyPath(string readOnlyPath) + { + if (string.IsNullOrEmpty(readOnlyPath)) + { + Log.Error("Read-only path is invalid."); + return; + } + + m_ReadOnlyPath = readOnlyPath; + } + + /// + /// 设置资源读写区路径。 + /// + /// 资源读写区路径。 + public void SetReadWritePath(string readWritePath) + { + if (string.IsNullOrEmpty(readWritePath)) + { + Log.Error("Read-write path is invalid."); + return; + } + + m_ReadWritePath = readWritePath; + } + + /// + /// 设置资源模式。 + /// + /// 资源模式。 + public void SetResourceMode(ResourceMode resourceMode) + { + throw new NotSupportedException("SetResourceMode"); + } + + /// + /// 设置当前变体。 + /// + /// 当前变体。 + public void SetCurrentVariant(string currentVariant) + { + throw new NotSupportedException("SetCurrentVariant"); + } + + /// + /// 设置对象池管理器。 + /// + /// 对象池管理器。 + public void SetObjectPoolManager(IObjectPoolManager objectPoolManager) + { + throw new NotSupportedException("SetObjectPoolManager"); + } + + /// + /// 设置文件系统管理器。 + /// + /// 文件系统管理器。 + public void SetFileSystemManager(IFileSystemManager fileSystemManager) + { + throw new NotSupportedException("SetFileSystemManager"); + } + + /// + /// 设置下载管理器。 + /// + /// 下载管理器。 + public void SetDownloadManager(IDownloadManager downloadManager) + { + throw new NotSupportedException("SetDownloadManager"); + } + + /// + /// 设置解密资源回调函数。 + /// + /// 要设置的解密资源回调函数。 + /// 如果不设置,将使用默认的解密资源回调函数。 + public void SetDecryptResourceCallback(DecryptResourceCallback decryptResourceCallback) + { + throw new NotSupportedException("SetDecryptResourceCallback"); + } + + /// + /// 设置资源辅助器。 + /// + /// 资源辅助器。 + public void SetResourceHelper(IResourceHelper resourceHelper) + { + throw new NotSupportedException("SetResourceHelper"); + } + + /// + /// 增加加载资源代理辅助器。 + /// + /// 要增加的加载资源代理辅助器。 + public void AddLoadResourceAgentHelper(ILoadResourceAgentHelper loadResourceAgentHelper) + { + throw new NotSupportedException("AddLoadResourceAgentHelper"); + } + + /// + /// 使用单机模式并初始化资源。 + /// + /// 使用单机模式并初始化资源完成时的回调函数。 + public void InitResources(InitResourcesCompleteCallback initResourcesCompleteCallback) + { + throw new NotSupportedException("InitResources"); + } + + /// + /// 检查版本资源列表。 + /// + /// 最新的内部资源版本号。 + /// 检查版本资源列表结果。 + public CheckVersionListResult CheckVersionList(int latestInternalResourceVersion) + { + throw new NotSupportedException("CheckVersionList"); + } + + /// + /// 使用可更新模式并更新版本资源列表。 + /// + /// 版本资源列表大小。 + /// 版本资源列表哈希值。 + /// 版本资源列表压缩后大小。 + /// 版本资源列表压缩后哈希值。 + /// 版本资源列表更新回调函数集。 + public void UpdateVersionList(int versionListLength, int versionListHashCode, int versionListCompressedLength, int versionListCompressedHashCode, UpdateVersionListCallbacks updateVersionListCallbacks) + { + throw new NotSupportedException("UpdateVersionList"); + } + + /// + /// 使用可更新模式并校验资源。 + /// + /// 每帧至少校验资源的大小,以字节为单位。 + /// 使用可更新模式并校验资源完成时的回调函数。 + public void VerifyResources(int verifyResourceLengthPerFrame, VerifyResourcesCompleteCallback verifyResourcesCompleteCallback) + { + throw new NotSupportedException("VerifyResources"); + } + + /// + /// 使用可更新模式并检查资源。 + /// + /// 是否忽略处理其它变体的资源,若不忽略,将会移除其它变体的资源。 + /// 使用可更新模式并检查资源完成时的回调函数。 + public void CheckResources(bool ignoreOtherVariant, CheckResourcesCompleteCallback checkResourcesCompleteCallback) + { + throw new NotSupportedException("CheckResources"); + } + + /// + /// 使用可更新模式并应用资源包资源。 + /// + /// 要应用的资源包路径。 + /// 使用可更新模式并应用资源包资源完成时的回调函数。 + public void ApplyResources(string resourcePackPath, ApplyResourcesCompleteCallback applyResourcesCompleteCallback) + { + throw new NotSupportedException("ApplyResources"); + } + + /// + /// 使用可更新模式并更新所有资源。 + /// + /// 使用可更新模式并更新默认资源组完成时的回调函数。 + public void UpdateResources(UpdateResourcesCompleteCallback updateResourcesCompleteCallback) + { + throw new NotSupportedException("UpdateResources"); + } + + /// + /// 使用可更新模式并更新指定资源组的资源。 + /// + /// 要更新的资源组名称。 + /// 使用可更新模式并更新指定资源组完成时的回调函数。 + public void UpdateResources(string resourceGroupName, UpdateResourcesCompleteCallback updateResourcesCompleteCallback) + { + throw new NotSupportedException("UpdateResources"); + } + + /// + /// 停止更新资源。 + /// + public void StopUpdateResources() + { + throw new NotSupportedException("StopUpdateResources"); + } + + /// + /// 校验资源包。 + /// + /// 要校验的资源包路径。 + /// 是否校验资源包成功。 + public bool VerifyResourcePack(string resourcePackPath) + { + throw new NotSupportedException("VerifyResourcePack"); + } + + /// + /// 获取所有加载资源任务的信息。 + /// + /// 所有加载资源任务的信息。 + public TaskInfo[] GetAllLoadAssetInfos() + { + throw new NotSupportedException("GetAllLoadAssetInfos"); + } + + /// + /// 获取所有加载资源任务的信息。 + /// + /// 所有加载资源任务的信息。 + public void GetAllLoadAssetInfos(List results) + { + throw new NotSupportedException("GetAllLoadAssetInfos"); + } + + /// + /// 检查资源是否存在。 + /// + /// 要检查资源的名称。 + /// 检查资源是否存在的结果。 + public HasAssetResult HasAsset(string assetName) + { +#if UNITY_EDITOR + UnityEngine.Object obj = UnityEditor.AssetDatabase.LoadMainAssetAtPath(assetName); + if (obj == null) + { + return HasAssetResult.NotExist; + } + + HasAssetResult result = obj.GetType() == typeof(UnityEditor.DefaultAsset) ? HasAssetResult.BinaryOnDisk : HasAssetResult.AssetOnDisk; + obj = null; + UnityEditor.EditorUtility.UnloadUnusedAssetsImmediate(); + return result; +#else + return HasAssetResult.NotExist; +#endif + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源回调函数集。 + public void LoadAsset(string assetName, LoadAssetCallbacks loadAssetCallbacks) + { + LoadAsset(assetName, null, DefaultPriority, loadAssetCallbacks, null); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源回调函数集。 + public void LoadAsset(string assetName, Type assetType, LoadAssetCallbacks loadAssetCallbacks) + { + LoadAsset(assetName, assetType, DefaultPriority, loadAssetCallbacks, null); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + public void LoadAsset(string assetName, int priority, LoadAssetCallbacks loadAssetCallbacks) + { + LoadAsset(assetName, null, priority, loadAssetCallbacks, null); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + LoadAsset(assetName, null, DefaultPriority, loadAssetCallbacks, userData); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + public void LoadAsset(string assetName, Type assetType, int priority, LoadAssetCallbacks loadAssetCallbacks) + { + LoadAsset(assetName, assetType, priority, loadAssetCallbacks, null); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, Type assetType, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + LoadAsset(assetName, assetType, DefaultPriority, loadAssetCallbacks, userData); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, int priority, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + LoadAsset(assetName, null, priority, loadAssetCallbacks, userData); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, Type assetType, int priority, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + if (loadAssetCallbacks == null) + { + Log.Error("Load asset callbacks is invalid."); + return; + } + + if (string.IsNullOrEmpty(assetName)) + { + if (loadAssetCallbacks.LoadAssetFailureCallback != null) + { + loadAssetCallbacks.LoadAssetFailureCallback(assetName, LoadResourceStatus.NotExist, "Asset name is invalid.", userData); + } + + return; + } + + if (!assetName.StartsWith("Assets/", StringComparison.Ordinal)) + { + if (loadAssetCallbacks.LoadAssetFailureCallback != null) + { + loadAssetCallbacks.LoadAssetFailureCallback(assetName, LoadResourceStatus.NotExist, Utility.Text.Format("Asset name '{0}' is invalid.", assetName), userData); + } + + return; + } + + if (!HasFile(assetName)) + { + if (loadAssetCallbacks.LoadAssetFailureCallback != null) + { + loadAssetCallbacks.LoadAssetFailureCallback(assetName, LoadResourceStatus.NotExist, Utility.Text.Format("Asset '{0}' is not exist.", assetName), userData); + } + + return; + } + + m_LoadAssetInfos.AddLast(new LoadAssetInfo(assetName, assetType, priority, DateTime.UtcNow, m_MinLoadAssetRandomDelaySeconds + (float)Utility.Random.GetRandomDouble() * (m_MaxLoadAssetRandomDelaySeconds - m_MinLoadAssetRandomDelaySeconds), loadAssetCallbacks, userData)); + } + + /// + /// 卸载资源。 + /// + /// 要卸载的资源。 + public void UnloadAsset(object asset) + { + // Do nothing in editor resource mode. + } + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景回调函数集。 + public void LoadScene(string sceneAssetName, LoadSceneCallbacks loadSceneCallbacks) + { + LoadScene(sceneAssetName, DefaultPriority, loadSceneCallbacks, null); + } + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景资源的优先级。 + /// 加载场景回调函数集。 + public void LoadScene(string sceneAssetName, int priority, LoadSceneCallbacks loadSceneCallbacks) + { + LoadScene(sceneAssetName, priority, loadSceneCallbacks, null); + } + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景回调函数集。 + /// 用户自定义数据。 + public void LoadScene(string sceneAssetName, LoadSceneCallbacks loadSceneCallbacks, object userData) + { + LoadScene(sceneAssetName, DefaultPriority, loadSceneCallbacks, userData); + } + + /// + /// 异步加载场景。 + /// + /// 要加载场景资源的名称。 + /// 加载场景资源的优先级。 + /// 加载场景回调函数集。 + /// 用户自定义数据。 + public void LoadScene(string sceneAssetName, int priority, LoadSceneCallbacks loadSceneCallbacks, object userData) + { + if (loadSceneCallbacks == null) + { + Log.Error("Load scene callbacks is invalid."); + return; + } + + if (string.IsNullOrEmpty(sceneAssetName)) + { + if (loadSceneCallbacks.LoadSceneFailureCallback != null) + { + loadSceneCallbacks.LoadSceneFailureCallback(sceneAssetName, LoadResourceStatus.NotExist, "Scene asset name is invalid.", userData); + } + + return; + } + + if (!sceneAssetName.StartsWith("Assets/", StringComparison.Ordinal) || !sceneAssetName.EndsWith(".unity", StringComparison.Ordinal)) + { + if (loadSceneCallbacks.LoadSceneFailureCallback != null) + { + loadSceneCallbacks.LoadSceneFailureCallback(sceneAssetName, LoadResourceStatus.NotExist, Utility.Text.Format("Scene asset name '{0}' is invalid.", sceneAssetName), userData); + } + + return; + } + + if (!HasFile(sceneAssetName)) + { + if (loadSceneCallbacks.LoadSceneFailureCallback != null) + { + loadSceneCallbacks.LoadSceneFailureCallback(sceneAssetName, LoadResourceStatus.NotExist, Utility.Text.Format("Scene '{0}' is not exist.", sceneAssetName), userData); + } + + return; + } + +#if UNITY_5_5_OR_NEWER + AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(sceneAssetName, LoadSceneMode.Additive); +#else + AsyncOperation asyncOperation = SceneManager.LoadSceneAsync(SceneComponent.GetSceneName(sceneAssetName), LoadSceneMode.Additive); +#endif + if (asyncOperation == null) + { + return; + } + + m_LoadSceneInfos.AddLast(new LoadSceneInfo(asyncOperation, sceneAssetName, priority, DateTime.UtcNow, loadSceneCallbacks, userData)); + } + + /// + /// 异步卸载场景。 + /// + /// 要卸载场景资源的名称。 + /// 卸载场景回调函数集。 + public void UnloadScene(string sceneAssetName, UnloadSceneCallbacks unloadSceneCallbacks) + { + UnloadScene(sceneAssetName, unloadSceneCallbacks, null); + } + + /// + /// 异步卸载场景。 + /// + /// 要卸载场景资源的名称。 + /// 卸载场景回调函数集。 + /// 用户自定义数据。 + public void UnloadScene(string sceneAssetName, UnloadSceneCallbacks unloadSceneCallbacks, object userData) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + Log.Error("Scene asset name is invalid."); + return; + } + + if (!sceneAssetName.StartsWith("Assets/", StringComparison.Ordinal) || !sceneAssetName.EndsWith(".unity", StringComparison.Ordinal)) + { + Log.Error("Scene asset name '{0}' is invalid.", sceneAssetName); + return; + } + + if (unloadSceneCallbacks == null) + { + Log.Error("Unload scene callbacks is invalid."); + return; + } + + if (!HasFile(sceneAssetName)) + { + Log.Error("Scene '{0}' is not exist.", sceneAssetName); + return; + } + +#if UNITY_5_5_OR_NEWER + AsyncOperation asyncOperation = SceneManager.UnloadSceneAsync(sceneAssetName); + if (asyncOperation == null) + { + return; + } + + m_UnloadSceneInfos.AddLast(new UnloadSceneInfo(asyncOperation, sceneAssetName, unloadSceneCallbacks, userData)); +#else + if (SceneManager.UnloadScene(SceneComponent.GetSceneName(sceneAssetName))) + { + if (unloadSceneCallbacks.UnloadSceneSuccessCallback != null) + { + unloadSceneCallbacks.UnloadSceneSuccessCallback(sceneAssetName, userData); + } + } + else + { + if (unloadSceneCallbacks.UnloadSceneFailureCallback != null) + { + unloadSceneCallbacks.UnloadSceneFailureCallback(sceneAssetName, userData); + } + } +#endif + } + + /// + /// 获取二进制资源的实际路径。 + /// + /// 要获取实际路径的二进制资源的名称。 + /// 二进制资源的实际路径。 + /// 此方法仅适用于二进制资源存储在磁盘(而非文件系统)中的情况。若二进制资源存储在文件系统中时,返回值将始终为空。 + public string GetBinaryPath(string binaryAssetName) + { + if (!HasFile(binaryAssetName)) + { + return null; + } + + return Application.dataPath.Substring(0, Application.dataPath.Length - AssetsStringLength) + binaryAssetName; + } + + /// + /// 获取二进制资源的实际路径。 + /// + /// 要获取实际路径的二进制资源的名称。 + /// 二进制资源是否存储在只读区中。 + /// 二进制资源是否存储在文件系统中。 + /// 二进制资源或存储二进制资源的文件系统,相对于只读区或者读写区的相对路径。 + /// 若二进制资源存储在文件系统中,则指示二进制资源在文件系统中的名称,否则此参数返回空。 + /// 是否获取二进制资源的实际路径成功。 + public bool GetBinaryPath(string binaryAssetName, out bool storageInReadOnly, out bool storageInFileSystem, out string relativePath, out string fileName) + { + throw new NotSupportedException("GetBinaryPath"); + } + + /// + /// 获取二进制资源的长度。 + /// + /// 要获取长度的二进制资源的名称。 + /// 二进制资源的长度。 + public int GetBinaryLength(string binaryAssetName) + { + string binaryPath = GetBinaryPath(binaryAssetName); + if (string.IsNullOrEmpty(binaryPath)) + { + return -1; + } + + return (int)new System.IO.FileInfo(binaryPath).Length; + } + + /// + /// 异步加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 加载二进制资源回调函数集。 + public void LoadBinary(string binaryAssetName, LoadBinaryCallbacks loadBinaryCallbacks) + { + LoadBinary(binaryAssetName, loadBinaryCallbacks, null); + } + + /// + /// 异步加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 加载二进制资源回调函数集。 + /// 用户自定义数据。 + public void LoadBinary(string binaryAssetName, LoadBinaryCallbacks loadBinaryCallbacks, object userData) + { + if (loadBinaryCallbacks == null) + { + Log.Error("Load binary callbacks is invalid."); + return; + } + + if (string.IsNullOrEmpty(binaryAssetName)) + { + if (loadBinaryCallbacks.LoadBinaryFailureCallback != null) + { + loadBinaryCallbacks.LoadBinaryFailureCallback(binaryAssetName, LoadResourceStatus.NotExist, "Binary asset name is invalid.", userData); + } + + return; + } + + if (!binaryAssetName.StartsWith("Assets/", StringComparison.Ordinal)) + { + if (loadBinaryCallbacks.LoadBinaryFailureCallback != null) + { + loadBinaryCallbacks.LoadBinaryFailureCallback(binaryAssetName, LoadResourceStatus.NotExist, Utility.Text.Format("Binary asset name '{0}' is invalid.", binaryAssetName), userData); + } + + return; + } + + string binaryPath = GetBinaryPath(binaryAssetName); + if (binaryPath == null) + { + if (loadBinaryCallbacks.LoadBinaryFailureCallback != null) + { + loadBinaryCallbacks.LoadBinaryFailureCallback(binaryAssetName, LoadResourceStatus.NotExist, Utility.Text.Format("Binary asset '{0}' is not exist.", binaryAssetName), userData); + } + + return; + } + + try + { + byte[] binaryBytes = File.ReadAllBytes(binaryPath); + loadBinaryCallbacks.LoadBinarySuccessCallback(binaryAssetName, binaryBytes, 0f, userData); + } + catch (Exception exception) + { + if (loadBinaryCallbacks.LoadBinaryFailureCallback != null) + { + loadBinaryCallbacks.LoadBinaryFailureCallback(binaryAssetName, LoadResourceStatus.AssetError, exception.ToString(), userData); + } + } + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + public byte[] LoadBinaryFromFileSystem(string binaryAssetName) + { + throw new NotSupportedException("LoadBinaryFromFileSystem"); + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 实际加载了多少字节。 + public int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer) + { + throw new NotSupportedException("LoadBinaryFromFileSystem"); + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 存储加载二进制资源的二进制流的起始位置。 + /// 实际加载了多少字节。 + public int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex) + { + throw new NotSupportedException("LoadBinaryFromFileSystem"); + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 存储加载二进制资源的二进制流的起始位置。 + /// 存储加载二进制资源的二进制流的长度。 + /// 实际加载了多少字节。 + public int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex, int length) + { + throw new NotSupportedException("LoadBinaryFromFileSystem"); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的长度。 + /// 存储加载二进制资源片段内容的二进制流。 + public byte[] LoadBinarySegmentFromFileSystem(string binaryAssetName, int length) + { + throw new NotSupportedException("LoadBinarySegmentFromFileSystem"); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 要加载片段的长度。 + /// 存储加载二进制资源片段内容的二进制流。 + public byte[] LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, int length) + { + throw new NotSupportedException("LoadBinarySegmentFromFileSystem"); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, byte[] buffer) + { + throw new NotSupportedException("LoadBinarySegmentFromFileSystem"); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, byte[] buffer, int length) + { + throw new NotSupportedException("LoadBinarySegmentFromFileSystem"); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 存储加载二进制资源片段内容的二进制流的起始位置。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex, int length) + { + throw new NotSupportedException("LoadBinarySegmentFromFileSystem"); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer) + { + throw new NotSupportedException("LoadBinarySegmentFromFileSystem"); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer, int length) + { + throw new NotSupportedException("LoadBinarySegmentFromFileSystem"); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 存储加载二进制资源片段内容的二进制流的起始位置。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer, int startIndex, int length) + { + throw new NotSupportedException("LoadBinarySegmentFromFileSystem"); + } + + /// + /// 检查资源组是否存在。 + /// + /// 要检查资源组的名称。 + /// 资源组是否存在。 + public bool HasResourceGroup(string resourceGroupName) + { + throw new NotSupportedException("HasResourceGroup"); + } + + /// + /// 获取默认资源组。 + /// + /// 默认资源组。 + public IResourceGroup GetResourceGroup() + { + throw new NotSupportedException("GetResourceGroup"); + } + + /// + /// 获取资源组。 + /// + /// 要获取的资源组名称。 + /// 要获取的资源组。 + public IResourceGroup GetResourceGroup(string resourceGroupName) + { + throw new NotSupportedException("GetResourceGroup"); + } + + /// + /// 获取所有资源组。 + /// + /// 所有资源组。 + public IResourceGroup[] GetAllResourceGroups() + { + throw new NotSupportedException("GetAllResourceGroups"); + } + + /// + /// 获取所有资源组。 + /// + /// 所有资源组。 + public void GetAllResourceGroups(List results) + { + throw new NotSupportedException("GetAllResourceGroups"); + } + + /// + /// 获取资源组集合。 + /// + /// 要获取的资源组名称的集合。 + /// 要获取的资源组集合。 + public IResourceGroupCollection GetResourceGroupCollection(params string[] resourceGroupNames) + { + throw new NotSupportedException("GetResourceGroupCollection"); + } + + /// + /// 获取资源组集合。 + /// + /// 要获取的资源组名称的集合。 + /// 要获取的资源组集合。 + public IResourceGroupCollection GetResourceGroupCollection(List resourceGroupNames) + { + throw new NotSupportedException("GetResourceGroupCollection"); + } + + private bool HasFile(string assetName) + { + if (string.IsNullOrEmpty(assetName)) + { + return false; + } + + if (HasCachedAsset(assetName)) + { + return true; + } + + string assetFullName = Application.dataPath.Substring(0, Application.dataPath.Length - AssetsStringLength) + assetName; + if (string.IsNullOrEmpty(assetFullName)) + { + return false; + } + + string[] splitedAssetFullName = assetFullName.Split('/'); + string currentPath = Path.GetPathRoot(assetFullName); + for (int i = 1; i < splitedAssetFullName.Length - 1; i++) + { + string[] directoryNames = Directory.GetDirectories(currentPath, splitedAssetFullName[i]); + if (directoryNames.Length != 1) + { + return false; + } + + currentPath = directoryNames[0]; + } + + string[] fileNames = Directory.GetFiles(currentPath, splitedAssetFullName[splitedAssetFullName.Length - 1]); + if (fileNames.Length != 1) + { + return false; + } + + string fileFullName = Utility.Path.GetRegularPath(fileNames[0]); + if (fileFullName == null) + { + return false; + } + + if (assetFullName != fileFullName) + { + if (assetFullName.ToLowerInvariant() == fileFullName.ToLowerInvariant()) + { + Log.Warning("The real path of the specific asset '{0}' is '{1}'. Check the case of letters in the path.", assetName, "Assets" + fileFullName.Substring(Application.dataPath.Length)); + } + + return false; + } + + return true; + } + + private bool HasCachedAsset(string assetName) + { + if (!m_EnableCachedAssets) + { + return false; + } + + if (string.IsNullOrEmpty(assetName)) + { + return false; + } + + return m_CachedAssets.ContainsKey(assetName); + } + + private UnityEngine.Object GetCachedAsset(string assetName) + { + if (!m_EnableCachedAssets) + { + return null; + } + + if (string.IsNullOrEmpty(assetName)) + { + return null; + } + + UnityEngine.Object asset = null; + if (m_CachedAssets.TryGetValue(assetName, out asset)) + { + return asset; + } + + return null; + } + + [StructLayout(LayoutKind.Auto)] + private struct LoadAssetInfo + { + private readonly string m_AssetName; + private readonly Type m_AssetType; + private readonly int m_Priority; + private readonly DateTime m_StartTime; + private readonly float m_DelaySeconds; + private readonly LoadAssetCallbacks m_LoadAssetCallbacks; + private readonly object m_UserData; + + public LoadAssetInfo(string assetName, Type assetType, int priority, DateTime startTime, float delaySeconds, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + m_AssetName = assetName; + m_AssetType = assetType; + m_Priority = priority; + m_StartTime = startTime; + m_DelaySeconds = delaySeconds; + m_LoadAssetCallbacks = loadAssetCallbacks; + m_UserData = userData; + } + + public string AssetName + { + get + { + return m_AssetName; + } + } + + public Type AssetType + { + get + { + return m_AssetType; + } + } + + public int Priority + { + get + { + return m_Priority; + } + } + + public DateTime StartTime + { + get + { + return m_StartTime; + } + } + + public float DelaySeconds + { + get + { + return m_DelaySeconds; + } + } + + public LoadAssetCallbacks LoadAssetCallbacks + { + get + { + return m_LoadAssetCallbacks; + } + } + + public object UserData + { + get + { + return m_UserData; + } + } + } + + [StructLayout(LayoutKind.Auto)] + private struct LoadSceneInfo + { + private readonly AsyncOperation m_AsyncOperation; + private readonly string m_SceneAssetName; + private readonly int m_Priority; + private readonly DateTime m_StartTime; + private readonly LoadSceneCallbacks m_LoadSceneCallbacks; + private readonly object m_UserData; + + public LoadSceneInfo(AsyncOperation asyncOperation, string sceneAssetName, int priority, DateTime startTime, LoadSceneCallbacks loadSceneCallbacks, object userData) + { + m_AsyncOperation = asyncOperation; + m_SceneAssetName = sceneAssetName; + m_Priority = priority; + m_StartTime = startTime; + m_LoadSceneCallbacks = loadSceneCallbacks; + m_UserData = userData; + } + + public AsyncOperation AsyncOperation + { + get + { + return m_AsyncOperation; + } + } + + public string SceneAssetName + { + get + { + return m_SceneAssetName; + } + } + + public int Priority + { + get + { + return m_Priority; + } + } + + public DateTime StartTime + { + get + { + return m_StartTime; + } + } + + public LoadSceneCallbacks LoadSceneCallbacks + { + get + { + return m_LoadSceneCallbacks; + } + } + + public object UserData + { + get + { + return m_UserData; + } + } + } + + [StructLayout(LayoutKind.Auto)] + private struct UnloadSceneInfo + { + private readonly AsyncOperation m_AsyncOperation; + private readonly string m_SceneAssetName; + private readonly UnloadSceneCallbacks m_UnloadSceneCallbacks; + private readonly object m_UserData; + + public UnloadSceneInfo(AsyncOperation asyncOperation, string sceneAssetName, UnloadSceneCallbacks unloadSceneCallbacks, object userData) + { + m_AsyncOperation = asyncOperation; + m_SceneAssetName = sceneAssetName; + m_UnloadSceneCallbacks = unloadSceneCallbacks; + m_UserData = userData; + } + + public AsyncOperation AsyncOperation + { + get + { + return m_AsyncOperation; + } + } + + public string SceneAssetName + { + get + { + return m_SceneAssetName; + } + } + + public UnloadSceneCallbacks UnloadSceneCallbacks + { + get + { + return m_UnloadSceneCallbacks; + } + } + + public object UserData + { + get + { + return m_UserData; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/EditorResourceComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/EditorResourceComponent.cs.meta new file mode 100644 index 0000000..9d5df4b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/EditorResourceComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c26ec20b78ec32048bfb6c0ff875d8cd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/LoadResourceAgentHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/LoadResourceAgentHelperBase.cs new file mode 100644 index 0000000..2a7d788 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/LoadResourceAgentHelperBase.cs @@ -0,0 +1,96 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.FileSystem; +using GameFramework.Resource; +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载资源代理辅助器基类。 + /// + public abstract class LoadResourceAgentHelperBase : MonoBehaviour, ILoadResourceAgentHelper + { + /// + /// 加载资源代理辅助器异步加载资源更新事件。 + /// + public abstract event EventHandler LoadResourceAgentHelperUpdate; + + /// + /// 加载资源代理辅助器异步读取资源文件完成事件。 + /// + public abstract event EventHandler LoadResourceAgentHelperReadFileComplete; + + /// + /// 加载资源代理辅助器异步读取资源二进制流完成事件。 + /// + public abstract event EventHandler LoadResourceAgentHelperReadBytesComplete; + + /// + /// 加载资源代理辅助器异步将资源二进制流转换为加载对象完成事件。 + /// + public abstract event EventHandler LoadResourceAgentHelperParseBytesComplete; + + /// + /// 加载资源代理辅助器异步加载资源完成事件。 + /// + public abstract event EventHandler LoadResourceAgentHelperLoadComplete; + + /// + /// 加载资源代理辅助器错误事件。 + /// + public abstract event EventHandler LoadResourceAgentHelperError; + + /// + /// 通过加载资源代理辅助器开始异步读取资源文件。 + /// + /// 要加载资源的完整路径名。 + public abstract void ReadFile(string fullPath); + + /// + /// 通过加载资源代理辅助器开始异步读取资源文件。 + /// + /// 要加载资源的文件系统。 + /// 要加载资源的名称。 + public abstract void ReadFile(IFileSystem fileSystem, string name); + + /// + /// 通过加载资源代理辅助器开始异步读取资源二进制流。 + /// + /// 要加载资源的完整路径名。 + public abstract void ReadBytes(string fullPath); + + /// + /// 通过加载资源代理辅助器开始异步读取资源二进制流。 + /// + /// 要加载资源的文件系统。 + /// 要加载资源的名称。 + public abstract void ReadBytes(IFileSystem fileSystem, string name); + + /// + /// 通过加载资源代理辅助器开始异步将资源二进制流转换为加载对象。 + /// + /// 要加载资源的二进制流。 + public abstract void ParseBytes(byte[] bytes); + + /// + /// 通过加载资源代理辅助器开始异步加载资源。 + /// + /// 资源。 + /// 要加载的资源名称。 + /// 要加载资源的类型。 + /// 要加载的资源是否是场景。 + public abstract void LoadAsset(object resource, string assetName, Type assetType, bool isScene); + + /// + /// 重置加载资源代理辅助器。 + /// + public abstract void Reset(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/LoadResourceAgentHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/LoadResourceAgentHelperBase.cs.meta new file mode 100644 index 0000000..8a8bfa0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/LoadResourceAgentHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 753d0ffbb600b8a4888c18a954ca0985 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ReadWritePathType.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ReadWritePathType.cs new file mode 100644 index 0000000..5f41bf4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ReadWritePathType.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Runtime +{ + /// + /// 读写区路径类型。 + /// + public enum ReadWritePathType : byte + { + /// + /// 未指定。 + /// + Unspecified = 0, + + /// + /// 临时缓存。 + /// + TemporaryCache, + + /// + /// 持久化数据。 + /// + PersistentData, + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ReadWritePathType.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ReadWritePathType.cs.meta new file mode 100644 index 0000000..d88efcd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ReadWritePathType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 59125eb0ef72f9a4cbe2fd08f0876ed7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplyFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplyFailureEventArgs.cs new file mode 100644 index 0000000..1052e48 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplyFailureEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源应用失败事件。 + /// + public sealed class ResourceApplyFailureEventArgs : GameEventArgs + { + /// + /// 资源应用失败事件编号。 + /// + public static readonly int EventId = typeof(ResourceApplyFailureEventArgs).GetHashCode(); + + /// + /// 初始化资源应用失败事件的新实例。 + /// + public ResourceApplyFailureEventArgs() + { + Name = null; + ResourcePackPath = null; + ErrorMessage = null; + } + + /// + /// 获取资源应用失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取资源包路径。 + /// + public string ResourcePackPath + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 创建资源应用失败事件。 + /// + /// 内部事件。 + /// 创建的资源应用失败事件。 + public static ResourceApplyFailureEventArgs Create(GameFramework.Resource.ResourceApplyFailureEventArgs e) + { + ResourceApplyFailureEventArgs resourceApplyFailureEventArgs = ReferencePool.Acquire(); + resourceApplyFailureEventArgs.Name = e.Name; + resourceApplyFailureEventArgs.ResourcePackPath = e.ResourcePackPath; + resourceApplyFailureEventArgs.ErrorMessage = e.ErrorMessage; + return resourceApplyFailureEventArgs; + } + + /// + /// 清理资源应用失败事件。 + /// + public override void Clear() + { + Name = null; + ResourcePackPath = null; + ErrorMessage = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplyFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplyFailureEventArgs.cs.meta new file mode 100644 index 0000000..d51598d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplyFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 66fd3ef74ebb3c64a85b92714b6fca9f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplyStartEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplyStartEventArgs.cs new file mode 100644 index 0000000..3d8775b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplyStartEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源应用开始事件。 + /// + public sealed class ResourceApplyStartEventArgs : GameEventArgs + { + /// + /// 资源应用开始事件编号。 + /// + public static readonly int EventId = typeof(ResourceApplyStartEventArgs).GetHashCode(); + + /// + /// 初始化资源应用开始事件的新实例。 + /// + public ResourceApplyStartEventArgs() + { + ResourcePackPath = null; + Count = 0; + TotalLength = 0L; + } + + /// + /// 获取资源应用开始事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取资源包路径。 + /// + public string ResourcePackPath + { + get; + private set; + } + + /// + /// 获取要应用资源的数量。 + /// + public int Count + { + get; + private set; + } + + /// + /// 获取要应用资源的总大小。 + /// + public long TotalLength + { + get; + private set; + } + + /// + /// 创建资源应用开始事件。 + /// + /// 内部事件。 + /// 创建的资源应用开始事件。 + public static ResourceApplyStartEventArgs Create(GameFramework.Resource.ResourceApplyStartEventArgs e) + { + ResourceApplyStartEventArgs resourceApplyStartEventArgs = ReferencePool.Acquire(); + resourceApplyStartEventArgs.ResourcePackPath = e.ResourcePackPath; + resourceApplyStartEventArgs.Count = e.Count; + resourceApplyStartEventArgs.TotalLength = e.TotalLength; + return resourceApplyStartEventArgs; + } + + /// + /// 清理资源应用开始事件。 + /// + public override void Clear() + { + ResourcePackPath = null; + Count = 0; + TotalLength = 0L; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplyStartEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplyStartEventArgs.cs.meta new file mode 100644 index 0000000..3dad449 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplyStartEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a2b8dac8903914b4b90a288cb8ad3d06 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplySuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplySuccessEventArgs.cs new file mode 100644 index 0000000..858d046 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplySuccessEventArgs.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源应用成功事件。 + /// + public sealed class ResourceApplySuccessEventArgs : GameEventArgs + { + /// + /// 资源应用成功事件编号。 + /// + public static readonly int EventId = typeof(ResourceApplySuccessEventArgs).GetHashCode(); + + /// + /// 初始化资源应用成功事件的新实例。 + /// + public ResourceApplySuccessEventArgs() + { + Name = null; + ApplyPath = null; + ResourcePackPath = null; + Length = 0; + CompressedLength = 0; + } + + /// + /// 获取资源应用成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取资源应用后存放路径。 + /// + public string ApplyPath + { + get; + private set; + } + + /// + /// 获取资源包路径。 + /// + public string ResourcePackPath + { + get; + private set; + } + + /// + /// 获取资源大小。 + /// + public int Length + { + get; + private set; + } + + /// + /// 获取压缩后大小。 + /// + public int CompressedLength + { + get; + private set; + } + + /// + /// 创建资源应用成功事件。 + /// + /// 内部事件。 + /// 创建的资源应用成功事件。 + public static ResourceApplySuccessEventArgs Create(GameFramework.Resource.ResourceApplySuccessEventArgs e) + { + ResourceApplySuccessEventArgs resourceApplySuccessEventArgs = ReferencePool.Acquire(); + resourceApplySuccessEventArgs.Name = e.Name; + resourceApplySuccessEventArgs.ApplyPath = e.ApplyPath; + resourceApplySuccessEventArgs.ResourcePackPath = e.ResourcePackPath; + resourceApplySuccessEventArgs.Length = e.Length; + resourceApplySuccessEventArgs.CompressedLength = e.CompressedLength; + return resourceApplySuccessEventArgs; + } + + /// + /// 清理资源应用成功事件。 + /// + public override void Clear() + { + Name = null; + ApplyPath = null; + ResourcePackPath = null; + Length = 0; + CompressedLength = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplySuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplySuccessEventArgs.cs.meta new file mode 100644 index 0000000..a4286d0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceApplySuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b5a9d46578a27a441a20e8578c940b42 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceComponent.cs new file mode 100644 index 0000000..ae3612d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceComponent.cs @@ -0,0 +1,1525 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Download; +using GameFramework.FileSystem; +using GameFramework.ObjectPool; +using GameFramework.Resource; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Resource")] + public sealed class ResourceComponent : GameFrameworkComponent + { + private const int DefaultPriority = 0; + private const int OneMegaBytes = 1024 * 1024; + + private IResourceManager m_ResourceManager = null; + private EventComponent m_EventComponent = null; + private bool m_EditorResourceMode = false; + private bool m_ForceUnloadUnusedAssets = false; + private bool m_PreorderUnloadUnusedAssets = false; + private bool m_PerformGCCollect = false; + private AsyncOperation m_AsyncOperation = null; + private float m_LastUnloadUnusedAssetsOperationElapseSeconds = 0f; + private ResourceHelperBase m_ResourceHelper = null; + + [SerializeField] + private ResourceMode m_ResourceMode = ResourceMode.Package; + + [SerializeField] + private ReadWritePathType m_ReadWritePathType = ReadWritePathType.Unspecified; + + [SerializeField] + private float m_MinUnloadUnusedAssetsInterval = 60f; + + [SerializeField] + private float m_MaxUnloadUnusedAssetsInterval = 300f; + + [SerializeField] + private float m_AssetAutoReleaseInterval = 60f; + + [SerializeField] + private int m_AssetCapacity = 64; + + [SerializeField] + private float m_AssetExpireTime = 60f; + + [SerializeField] + private int m_AssetPriority = 0; + + [SerializeField] + private float m_ResourceAutoReleaseInterval = 60f; + + [SerializeField] + private int m_ResourceCapacity = 16; + + [SerializeField] + private float m_ResourceExpireTime = 60f; + + [SerializeField] + private int m_ResourcePriority = 0; + + [SerializeField] + private string m_UpdatePrefixUri = null; + + [SerializeField] + private int m_GenerateReadWriteVersionListLength = OneMegaBytes; + + [SerializeField] + private int m_UpdateRetryCount = 3; + + [SerializeField] + private Transform m_InstanceRoot = null; + + [SerializeField] + private string m_ResourceHelperTypeName = "UnityGameFramework.Runtime.DefaultResourceHelper"; + + [SerializeField] + private ResourceHelperBase m_CustomResourceHelper = null; + + [SerializeField] + private string m_LoadResourceAgentHelperTypeName = "UnityGameFramework.Runtime.DefaultLoadResourceAgentHelper"; + + [SerializeField] + private LoadResourceAgentHelperBase m_CustomLoadResourceAgentHelper = null; + + [SerializeField] + private int m_LoadResourceAgentHelperCount = 3; + + /// + /// 获取资源只读路径。 + /// + public string ReadOnlyPath + { + get + { + return m_ResourceManager.ReadOnlyPath; + } + } + + /// + /// 获取资源读写路径。 + /// + public string ReadWritePath + { + get + { + return m_ResourceManager.ReadWritePath; + } + } + + /// + /// 获取资源模式。 + /// + public ResourceMode ResourceMode + { + get + { + return m_ResourceManager.ResourceMode; + } + } + + /// + /// 获取资源读写路径类型。 + /// + public ReadWritePathType ReadWritePathType + { + get + { + return m_ReadWritePathType; + } + } + + /// + /// 设置当前变体。 + /// + public string CurrentVariant + { + get + { + return m_ResourceManager.CurrentVariant; + } + } + + /// + /// 获取单机模式版本资源列表序列化器。 + /// + public PackageVersionListSerializer PackageVersionListSerializer + { + get + { + return m_ResourceManager.PackageVersionListSerializer; + } + } + + /// + /// 获取可更新模式版本资源列表序列化器。 + /// + public UpdatableVersionListSerializer UpdatableVersionListSerializer + { + get + { + return m_ResourceManager.UpdatableVersionListSerializer; + } + } + + /// + /// 获取本地只读区版本资源列表序列化器。 + /// + public ReadOnlyVersionListSerializer ReadOnlyVersionListSerializer + { + get + { + return m_ResourceManager.ReadOnlyVersionListSerializer; + } + } + + /// + /// 获取本地读写区版本资源列表序列化器。 + /// + public ReadWriteVersionListSerializer ReadWriteVersionListSerializer + { + get + { + return m_ResourceManager.ReadWriteVersionListSerializer; + } + } + + /// + /// 获取资源包版本资源列表序列化器。 + /// + public ResourcePackVersionListSerializer ResourcePackVersionListSerializer + { + get + { + return m_ResourceManager.ResourcePackVersionListSerializer; + } + } + + /// + /// 获取无用资源释放的等待时长,以秒为单位。 + /// + public float LastUnloadUnusedAssetsOperationElapseSeconds + { + get + { + return m_LastUnloadUnusedAssetsOperationElapseSeconds; + } + } + + /// + /// 获取或设置无用资源释放的最小间隔时间,以秒为单位。 + /// + public float MinUnloadUnusedAssetsInterval + { + get + { + return m_MinUnloadUnusedAssetsInterval; + } + set + { + m_MinUnloadUnusedAssetsInterval = value; + } + } + + /// + /// 获取或设置无用资源释放的最大间隔时间,以秒为单位。 + /// + public float MaxUnloadUnusedAssetsInterval + { + get + { + return m_MaxUnloadUnusedAssetsInterval; + } + set + { + m_MaxUnloadUnusedAssetsInterval = value; + } + } + + /// + /// 获取当前资源适用的游戏版本号。 + /// + public string ApplicableGameVersion + { + get + { + return m_ResourceManager.ApplicableGameVersion; + } + } + + /// + /// 获取当前内部资源版本号。 + /// + public int InternalResourceVersion + { + get + { + return m_ResourceManager.InternalResourceVersion; + } + } + + /// + /// 获取资源数量。 + /// + public int AssetCount + { + get + { + return m_ResourceManager.AssetCount; + } + } + + /// + /// 获取资源数量。 + /// + public int ResourceCount + { + get + { + return m_ResourceManager.ResourceCount; + } + } + + /// + /// 获取资源组数量。 + /// + public int ResourceGroupCount + { + get + { + return m_ResourceManager.ResourceGroupCount; + } + } + + /// + /// 获取或设置资源更新下载地址。 + /// + public string UpdatePrefixUri + { + get + { + return m_ResourceManager.UpdatePrefixUri; + } + set + { + m_ResourceManager.UpdatePrefixUri = m_UpdatePrefixUri = value; + } + } + + public string HotUpdateScripts; + public string OtherHotUpdateScripts; + + /// + /// 获取或设置每更新多少字节的资源,重新生成一次版本资源列表。 + /// + public int GenerateReadWriteVersionListLength + { + get + { + return m_ResourceManager.GenerateReadWriteVersionListLength; + } + set + { + m_ResourceManager.GenerateReadWriteVersionListLength = m_GenerateReadWriteVersionListLength = value; + } + } + + /// + /// 获取正在应用的资源包路径。 + /// + public string ApplyingResourcePackPath + { + get + { + return m_ResourceManager.ApplyingResourcePackPath; + } + } + + /// + /// 获取等待应用资源数量。 + /// + public int ApplyWaitingCount + { + get + { + return m_ResourceManager.ApplyWaitingCount; + } + } + + /// + /// 获取或设置资源更新重试次数。 + /// + public int UpdateRetryCount + { + get + { + return m_ResourceManager.UpdateRetryCount; + } + set + { + m_ResourceManager.UpdateRetryCount = m_UpdateRetryCount = value; + } + } + + /// + /// 获取正在更新的资源组。 + /// + public IResourceGroup UpdatingResourceGroup + { + get + { + return m_ResourceManager.UpdatingResourceGroup; + } + } + + /// + /// 获取等待更新资源数量。 + /// + public int UpdateWaitingCount + { + get + { + return m_ResourceManager.UpdateWaitingCount; + } + } + + /// + /// 获取使用时下载的等待更新资源数量。 + /// + public int UpdateWaitingWhilePlayingCount + { + get + { + return m_ResourceManager.UpdateWaitingWhilePlayingCount; + } + } + + /// + /// 获取候选更新资源数量。 + /// + public int UpdateCandidateCount + { + get + { + return m_ResourceManager.UpdateCandidateCount; + } + } + + /// + /// 获取加载资源代理总数量。 + /// + public int LoadTotalAgentCount + { + get + { + return m_ResourceManager.LoadTotalAgentCount; + } + } + + /// + /// 获取可用加载资源代理数量。 + /// + public int LoadFreeAgentCount + { + get + { + return m_ResourceManager.LoadFreeAgentCount; + } + } + + /// + /// 获取工作中加载资源代理数量。 + /// + public int LoadWorkingAgentCount + { + get + { + return m_ResourceManager.LoadWorkingAgentCount; + } + } + + /// + /// 获取等待加载资源任务数量。 + /// + public int LoadWaitingTaskCount + { + get + { + return m_ResourceManager.LoadWaitingTaskCount; + } + } + + /// + /// 获取或设置资源对象池自动释放可释放对象的间隔秒数。 + /// + public float AssetAutoReleaseInterval + { + get + { + return m_ResourceManager.AssetAutoReleaseInterval; + } + set + { + m_ResourceManager.AssetAutoReleaseInterval = m_AssetAutoReleaseInterval = value; + } + } + + /// + /// 获取或设置资源对象池的容量。 + /// + public int AssetCapacity + { + get + { + return m_ResourceManager.AssetCapacity; + } + set + { + m_ResourceManager.AssetCapacity = m_AssetCapacity = value; + } + } + + /// + /// 获取或设置资源对象池对象过期秒数。 + /// + public float AssetExpireTime + { + get + { + return m_ResourceManager.AssetExpireTime; + } + set + { + m_ResourceManager.AssetExpireTime = m_AssetExpireTime = value; + } + } + + /// + /// 获取或设置资源对象池的优先级。 + /// + public int AssetPriority + { + get + { + return m_ResourceManager.AssetPriority; + } + set + { + m_ResourceManager.AssetPriority = m_AssetPriority = value; + } + } + + /// + /// 获取或设置资源对象池自动释放可释放对象的间隔秒数。 + /// + public float ResourceAutoReleaseInterval + { + get + { + return m_ResourceManager.ResourceAutoReleaseInterval; + } + set + { + m_ResourceManager.ResourceAutoReleaseInterval = m_ResourceAutoReleaseInterval = value; + } + } + + /// + /// 获取或设置资源对象池的容量。 + /// + public int ResourceCapacity + { + get + { + return m_ResourceManager.ResourceCapacity; + } + set + { + m_ResourceManager.ResourceCapacity = m_ResourceCapacity = value; + } + } + + /// + /// 获取或设置资源对象池对象过期秒数。 + /// + public float ResourceExpireTime + { + get + { + return m_ResourceManager.ResourceExpireTime; + } + set + { + m_ResourceManager.ResourceExpireTime = m_ResourceExpireTime = value; + } + } + + /// + /// 获取或设置资源对象池的优先级。 + /// + public int ResourcePriority + { + get + { + return m_ResourceManager.ResourcePriority; + } + set + { + m_ResourceManager.ResourcePriority = m_ResourcePriority = value; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + } + + private void Start() + { + BaseComponent baseComponent = GameEntry.GetComponent(); + if (baseComponent == null) + { + Log.Fatal("Base component is invalid."); + return; + } + + m_EventComponent = GameEntry.GetComponent(); + if (m_EventComponent == null) + { + Log.Fatal("Event component is invalid."); + return; + } + + m_EditorResourceMode = baseComponent.EditorResourceMode; + m_ResourceManager = m_EditorResourceMode ? baseComponent.EditorResourceHelper : GameFrameworkEntry.GetModule(); + if (m_ResourceManager == null) + { + Log.Fatal("Resource manager is invalid."); + return; + } + + m_ResourceManager.ResourceVerifyStart += OnResourceVerifyStart; + m_ResourceManager.ResourceVerifySuccess += OnResourceVerifySuccess; + m_ResourceManager.ResourceVerifyFailure += OnResourceVerifyFailure; + m_ResourceManager.ResourceApplyStart += OnResourceApplyStart; + m_ResourceManager.ResourceApplySuccess += OnResourceApplySuccess; + m_ResourceManager.ResourceApplyFailure += OnResourceApplyFailure; + m_ResourceManager.ResourceUpdateStart += OnResourceUpdateStart; + m_ResourceManager.ResourceUpdateChanged += OnResourceUpdateChanged; + m_ResourceManager.ResourceUpdateSuccess += OnResourceUpdateSuccess; + m_ResourceManager.ResourceUpdateFailure += OnResourceUpdateFailure; + m_ResourceManager.ResourceUpdateAllComplete += OnResourceUpdateAllComplete; + + if (Application.platform == RuntimePlatform.Android) + { + //Application.streamingAssetsPath安卓下路径为"jar:file://" + Application.dataPath + "!/assets" + //分包后是 + string appDataPath = Application.dataPath; + var tmp = System.IO.Path.GetDirectoryName(appDataPath); + tmp = tmp + "/split_base_assets.apk" + "!/assets"; + if (System.IO.File.Exists(tmp)) + { + appDataPath = "jar:file://" + tmp; + m_ResourceManager.SetReadOnlyPath(appDataPath); + } + else + { + m_ResourceManager.SetReadOnlyPath(Application.streamingAssetsPath); + } + } + else + { + m_ResourceManager.SetReadOnlyPath(Application.streamingAssetsPath); + } + + if (m_ReadWritePathType == ReadWritePathType.TemporaryCache) + { + m_ResourceManager.SetReadWritePath(Application.temporaryCachePath); + } + else + { + if (m_ReadWritePathType == ReadWritePathType.Unspecified) + { + m_ReadWritePathType = ReadWritePathType.PersistentData; + } + + m_ResourceManager.SetReadWritePath(Application.persistentDataPath); + } + + if (m_EditorResourceMode) + { + return; + } + + SetResourceMode(m_ResourceMode); + m_ResourceManager.SetObjectPoolManager(GameFrameworkEntry.GetModule()); + m_ResourceManager.SetFileSystemManager(GameFrameworkEntry.GetModule()); + m_ResourceManager.SetDownloadManager(GameFrameworkEntry.GetModule()); + m_ResourceManager.AssetAutoReleaseInterval = m_AssetAutoReleaseInterval; + m_ResourceManager.AssetCapacity = m_AssetCapacity; + m_ResourceManager.AssetExpireTime = m_AssetExpireTime; + m_ResourceManager.AssetPriority = m_AssetPriority; + m_ResourceManager.ResourceAutoReleaseInterval = m_ResourceAutoReleaseInterval; + m_ResourceManager.ResourceCapacity = m_ResourceCapacity; + m_ResourceManager.ResourceExpireTime = m_ResourceExpireTime; + m_ResourceManager.ResourcePriority = m_ResourcePriority; + if (m_ResourceMode == ResourceMode.Updatable || m_ResourceMode == ResourceMode.UpdatableWhilePlaying) + { + m_ResourceManager.UpdatePrefixUri = m_UpdatePrefixUri; + m_ResourceManager.GenerateReadWriteVersionListLength = m_GenerateReadWriteVersionListLength; + m_ResourceManager.UpdateRetryCount = m_UpdateRetryCount; + } + + m_ResourceHelper = Helper.CreateHelper(m_ResourceHelperTypeName, m_CustomResourceHelper); + if (m_ResourceHelper == null) + { + Log.Error("Can not create resource helper."); + return; + } + + m_ResourceHelper.name = "Resource Helper"; + Transform transform = m_ResourceHelper.transform; + transform.SetParent(this.transform); + transform.localScale = Vector3.one; + + m_ResourceManager.SetResourceHelper(m_ResourceHelper); + + if (m_InstanceRoot == null) + { + m_InstanceRoot = new GameObject("Load Resource Agent Instances").transform; + m_InstanceRoot.SetParent(gameObject.transform); + m_InstanceRoot.localScale = Vector3.one; + } + + for (int i = 0; i < m_LoadResourceAgentHelperCount; i++) + { + AddLoadResourceAgentHelper(i); + } + } + + private void Update() + { + m_LastUnloadUnusedAssetsOperationElapseSeconds += Time.unscaledDeltaTime; + if (m_AsyncOperation == null && (m_ForceUnloadUnusedAssets || m_LastUnloadUnusedAssetsOperationElapseSeconds >= m_MaxUnloadUnusedAssetsInterval || m_PreorderUnloadUnusedAssets && m_LastUnloadUnusedAssetsOperationElapseSeconds >= m_MinUnloadUnusedAssetsInterval)) + { + Log.Info("Unload unused assets..."); + m_ForceUnloadUnusedAssets = false; + m_PreorderUnloadUnusedAssets = false; + m_LastUnloadUnusedAssetsOperationElapseSeconds = 0f; + m_AsyncOperation = Resources.UnloadUnusedAssets(); + } + + if (m_AsyncOperation != null && m_AsyncOperation.isDone) + { + m_AsyncOperation = null; + if (m_PerformGCCollect) + { + Log.Info("GC.Collect..."); + m_PerformGCCollect = false; + GC.Collect(); + } + } + } + + /// + /// 设置资源模式。 + /// + /// 资源模式。 + public void SetResourceMode(ResourceMode resourceMode) + { + m_ResourceManager.SetResourceMode(resourceMode); + switch (resourceMode) + { + case ResourceMode.Package: + m_ResourceManager.PackageVersionListSerializer.RegisterDeserializeCallback(0, BuiltinVersionListSerializer.PackageVersionListDeserializeCallback_V0); + m_ResourceManager.PackageVersionListSerializer.RegisterDeserializeCallback(1, BuiltinVersionListSerializer.PackageVersionListDeserializeCallback_V1); + m_ResourceManager.PackageVersionListSerializer.RegisterDeserializeCallback(2, BuiltinVersionListSerializer.PackageVersionListDeserializeCallback_V2); + break; + + case ResourceMode.Updatable: + case ResourceMode.UpdatableWhilePlaying: + m_ResourceManager.UpdatableVersionListSerializer.RegisterDeserializeCallback(0, BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback_V0); + m_ResourceManager.UpdatableVersionListSerializer.RegisterDeserializeCallback(1, BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback_V1); + m_ResourceManager.UpdatableVersionListSerializer.RegisterDeserializeCallback(2, BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback_V2); + + m_ResourceManager.UpdatableVersionListSerializer.RegisterTryGetValueCallback(0, BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback_V0); + m_ResourceManager.UpdatableVersionListSerializer.RegisterTryGetValueCallback(1, BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback_V1_V2); + m_ResourceManager.UpdatableVersionListSerializer.RegisterTryGetValueCallback(2, BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback_V1_V2); + + m_ResourceManager.ReadOnlyVersionListSerializer.RegisterDeserializeCallback(0, BuiltinVersionListSerializer.LocalVersionListDeserializeCallback_V0); + m_ResourceManager.ReadOnlyVersionListSerializer.RegisterDeserializeCallback(1, BuiltinVersionListSerializer.LocalVersionListDeserializeCallback_V1); + m_ResourceManager.ReadOnlyVersionListSerializer.RegisterDeserializeCallback(2, BuiltinVersionListSerializer.LocalVersionListDeserializeCallback_V2); + + m_ResourceManager.ReadWriteVersionListSerializer.RegisterSerializeCallback(0, BuiltinVersionListSerializer.LocalVersionListSerializeCallback_V0); + m_ResourceManager.ReadWriteVersionListSerializer.RegisterSerializeCallback(1, BuiltinVersionListSerializer.LocalVersionListSerializeCallback_V1); + m_ResourceManager.ReadWriteVersionListSerializer.RegisterSerializeCallback(2, BuiltinVersionListSerializer.LocalVersionListSerializeCallback_V2); + + m_ResourceManager.ReadWriteVersionListSerializer.RegisterDeserializeCallback(0, BuiltinVersionListSerializer.LocalVersionListDeserializeCallback_V0); + m_ResourceManager.ReadWriteVersionListSerializer.RegisterDeserializeCallback(1, BuiltinVersionListSerializer.LocalVersionListDeserializeCallback_V1); + m_ResourceManager.ReadWriteVersionListSerializer.RegisterDeserializeCallback(2, BuiltinVersionListSerializer.LocalVersionListDeserializeCallback_V2); + + m_ResourceManager.ResourcePackVersionListSerializer.RegisterDeserializeCallback(0, BuiltinVersionListSerializer.ResourcePackVersionListDeserializeCallback_V0); + break; + } + } + + /// + /// 设置当前变体。 + /// + /// 当前变体。 + public void SetCurrentVariant(string currentVariant) + { + m_ResourceManager.SetCurrentVariant(!string.IsNullOrEmpty(currentVariant) ? currentVariant : null); + } + + /// + /// 设置解密资源回调函数。 + /// + /// 要设置的解密资源回调函数。 + /// 如果不设置,将使用默认的解密资源回调函数。 + public void SetDecryptResourceCallback(DecryptResourceCallback decryptResourceCallback) + { + m_ResourceManager.SetDecryptResourceCallback(decryptResourceCallback); + } + + /// + /// 预订执行释放未被使用的资源。 + /// + /// 是否使用垃圾回收。 + public void UnloadUnusedAssets(bool performGCCollect) + { + m_PreorderUnloadUnusedAssets = true; + if (performGCCollect) + { + m_PerformGCCollect = performGCCollect; + } + } + + /// + /// 强制执行释放未被使用的资源。 + /// + /// 是否使用垃圾回收。 + public void ForceUnloadUnusedAssets(bool performGCCollect) + { + m_ForceUnloadUnusedAssets = true; + if (performGCCollect) + { + m_PerformGCCollect = performGCCollect; + } + } + + /// + /// 使用单机模式并初始化资源。 + /// + /// 使用单机模式并初始化资源完成时的回调函数。 + public void InitResources(InitResourcesCompleteCallback initResourcesCompleteCallback) + { + m_ResourceManager.InitResources(initResourcesCompleteCallback); + } + + /// + /// 使用可更新模式并检查版本资源列表。 + /// + /// 最新的内部资源版本号。 + /// 检查版本资源列表结果。 + public CheckVersionListResult CheckVersionList(int latestInternalResourceVersion) + { + return m_ResourceManager.CheckVersionList(latestInternalResourceVersion); + } + + /// + /// 使用可更新模式并更新版本资源列表。 + /// + /// 版本资源列表大小。 + /// 版本资源列表哈希值。 + /// 版本资源列表压缩后大小。 + /// 版本资源列表压缩后哈希值。 + /// 版本资源列表更新回调函数集。 + public void UpdateVersionList(int versionListLength, int versionListHashCode, int versionListCompressedLength, int versionListCompressedHashCode, UpdateVersionListCallbacks updateVersionListCallbacks) + { + m_ResourceManager.UpdateVersionList(versionListLength, versionListHashCode, versionListCompressedLength, versionListCompressedHashCode, updateVersionListCallbacks); + } + + /// + /// 使用可更新模式并校验资源。 + /// + /// 使用可更新模式并校验资源完成时的回调函数。 + public void VerifyResources(VerifyResourcesCompleteCallback verifyResourcesCompleteCallback) + { + m_ResourceManager.VerifyResources(0, verifyResourcesCompleteCallback); + } + + /// + /// 使用可更新模式并校验资源。 + /// + /// 每帧至少校验资源的大小,以字节为单位。 + /// 使用可更新模式并校验资源完成时的回调函数。 + public void VerifyResources(int verifyResourceLengthPerFrame, VerifyResourcesCompleteCallback verifyResourcesCompleteCallback) + { + m_ResourceManager.VerifyResources(verifyResourceLengthPerFrame, verifyResourcesCompleteCallback); + } + + /// + /// 使用可更新模式并检查资源。 + /// + /// 使用可更新模式并检查资源完成时的回调函数。 + public void CheckResources(CheckResourcesCompleteCallback checkResourcesCompleteCallback) + { + m_ResourceManager.CheckResources(false, checkResourcesCompleteCallback); + } + + /// + /// 使用可更新模式并检查资源。 + /// + /// 是否忽略处理其它变体的资源,若不忽略,将会移除其它变体的资源。 + /// 使用可更新模式并检查资源完成时的回调函数。 + public void CheckResources(bool ignoreOtherVariant, CheckResourcesCompleteCallback checkResourcesCompleteCallback) + { + m_ResourceManager.CheckResources(ignoreOtherVariant, checkResourcesCompleteCallback); + } + + /// + /// 使用可更新模式并应用资源包资源。 + /// + /// 要应用的资源包路径。 + /// 使用可更新模式并应用资源包资源完成时的回调函数。 + public void ApplyResources(string resourcePackPath, ApplyResourcesCompleteCallback applyResourcesCompleteCallback) + { + m_ResourceManager.ApplyResources(resourcePackPath, applyResourcesCompleteCallback); + } + + /// + /// 使用可更新模式并更新所有资源。 + /// + /// 使用可更新模式并更新默认资源组完成时的回调函数。 + public void UpdateResources(UpdateResourcesCompleteCallback updateResourcesCompleteCallback) + { + m_ResourceManager.UpdateResources(updateResourcesCompleteCallback); + } + + /// + /// 使用可更新模式并更新指定资源组的资源。 + /// + /// 要更新的资源组名称。 + /// 使用可更新模式并更新指定资源组完成时的回调函数。 + public void UpdateResources(string resourceGroupName, UpdateResourcesCompleteCallback updateResourcesCompleteCallback) + { + m_ResourceManager.UpdateResources(resourceGroupName, updateResourcesCompleteCallback); + } + + /// + /// 停止更新资源。 + /// + public void StopUpdateResources() + { + m_ResourceManager.StopUpdateResources(); + } + + /// + /// 校验资源包。 + /// + /// 要校验的资源包路径。 + /// 是否校验资源包成功。 + public bool VerifyResourcePack(string resourcePackPath) + { + return m_ResourceManager.VerifyResourcePack(resourcePackPath); + } + + /// + /// 获取所有加载资源任务的信息。 + /// + /// 所有加载资源任务的信息。 + public TaskInfo[] GetAllLoadAssetInfos() + { + return m_ResourceManager.GetAllLoadAssetInfos(); + } + + /// + /// 获取所有加载资源任务的信息。 + /// + /// 所有加载资源任务的信息。 + public void GetAllLoadAssetInfos(List results) + { + m_ResourceManager.GetAllLoadAssetInfos(results); + } + + /// + /// 检查资源是否存在。 + /// + /// 要检查资源的名称。 + /// 检查资源是否存在的结果。 + public HasAssetResult HasAsset(string assetName) + { + return m_ResourceManager.HasAsset(assetName); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源回调函数集。 + public void LoadAsset(string assetName, LoadAssetCallbacks loadAssetCallbacks) + { + LoadAsset(assetName, null, DefaultPriority, loadAssetCallbacks, null); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源回调函数集。 + public void LoadAsset(string assetName, Type assetType, LoadAssetCallbacks loadAssetCallbacks) + { + LoadAsset(assetName, assetType, DefaultPriority, loadAssetCallbacks, null); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + public void LoadAsset(string assetName, int priority, LoadAssetCallbacks loadAssetCallbacks) + { + LoadAsset(assetName, null, priority, loadAssetCallbacks, null); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + LoadAsset(assetName, null, DefaultPriority, loadAssetCallbacks, userData); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + public void LoadAsset(string assetName, Type assetType, int priority, LoadAssetCallbacks loadAssetCallbacks) + { + LoadAsset(assetName, assetType, priority, loadAssetCallbacks, null); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, Type assetType, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + LoadAsset(assetName, assetType, DefaultPriority, loadAssetCallbacks, userData); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, int priority, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + LoadAsset(assetName, null, priority, loadAssetCallbacks, userData); + } + + /// + /// 异步加载资源。 + /// + /// 要加载资源的名称。 + /// 要加载资源的类型。 + /// 加载资源的优先级。 + /// 加载资源回调函数集。 + /// 用户自定义数据。 + public void LoadAsset(string assetName, Type assetType, int priority, LoadAssetCallbacks loadAssetCallbacks, object userData) + { + if (string.IsNullOrEmpty(assetName)) + { + Log.Error("Asset name is invalid."); + return; + } + + if (!assetName.StartsWith("Assets/", StringComparison.Ordinal)) + { + Log.Error("Asset name '{0}' is invalid.", assetName); + return; + } + + m_ResourceManager.LoadAsset(assetName, assetType, priority, loadAssetCallbacks, userData); + } + + /// + /// 卸载资源。 + /// + /// 要卸载的资源。 + public void UnloadAsset(object asset) + { + m_ResourceManager.UnloadAsset(asset); + } + + /// + /// 获取二进制资源的实际路径。 + /// + /// 要获取实际路径的二进制资源的名称。 + /// 二进制资源的实际路径。 + /// 此方法仅适用于二进制资源存储在磁盘(而非文件系统)中的情况。若二进制资源存储在文件系统中时,返回值将始终为空。 + public string GetBinaryPath(string binaryAssetName) + { + return m_ResourceManager.GetBinaryPath(binaryAssetName); + } + + /// + /// 获取二进制资源的实际路径。 + /// + /// 要获取实际路径的二进制资源的名称。 + /// 二进制资源是否存储在只读区中。 + /// 二进制资源是否存储在文件系统中。 + /// 二进制资源或存储二进制资源的文件系统,相对于只读区或者读写区的相对路径。 + /// 若二进制资源存储在文件系统中,则指示二进制资源在文件系统中的名称,否则此参数返回空。 + /// 是否获取二进制资源的实际路径成功。 + public bool GetBinaryPath(string binaryAssetName, out bool storageInReadOnly, out bool storageInFileSystem, out string relativePath, out string fileName) + { + return m_ResourceManager.GetBinaryPath(binaryAssetName, out storageInReadOnly, out storageInFileSystem, out relativePath, out fileName); + } + + /// + /// 获取二进制资源的长度。 + /// + /// 要获取长度的二进制资源的名称。 + /// 二进制资源的长度。 + public int GetBinaryLength(string binaryAssetName) + { + return m_ResourceManager.GetBinaryLength(binaryAssetName); + } + + /// + /// 异步加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 加载二进制资源回调函数集。 + public void LoadBinary(string binaryAssetName, LoadBinaryCallbacks loadBinaryCallbacks) + { + LoadBinary(binaryAssetName, loadBinaryCallbacks, null); + } + + /// + /// 异步加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 加载二进制资源回调函数集。 + /// 用户自定义数据。 + public void LoadBinary(string binaryAssetName, LoadBinaryCallbacks loadBinaryCallbacks, object userData) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + Log.Error("Binary asset name is invalid."); + return; + } + + if (!binaryAssetName.StartsWith("Assets/", StringComparison.Ordinal)) + { + Log.Error("Binary asset name '{0}' is invalid.", binaryAssetName); + return; + } + + m_ResourceManager.LoadBinary(binaryAssetName, loadBinaryCallbacks, userData); + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + public byte[] LoadBinaryFromFileSystem(string binaryAssetName) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + Log.Error("Binary asset name is invalid."); + return null; + } + + if (!binaryAssetName.StartsWith("Assets/", StringComparison.Ordinal)) + { + Log.Error("Binary asset name '{0}' is invalid.", binaryAssetName); + return null; + } + + return m_ResourceManager.LoadBinaryFromFileSystem(binaryAssetName); + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 实际加载了多少字节。 + public int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer) + { + if (buffer == null) + { + Log.Error("Buffer is invalid."); + return 0; + } + + return LoadBinaryFromFileSystem(binaryAssetName, buffer, 0, buffer.Length); + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 存储加载二进制资源的二进制流的起始位置。 + /// 实际加载了多少字节。 + public int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex) + { + if (buffer == null) + { + Log.Error("Buffer is invalid."); + return 0; + } + + return LoadBinaryFromFileSystem(binaryAssetName, buffer, startIndex, buffer.Length - startIndex); + } + + /// + /// 从文件系统中加载二进制资源。 + /// + /// 要加载二进制资源的名称。 + /// 存储加载二进制资源的二进制流。 + /// 存储加载二进制资源的二进制流的起始位置。 + /// 存储加载二进制资源的二进制流的长度。 + /// 实际加载了多少字节。 + public int LoadBinaryFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex, int length) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + Log.Error("Binary asset name is invalid."); + return 0; + } + + if (!binaryAssetName.StartsWith("Assets/", StringComparison.Ordinal)) + { + Log.Error("Binary asset name '{0}' is invalid.", binaryAssetName); + return 0; + } + + if (buffer == null) + { + Log.Error("Buffer is invalid."); + return 0; + } + + return m_ResourceManager.LoadBinaryFromFileSystem(binaryAssetName, buffer, startIndex, length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的长度。 + /// 存储加载二进制资源片段内容的二进制流。 + public byte[] LoadBinarySegmentFromFileSystem(string binaryAssetName, int length) + { + return LoadBinarySegmentFromFileSystem(binaryAssetName, 0, length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 要加载片段的长度。 + /// 存储加载二进制资源片段内容的二进制流。 + public byte[] LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, int length) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + Log.Error("Binary asset name is invalid."); + return null; + } + + if (!binaryAssetName.StartsWith("Assets/", StringComparison.Ordinal)) + { + Log.Error("Binary asset name '{0}' is invalid.", binaryAssetName); + return null; + } + + return m_ResourceManager.LoadBinarySegmentFromFileSystem(binaryAssetName, offset, length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, byte[] buffer) + { + if (buffer == null) + { + Log.Error("Buffer is invalid."); + return 0; + } + + return LoadBinarySegmentFromFileSystem(binaryAssetName, 0, buffer, 0, buffer.Length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, byte[] buffer, int length) + { + return LoadBinarySegmentFromFileSystem(binaryAssetName, 0, buffer, 0, length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 存储加载二进制资源片段内容的二进制流的起始位置。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, byte[] buffer, int startIndex, int length) + { + return LoadBinarySegmentFromFileSystem(binaryAssetName, 0, buffer, startIndex, length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer) + { + if (buffer == null) + { + Log.Error("Buffer is invalid."); + return 0; + } + + return LoadBinarySegmentFromFileSystem(binaryAssetName, offset, buffer, 0, buffer.Length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer, int length) + { + return LoadBinarySegmentFromFileSystem(binaryAssetName, offset, buffer, 0, length); + } + + /// + /// 从文件系统中加载二进制资源的片段。 + /// + /// 要加载片段的二进制资源的名称。 + /// 要加载片段的偏移。 + /// 存储加载二进制资源片段内容的二进制流。 + /// 存储加载二进制资源片段内容的二进制流的起始位置。 + /// 要加载片段的长度。 + /// 实际加载了多少字节。 + public int LoadBinarySegmentFromFileSystem(string binaryAssetName, int offset, byte[] buffer, int startIndex, int length) + { + if (string.IsNullOrEmpty(binaryAssetName)) + { + Log.Error("Binary asset name is invalid."); + return 0; + } + + if (!binaryAssetName.StartsWith("Assets/", StringComparison.Ordinal)) + { + Log.Error("Binary asset name '{0}' is invalid.", binaryAssetName); + return 0; + } + + if (buffer == null) + { + Log.Error("Buffer is invalid."); + return 0; + } + + return m_ResourceManager.LoadBinarySegmentFromFileSystem(binaryAssetName, offset, buffer, startIndex, length); + } + + /// + /// 检查资源组是否存在。 + /// + /// 要检查资源组的名称。 + /// 资源组是否存在。 + public bool HasResourceGroup(string resourceGroupName) + { + return m_ResourceManager.HasResourceGroup(resourceGroupName); + } + + /// + /// 获取默认资源组。 + /// + /// 默认资源组。 + public IResourceGroup GetResourceGroup() + { + return m_ResourceManager.GetResourceGroup(); + } + + /// + /// 获取资源组。 + /// + /// 要获取的资源组名称。 + /// 要获取的资源组。 + public IResourceGroup GetResourceGroup(string resourceGroupName) + { + return m_ResourceManager.GetResourceGroup(resourceGroupName); + } + + /// + /// 获取所有资源组。 + /// + /// 所有资源组。 + public IResourceGroup[] GetAllResourceGroups() + { + return m_ResourceManager.GetAllResourceGroups(); + } + + /// + /// 获取所有资源组。 + /// + /// 所有资源组。 + public void GetAllResourceGroups(List results) + { + m_ResourceManager.GetAllResourceGroups(results); + } + + /// + /// 获取资源组集合。 + /// + /// 要获取的资源组名称的集合。 + /// 要获取的资源组集合。 + public IResourceGroupCollection GetResourceGroupCollection(params string[] resourceGroupNames) + { + return m_ResourceManager.GetResourceGroupCollection(resourceGroupNames); + } + + /// + /// 获取资源组集合。 + /// + /// 要获取的资源组名称的集合。 + /// 要获取的资源组集合。 + public IResourceGroupCollection GetResourceGroupCollection(List resourceGroupNames) + { + return m_ResourceManager.GetResourceGroupCollection(resourceGroupNames); + } + + /// + /// 增加加载资源代理辅助器。 + /// + /// 加载资源代理辅助器索引。 + private void AddLoadResourceAgentHelper(int index) + { + LoadResourceAgentHelperBase loadResourceAgentHelper = Helper.CreateHelper(m_LoadResourceAgentHelperTypeName, m_CustomLoadResourceAgentHelper, index); + if (loadResourceAgentHelper == null) + { + Log.Error("Can not create load resource agent helper."); + return; + } + + loadResourceAgentHelper.name = Utility.Text.Format("Load Resource Agent Helper - {0}", index); + Transform transform = loadResourceAgentHelper.transform; + transform.SetParent(m_InstanceRoot); + transform.localScale = Vector3.one; + + m_ResourceManager.AddLoadResourceAgentHelper(loadResourceAgentHelper); + } + + private void OnResourceVerifyStart(object sender, GameFramework.Resource.ResourceVerifyStartEventArgs e) + { + m_EventComponent.Fire(this, ResourceVerifyStartEventArgs.Create(e)); + } + + private void OnResourceVerifySuccess(object sender, GameFramework.Resource.ResourceVerifySuccessEventArgs e) + { + m_EventComponent.Fire(this, ResourceVerifySuccessEventArgs.Create(e)); + } + + private void OnResourceVerifyFailure(object sender, GameFramework.Resource.ResourceVerifyFailureEventArgs e) + { + m_EventComponent.Fire(this, ResourceVerifyFailureEventArgs.Create(e)); + } + + private void OnResourceApplyStart(object sender, GameFramework.Resource.ResourceApplyStartEventArgs e) + { + m_EventComponent.Fire(this, ResourceApplyStartEventArgs.Create(e)); + } + + private void OnResourceApplySuccess(object sender, GameFramework.Resource.ResourceApplySuccessEventArgs e) + { + m_EventComponent.Fire(this, ResourceApplySuccessEventArgs.Create(e)); + } + + private void OnResourceApplyFailure(object sender, GameFramework.Resource.ResourceApplyFailureEventArgs e) + { + m_EventComponent.Fire(this, ResourceApplyFailureEventArgs.Create(e)); + } + + private void OnResourceUpdateStart(object sender, GameFramework.Resource.ResourceUpdateStartEventArgs e) + { + m_EventComponent.Fire(this, ResourceUpdateStartEventArgs.Create(e)); + } + + private void OnResourceUpdateChanged(object sender, GameFramework.Resource.ResourceUpdateChangedEventArgs e) + { + m_EventComponent.Fire(this, ResourceUpdateChangedEventArgs.Create(e)); + } + + private void OnResourceUpdateSuccess(object sender, GameFramework.Resource.ResourceUpdateSuccessEventArgs e) + { + m_EventComponent.Fire(this, ResourceUpdateSuccessEventArgs.Create(e)); + } + + private void OnResourceUpdateFailure(object sender, GameFramework.Resource.ResourceUpdateFailureEventArgs e) + { + m_EventComponent.Fire(this, ResourceUpdateFailureEventArgs.Create(e)); + } + + private void OnResourceUpdateAllComplete(object sender, GameFramework.Resource.ResourceUpdateAllCompleteEventArgs e) + { + m_EventComponent.Fire(this, ResourceUpdateAllCompleteEventArgs.Create(e)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceComponent.cs.meta new file mode 100644 index 0000000..8b99b82 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7eff66e40586ec14d8a301d416f17f1e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceHelperBase.cs new file mode 100644 index 0000000..df016bf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceHelperBase.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Resource; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源辅助器基类。 + /// + public abstract class ResourceHelperBase : MonoBehaviour, IResourceHelper + { + /// + /// 直接从指定文件路径加载数据流。 + /// + /// 文件路径。 + /// 加载数据流回调函数集。 + /// 用户自定义数据。 + public abstract void LoadBytes(string fileUri, LoadBytesCallbacks loadBytesCallbacks, object userData); + + /// + /// 卸载场景。 + /// + /// 场景资源名称。 + /// 卸载场景回调函数集。 + /// 用户自定义数据。 + public abstract void UnloadScene(string sceneAssetName, UnloadSceneCallbacks unloadSceneCallbacks, object userData); + + /// + /// 释放资源。 + /// + /// 要释放的资源。 + public abstract void Release(object objectToRelease); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceHelperBase.cs.meta new file mode 100644 index 0000000..d5bb43b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 231b6034e6f70794886826c9ba18dc2d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateAllCompleteEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateAllCompleteEventArgs.cs new file mode 100644 index 0000000..219c0a2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateAllCompleteEventArgs.cs @@ -0,0 +1,58 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源更新全部完成事件。 + /// + public sealed class ResourceUpdateAllCompleteEventArgs : GameEventArgs + { + /// + /// 资源更新全部完成事件编号。 + /// + public static readonly int EventId = typeof(ResourceUpdateAllCompleteEventArgs).GetHashCode(); + + /// + /// 初始化资源更新全部完成事件的新实例。 + /// + public ResourceUpdateAllCompleteEventArgs() + { + } + + /// + /// 获取资源更新全部完成事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 创建资源更新全部完成事件。 + /// + /// 内部事件。 + /// 创建的资源更新全部完成事件。 + public static ResourceUpdateAllCompleteEventArgs Create(GameFramework.Resource.ResourceUpdateAllCompleteEventArgs e) + { + return ReferencePool.Acquire(); + } + + /// + /// 清理资源更新全部完成事件。 + /// + public override void Clear() + { + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateAllCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateAllCompleteEventArgs.cs.meta new file mode 100644 index 0000000..76f67ac --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateAllCompleteEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2170354b236b90446bdd75a841140b52 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateChangedEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateChangedEventArgs.cs new file mode 100644 index 0000000..f117e3b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateChangedEventArgs.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源更新改变事件。 + /// + public sealed class ResourceUpdateChangedEventArgs : GameEventArgs + { + /// + /// 资源更新改变事件编号。 + /// + public static readonly int EventId = typeof(ResourceUpdateChangedEventArgs).GetHashCode(); + + /// + /// 初始化资源更新改变事件的新实例。 + /// + public ResourceUpdateChangedEventArgs() + { + Name = null; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0; + CompressedLength = 0; + } + + /// + /// 获取资源更新改变事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取资源下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取当前下载大小。 + /// + public int CurrentLength + { + get; + private set; + } + + /// + /// 获取压缩后大小。 + /// + public int CompressedLength + { + get; + private set; + } + + /// + /// 创建资源更新改变事件。 + /// + /// 内部事件。 + /// 创建的资源更新改变事件。 + public static ResourceUpdateChangedEventArgs Create(GameFramework.Resource.ResourceUpdateChangedEventArgs e) + { + ResourceUpdateChangedEventArgs resourceUpdateChangedEventArgs = ReferencePool.Acquire(); + resourceUpdateChangedEventArgs.Name = e.Name; + resourceUpdateChangedEventArgs.DownloadPath = e.DownloadPath; + resourceUpdateChangedEventArgs.DownloadUri = e.DownloadUri; + resourceUpdateChangedEventArgs.CurrentLength = e.CurrentLength; + resourceUpdateChangedEventArgs.CompressedLength = e.CompressedLength; + return resourceUpdateChangedEventArgs; + } + + /// + /// 清理资源更新改变事件。 + /// + public override void Clear() + { + Name = null; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0; + CompressedLength = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateChangedEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateChangedEventArgs.cs.meta new file mode 100644 index 0000000..c4fffdb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateChangedEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 578263f614242464495370d64b664c7f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateFailureEventArgs.cs new file mode 100644 index 0000000..27f5757 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateFailureEventArgs.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源更新失败事件。 + /// + public sealed class ResourceUpdateFailureEventArgs : GameEventArgs + { + /// + /// 资源更新失败事件编号。 + /// + public static readonly int EventId = typeof(ResourceUpdateFailureEventArgs).GetHashCode(); + + /// + /// 初始化资源更新失败事件的新实例。 + /// + public ResourceUpdateFailureEventArgs() + { + Name = null; + DownloadUri = null; + RetryCount = 0; + TotalRetryCount = 0; + ErrorMessage = null; + } + + /// + /// 获取资源更新失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取已重试次数。 + /// + public int RetryCount + { + get; + private set; + } + + /// + /// 获取设定的重试次数。 + /// + public int TotalRetryCount + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 创建资源更新失败事件。 + /// + /// 内部事件。 + /// 创建的资源更新失败事件。 + public static ResourceUpdateFailureEventArgs Create(GameFramework.Resource.ResourceUpdateFailureEventArgs e) + { + ResourceUpdateFailureEventArgs resourceUpdateFailureEventArgs = ReferencePool.Acquire(); + resourceUpdateFailureEventArgs.Name = e.Name; + resourceUpdateFailureEventArgs.DownloadUri = e.DownloadUri; + resourceUpdateFailureEventArgs.RetryCount = e.RetryCount; + resourceUpdateFailureEventArgs.TotalRetryCount = e.TotalRetryCount; + resourceUpdateFailureEventArgs.ErrorMessage = e.ErrorMessage; + return resourceUpdateFailureEventArgs; + } + + /// + /// 清理资源更新失败事件。 + /// + public override void Clear() + { + Name = null; + DownloadUri = null; + RetryCount = 0; + TotalRetryCount = 0; + ErrorMessage = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateFailureEventArgs.cs.meta new file mode 100644 index 0000000..36fddcf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6425ae0a812a24b4a863461585a7c7ea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateStartEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateStartEventArgs.cs new file mode 100644 index 0000000..14f191d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateStartEventArgs.cs @@ -0,0 +1,131 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源更新开始事件。 + /// + public sealed class ResourceUpdateStartEventArgs : GameEventArgs + { + /// + /// 资源更新开始事件编号。 + /// + public static readonly int EventId = typeof(ResourceUpdateStartEventArgs).GetHashCode(); + + /// + /// 初始化资源更新开始事件的新实例。 + /// + public ResourceUpdateStartEventArgs() + { + Name = null; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0; + CompressedLength = 0; + RetryCount = 0; + } + + /// + /// 获取资源更新开始事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取资源下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取当前下载大小。 + /// + public int CurrentLength + { + get; + private set; + } + + /// + /// 获取压缩后大小。 + /// + public int CompressedLength + { + get; + private set; + } + + /// + /// 获取已重试下载次数。 + /// + public int RetryCount + { + get; + private set; + } + + /// + /// 创建资源更新开始事件。 + /// + /// 内部事件。 + /// 创建的资源更新开始事件。 + public static ResourceUpdateStartEventArgs Create(GameFramework.Resource.ResourceUpdateStartEventArgs e) + { + ResourceUpdateStartEventArgs resourceUpdateStartEventArgs = ReferencePool.Acquire(); + resourceUpdateStartEventArgs.Name = e.Name; + resourceUpdateStartEventArgs.DownloadPath = e.DownloadPath; + resourceUpdateStartEventArgs.DownloadUri = e.DownloadUri; + resourceUpdateStartEventArgs.CurrentLength = e.CurrentLength; + resourceUpdateStartEventArgs.CompressedLength = e.CompressedLength; + resourceUpdateStartEventArgs.RetryCount = e.RetryCount; + return resourceUpdateStartEventArgs; + } + + /// + /// 清理资源更新开始事件。 + /// + public override void Clear() + { + Name = null; + DownloadPath = null; + DownloadUri = null; + CurrentLength = 0; + CompressedLength = 0; + RetryCount = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateStartEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateStartEventArgs.cs.meta new file mode 100644 index 0000000..2461868 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateStartEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b52ac443f249b2549827406d63bcbc57 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateSuccessEventArgs.cs new file mode 100644 index 0000000..8438b3d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateSuccessEventArgs.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源更新成功事件。 + /// + public sealed class ResourceUpdateSuccessEventArgs : GameEventArgs + { + /// + /// 资源更新成功事件编号。 + /// + public static readonly int EventId = typeof(ResourceUpdateSuccessEventArgs).GetHashCode(); + + /// + /// 初始化资源更新成功事件的新实例。 + /// + public ResourceUpdateSuccessEventArgs() + { + Name = null; + DownloadPath = null; + DownloadUri = null; + Length = 0; + CompressedLength = 0; + } + + /// + /// 获取资源更新成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取资源下载后存放路径。 + /// + public string DownloadPath + { + get; + private set; + } + + /// + /// 获取下载地址。 + /// + public string DownloadUri + { + get; + private set; + } + + /// + /// 获取资源大小。 + /// + public int Length + { + get; + private set; + } + + /// + /// 获取压缩后大小。 + /// + public int CompressedLength + { + get; + private set; + } + + /// + /// 创建资源更新成功事件。 + /// + /// 内部事件。 + /// 创建的资源更新成功事件。 + public static ResourceUpdateSuccessEventArgs Create(GameFramework.Resource.ResourceUpdateSuccessEventArgs e) + { + ResourceUpdateSuccessEventArgs resourceUpdateSuccessEventArgs = ReferencePool.Acquire(); + resourceUpdateSuccessEventArgs.Name = e.Name; + resourceUpdateSuccessEventArgs.DownloadPath = e.DownloadPath; + resourceUpdateSuccessEventArgs.DownloadUri = e.DownloadUri; + resourceUpdateSuccessEventArgs.Length = e.Length; + resourceUpdateSuccessEventArgs.CompressedLength = e.CompressedLength; + return resourceUpdateSuccessEventArgs; + } + + /// + /// 清理资源更新成功事件。 + /// + public override void Clear() + { + Name = null; + DownloadPath = null; + DownloadUri = null; + Length = 0; + CompressedLength = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateSuccessEventArgs.cs.meta new file mode 100644 index 0000000..2d27644 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceUpdateSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d652343468bb5eb489ea17764743a770 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifyFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifyFailureEventArgs.cs new file mode 100644 index 0000000..326a22b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifyFailureEventArgs.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源校验失败事件。 + /// + public sealed class ResourceVerifyFailureEventArgs : GameEventArgs + { + /// + /// 资源校验失败事件编号。 + /// + public static readonly int EventId = typeof(ResourceVerifyFailureEventArgs).GetHashCode(); + + /// + /// 初始化资源校验失败事件的新实例。 + /// + public ResourceVerifyFailureEventArgs() + { + Name = null; + } + + /// + /// 获取资源校验失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 创建资源校验失败事件。 + /// + /// 内部事件。 + /// 创建的资源校验失败事件。 + public static ResourceVerifyFailureEventArgs Create(GameFramework.Resource.ResourceVerifyFailureEventArgs e) + { + ResourceVerifyFailureEventArgs resourceVerifyFailureEventArgs = ReferencePool.Acquire(); + resourceVerifyFailureEventArgs.Name = e.Name; + return resourceVerifyFailureEventArgs; + } + + /// + /// 清理资源校验失败事件。 + /// + public override void Clear() + { + Name = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifyFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifyFailureEventArgs.cs.meta new file mode 100644 index 0000000..98a87dc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifyFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7adfa3d08717d2d4f9ffb7052753a3bc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifyStartEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifyStartEventArgs.cs new file mode 100644 index 0000000..9879f0a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifyStartEventArgs.cs @@ -0,0 +1,83 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源校验开始事件。 + /// + public sealed class ResourceVerifyStartEventArgs : GameEventArgs + { + /// + /// 资源校验开始事件编号。 + /// + public static readonly int EventId = typeof(ResourceVerifyStartEventArgs).GetHashCode(); + + /// + /// 初始化资源校验开始事件的新实例。 + /// + public ResourceVerifyStartEventArgs() + { + Count = 0; + TotalLength = 0L; + } + + /// + /// 获取资源校验开始事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取要校验资源的数量。 + /// + public int Count + { + get; + private set; + } + + /// + /// 获取要校验资源的总大小。 + /// + public long TotalLength + { + get; + private set; + } + + /// + /// 创建资源校验开始事件。 + /// + /// 内部事件。 + /// 创建的资源校验开始事件。 + public static ResourceVerifyStartEventArgs Create(GameFramework.Resource.ResourceVerifyStartEventArgs e) + { + ResourceVerifyStartEventArgs resourceVerifyStartEventArgs = ReferencePool.Acquire(); + resourceVerifyStartEventArgs.Count = e.Count; + resourceVerifyStartEventArgs.TotalLength = e.TotalLength; + return resourceVerifyStartEventArgs; + } + + /// + /// 清理资源校验开始事件。 + /// + public override void Clear() + { + Count = 0; + TotalLength = 0L; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifyStartEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifyStartEventArgs.cs.meta new file mode 100644 index 0000000..1def453 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifyStartEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 42cc09d13fb26744ab9fc5da7714f443 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifySuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifySuccessEventArgs.cs new file mode 100644 index 0000000..e90ac8a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifySuccessEventArgs.cs @@ -0,0 +1,83 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 资源校验成功事件。 + /// + public sealed class ResourceVerifySuccessEventArgs : GameEventArgs + { + /// + /// 资源校验成功事件编号。 + /// + public static readonly int EventId = typeof(ResourceVerifySuccessEventArgs).GetHashCode(); + + /// + /// 初始化资源校验成功事件的新实例。 + /// + public ResourceVerifySuccessEventArgs() + { + Name = null; + Length = 0; + } + + /// + /// 获取资源校验成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取资源名称。 + /// + public string Name + { + get; + private set; + } + + /// + /// 获取资源大小。 + /// + public int Length + { + get; + private set; + } + + /// + /// 创建资源校验成功事件。 + /// + /// 内部事件。 + /// 创建的资源校验成功事件。 + public static ResourceVerifySuccessEventArgs Create(GameFramework.Resource.ResourceVerifySuccessEventArgs e) + { + ResourceVerifySuccessEventArgs resourceVerifySuccessEventArgs = ReferencePool.Acquire(); + resourceVerifySuccessEventArgs.Name = e.Name; + resourceVerifySuccessEventArgs.Length = e.Length; + return resourceVerifySuccessEventArgs; + } + + /// + /// 清理资源校验成功事件。 + /// + public override void Clear() + { + Name = null; + Length = 0; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifySuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifySuccessEventArgs.cs.meta new file mode 100644 index 0000000..d27f4c5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/ResourceVerifySuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4318e2ddfebdf804eaac67df48fd4a83 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/SceneAsset.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/SceneAsset.cs new file mode 100644 index 0000000..c926b6f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/SceneAsset.cs @@ -0,0 +1,13 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Runtime +{ + internal sealed class SceneAsset + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/SceneAsset.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/SceneAsset.cs.meta new file mode 100644 index 0000000..4f03827 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Resource/SceneAsset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed139c50a07e4544eb7ff7e75654d488 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene.meta new file mode 100644 index 0000000..1149c08 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 141ad46133ef8f54e9f4f0ac35f0da19 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/ActiveSceneChangedEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/ActiveSceneChangedEventArgs.cs new file mode 100644 index 0000000..21baa72 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/ActiveSceneChangedEventArgs.cs @@ -0,0 +1,85 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using UnityEngine.SceneManagement; + +namespace UnityGameFramework.Runtime +{ + /// + /// 激活场景被改变事件。 + /// + public sealed class ActiveSceneChangedEventArgs : GameEventArgs + { + /// + /// 激活场景被改变事件编号。 + /// + public static readonly int EventId = typeof(ActiveSceneChangedEventArgs).GetHashCode(); + + /// + /// 初始化激活场景被改变事件的新实例。 + /// + public ActiveSceneChangedEventArgs() + { + LastActiveScene = default(Scene); + ActiveScene = default(Scene); + } + + /// + /// 获取激活场景被改变事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取上一个被激活的场景。 + /// + public Scene LastActiveScene + { + get; + private set; + } + + /// + /// 获取被激活的场景。 + /// + public Scene ActiveScene + { + get; + private set; + } + + /// + /// 创建激活场景被改变事件。 + /// + /// 上一个被激活的场景。 + /// 被激活的场景。 + /// 创建的激活场景被改变事件。 + public static ActiveSceneChangedEventArgs Create(Scene lastActiveScene, Scene activeScene) + { + ActiveSceneChangedEventArgs activeSceneChangedEventArgs = ReferencePool.Acquire(); + activeSceneChangedEventArgs.LastActiveScene = lastActiveScene; + activeSceneChangedEventArgs.ActiveScene = activeScene; + return activeSceneChangedEventArgs; + } + + /// + /// 清理激活场景被改变事件。 + /// + public override void Clear() + { + LastActiveScene = default(Scene); + ActiveScene = default(Scene); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/ActiveSceneChangedEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/ActiveSceneChangedEventArgs.cs.meta new file mode 100644 index 0000000..4292983 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/ActiveSceneChangedEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 41e284ba4b2e7b044b63702496b5b31f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneDependencyAssetEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneDependencyAssetEventArgs.cs new file mode 100644 index 0000000..5040201 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneDependencyAssetEventArgs.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载场景时加载依赖资源事件。 + /// + public sealed class LoadSceneDependencyAssetEventArgs : GameEventArgs + { + /// + /// 加载场景时加载依赖资源事件编号。 + /// + public static readonly int EventId = typeof(LoadSceneDependencyAssetEventArgs).GetHashCode(); + + /// + /// 初始化加载场景时加载依赖资源事件的新实例。 + /// + public LoadSceneDependencyAssetEventArgs() + { + SceneAssetName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + + /// + /// 获取加载场景时加载依赖资源事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取场景资源名称。 + /// + public string SceneAssetName + { + get; + private set; + } + + /// + /// 获取被加载的依赖资源名称。 + /// + public string DependencyAssetName + { + get; + private set; + } + + /// + /// 获取当前已加载依赖资源数量。 + /// + public int LoadedCount + { + get; + private set; + } + + /// + /// 获取总共加载依赖资源数量。 + /// + public int TotalCount + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载场景时加载依赖资源事件。 + /// + /// 内部事件。 + /// 创建的加载场景时加载依赖资源事件。 + public static LoadSceneDependencyAssetEventArgs Create(GameFramework.Scene.LoadSceneDependencyAssetEventArgs e) + { + LoadSceneDependencyAssetEventArgs loadSceneDependencyAssetEventArgs = ReferencePool.Acquire(); + loadSceneDependencyAssetEventArgs.SceneAssetName = e.SceneAssetName; + loadSceneDependencyAssetEventArgs.DependencyAssetName = e.DependencyAssetName; + loadSceneDependencyAssetEventArgs.LoadedCount = e.LoadedCount; + loadSceneDependencyAssetEventArgs.TotalCount = e.TotalCount; + loadSceneDependencyAssetEventArgs.UserData = e.UserData; + return loadSceneDependencyAssetEventArgs; + } + + /// + /// 清理加载场景时加载依赖资源事件。 + /// + public override void Clear() + { + SceneAssetName = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneDependencyAssetEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneDependencyAssetEventArgs.cs.meta new file mode 100644 index 0000000..f80db9f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneDependencyAssetEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1d79041cd45038b48acd126c6b44038a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneFailureEventArgs.cs new file mode 100644 index 0000000..603fa43 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneFailureEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载场景失败事件。 + /// + public sealed class LoadSceneFailureEventArgs : GameEventArgs + { + /// + /// 加载场景失败事件编号。 + /// + public static readonly int EventId = typeof(LoadSceneFailureEventArgs).GetHashCode(); + + /// + /// 初始化加载场景失败事件的新实例。 + /// + public LoadSceneFailureEventArgs() + { + SceneAssetName = null; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取加载场景失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取场景资源名称。 + /// + public string SceneAssetName + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载场景失败事件。 + /// + /// 内部事件。 + /// 创建的加载场景失败事件。 + public static LoadSceneFailureEventArgs Create(GameFramework.Scene.LoadSceneFailureEventArgs e) + { + LoadSceneFailureEventArgs loadSceneFailureEventArgs = ReferencePool.Acquire(); + loadSceneFailureEventArgs.SceneAssetName = e.SceneAssetName; + loadSceneFailureEventArgs.ErrorMessage = e.ErrorMessage; + loadSceneFailureEventArgs.UserData = e.UserData; + return loadSceneFailureEventArgs; + } + + /// + /// 清理加载场景失败事件。 + /// + public override void Clear() + { + SceneAssetName = null; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneFailureEventArgs.cs.meta new file mode 100644 index 0000000..559b54d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b164a3668d54e5418bb662588aa3805 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneSuccessEventArgs.cs new file mode 100644 index 0000000..83ce250 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneSuccessEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载场景成功事件。 + /// + public sealed class LoadSceneSuccessEventArgs : GameEventArgs + { + /// + /// 加载场景成功事件编号。 + /// + public static readonly int EventId = typeof(LoadSceneSuccessEventArgs).GetHashCode(); + + /// + /// 初始化加载场景成功事件的新实例。 + /// + public LoadSceneSuccessEventArgs() + { + SceneAssetName = null; + Duration = 0f; + UserData = null; + } + + /// + /// 获取加载场景成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取场景资源名称。 + /// + public string SceneAssetName + { + get; + private set; + } + + /// + /// 获取加载持续时间。 + /// + public float Duration + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载场景成功事件。 + /// + /// 内部事件。 + /// 创建的加载场景成功事件。 + public static LoadSceneSuccessEventArgs Create(GameFramework.Scene.LoadSceneSuccessEventArgs e) + { + LoadSceneSuccessEventArgs loadSceneSuccessEventArgs = ReferencePool.Acquire(); + loadSceneSuccessEventArgs.SceneAssetName = e.SceneAssetName; + loadSceneSuccessEventArgs.Duration = e.Duration; + loadSceneSuccessEventArgs.UserData = e.UserData; + return loadSceneSuccessEventArgs; + } + + /// + /// 清理加载场景成功事件。 + /// + public override void Clear() + { + SceneAssetName = null; + Duration = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneSuccessEventArgs.cs.meta new file mode 100644 index 0000000..dd0a63c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 05add94fc5037024c87844fd64e1ab71 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneUpdateEventArgs.cs new file mode 100644 index 0000000..3eccd9a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneUpdateEventArgs.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 加载场景更新事件。 + /// + public sealed class LoadSceneUpdateEventArgs : GameEventArgs + { + /// + /// 加载场景更新事件编号。 + /// + public static readonly int EventId = typeof(LoadSceneUpdateEventArgs).GetHashCode(); + + /// + /// 初始化加载场景更新事件的新实例。 + /// + public LoadSceneUpdateEventArgs() + { + SceneAssetName = null; + Progress = 0f; + UserData = null; + } + + /// + /// 获取加载场景更新事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取场景资源名称。 + /// + public string SceneAssetName + { + get; + private set; + } + + /// + /// 获取加载场景进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建加载场景更新事件。 + /// + /// 内部事件。 + /// 创建的加载场景更新事件。 + public static LoadSceneUpdateEventArgs Create(GameFramework.Scene.LoadSceneUpdateEventArgs e) + { + LoadSceneUpdateEventArgs loadSceneUpdateEventArgs = ReferencePool.Acquire(); + loadSceneUpdateEventArgs.SceneAssetName = e.SceneAssetName; + loadSceneUpdateEventArgs.Progress = e.Progress; + loadSceneUpdateEventArgs.UserData = e.UserData; + return loadSceneUpdateEventArgs; + } + + /// + /// 清理加载场景更新事件。 + /// + public override void Clear() + { + SceneAssetName = null; + Progress = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneUpdateEventArgs.cs.meta new file mode 100644 index 0000000..cc6628c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/LoadSceneUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9a8da542d25a6ee4b8e094e89c28bd7e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/SceneComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/SceneComponent.cs new file mode 100644 index 0000000..9f1dd3e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/SceneComponent.cs @@ -0,0 +1,477 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Resource; +using GameFramework.Scene; +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace UnityGameFramework.Runtime +{ + /// + /// 场景组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Scene")] + public sealed class SceneComponent : GameFrameworkComponent + { + private const int DefaultPriority = 0; + + private ISceneManager m_SceneManager = null; + private EventComponent m_EventComponent = null; + private readonly SortedDictionary m_SceneOrder = new SortedDictionary(StringComparer.Ordinal); + private Camera m_MainCamera = null; + private Scene m_GameFrameworkScene = default(Scene); + + [SerializeField] + private bool m_EnableLoadSceneUpdateEvent = true; + + [SerializeField] + private bool m_EnableLoadSceneDependencyAssetEvent = true; + + /// + /// 获取当前场景主摄像机。 + /// + public Camera MainCamera + { + get + { + return m_MainCamera; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_SceneManager = GameFrameworkEntry.GetModule(); + if (m_SceneManager == null) + { + Log.Fatal("Scene manager is invalid."); + return; + } + + m_SceneManager.LoadSceneSuccess += OnLoadSceneSuccess; + m_SceneManager.LoadSceneFailure += OnLoadSceneFailure; + + if (m_EnableLoadSceneUpdateEvent) + { + m_SceneManager.LoadSceneUpdate += OnLoadSceneUpdate; + } + + if (m_EnableLoadSceneDependencyAssetEvent) + { + m_SceneManager.LoadSceneDependencyAsset += OnLoadSceneDependencyAsset; + } + + m_SceneManager.UnloadSceneSuccess += OnUnloadSceneSuccess; + m_SceneManager.UnloadSceneFailure += OnUnloadSceneFailure; + + m_GameFrameworkScene = UnityEngine.SceneManagement.SceneManager.GetSceneAt(GameEntry.GameFrameworkSceneId); + if (!m_GameFrameworkScene.IsValid()) + { + Log.Fatal("Game Framework scene is invalid."); + return; + } + } + + private void Start() + { + BaseComponent baseComponent = GameEntry.GetComponent(); + if (baseComponent == null) + { + Log.Fatal("Base component is invalid."); + return; + } + + m_EventComponent = GameEntry.GetComponent(); + if (m_EventComponent == null) + { + Log.Fatal("Event component is invalid."); + return; + } + + if (baseComponent.EditorResourceMode) + { + m_SceneManager.SetResourceManager(baseComponent.EditorResourceHelper); + } + else + { + m_SceneManager.SetResourceManager(GameFrameworkEntry.GetModule()); + } + } + + /// + /// 获取场景名称。 + /// + /// 场景资源名称。 + /// 场景名称。 + public static string GetSceneName(string sceneAssetName) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + Log.Error("Scene asset name is invalid."); + return null; + } + + int sceneNamePosition = sceneAssetName.LastIndexOf('/'); + if (sceneNamePosition + 1 >= sceneAssetName.Length) + { + Log.Error("Scene asset name '{0}' is invalid.", sceneAssetName); + return null; + } + + string sceneName = sceneAssetName.Substring(sceneNamePosition + 1); + sceneNamePosition = sceneName.LastIndexOf(".unity"); + if (sceneNamePosition > 0) + { + sceneName = sceneName.Substring(0, sceneNamePosition); + } + + return sceneName; + } + + /// + /// 获取场景是否已加载。 + /// + /// 场景资源名称。 + /// 场景是否已加载。 + public bool SceneIsLoaded(string sceneAssetName) + { + return m_SceneManager.SceneIsLoaded(sceneAssetName); + } + + /// + /// 获取已加载场景的资源名称。 + /// + /// 已加载场景的资源名称。 + public string[] GetLoadedSceneAssetNames() + { + return m_SceneManager.GetLoadedSceneAssetNames(); + } + + /// + /// 获取已加载场景的资源名称。 + /// + /// 已加载场景的资源名称。 + public void GetLoadedSceneAssetNames(List results) + { + m_SceneManager.GetLoadedSceneAssetNames(results); + } + + /// + /// 获取场景是否正在加载。 + /// + /// 场景资源名称。 + /// 场景是否正在加载。 + public bool SceneIsLoading(string sceneAssetName) + { + return m_SceneManager.SceneIsLoading(sceneAssetName); + } + + /// + /// 获取正在加载场景的资源名称。 + /// + /// 正在加载场景的资源名称。 + public string[] GetLoadingSceneAssetNames() + { + return m_SceneManager.GetLoadingSceneAssetNames(); + } + + /// + /// 获取正在加载场景的资源名称。 + /// + /// 正在加载场景的资源名称。 + public void GetLoadingSceneAssetNames(List results) + { + m_SceneManager.GetLoadingSceneAssetNames(results); + } + + /// + /// 获取场景是否正在卸载。 + /// + /// 场景资源名称。 + /// 场景是否正在卸载。 + public bool SceneIsUnloading(string sceneAssetName) + { + return m_SceneManager.SceneIsUnloading(sceneAssetName); + } + + /// + /// 获取正在卸载场景的资源名称。 + /// + /// 正在卸载场景的资源名称。 + public string[] GetUnloadingSceneAssetNames() + { + return m_SceneManager.GetUnloadingSceneAssetNames(); + } + + /// + /// 获取正在卸载场景的资源名称。 + /// + /// 正在卸载场景的资源名称。 + public void GetUnloadingSceneAssetNames(List results) + { + m_SceneManager.GetUnloadingSceneAssetNames(results); + } + + /// + /// 检查场景资源是否存在。 + /// + /// 要检查场景资源的名称。 + /// 场景资源是否存在。 + public bool HasScene(string sceneAssetName) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + Log.Error("Scene asset name is invalid."); + return false; + } + + if (!sceneAssetName.StartsWith("Assets/", StringComparison.Ordinal) || !sceneAssetName.EndsWith(".unity", StringComparison.Ordinal)) + { + Log.Error("Scene asset name '{0}' is invalid.", sceneAssetName); + return false; + } + + return m_SceneManager.HasScene(sceneAssetName); + } + + /// + /// 加载场景。 + /// + /// 场景资源名称。 + public void LoadScene(string sceneAssetName) + { + LoadScene(sceneAssetName, DefaultPriority, null); + } + + /// + /// 加载场景。 + /// + /// 场景资源名称。 + /// 加载场景资源的优先级。 + public void LoadScene(string sceneAssetName, int priority) + { + LoadScene(sceneAssetName, priority, null); + } + + /// + /// 加载场景。 + /// + /// 场景资源名称。 + /// 用户自定义数据。 + public void LoadScene(string sceneAssetName, object userData) + { + LoadScene(sceneAssetName, DefaultPriority, userData); + } + + /// + /// 加载场景。 + /// + /// 场景资源名称。 + /// 加载场景资源的优先级。 + /// 用户自定义数据。 + public void LoadScene(string sceneAssetName, int priority, object userData) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + Log.Error("Scene asset name is invalid."); + return; + } + + if (!sceneAssetName.StartsWith("Assets/", StringComparison.Ordinal) || !sceneAssetName.EndsWith(".unity", StringComparison.Ordinal)) + { + Log.Error("Scene asset name '{0}' is invalid.", sceneAssetName); + return; + } + + m_SceneManager.LoadScene(sceneAssetName, priority, userData); + } + + /// + /// 卸载场景。 + /// + /// 场景资源名称。 + public void UnloadScene(string sceneAssetName) + { + UnloadScene(sceneAssetName, null); + } + + /// + /// 卸载场景。 + /// + /// 场景资源名称。 + /// 用户自定义数据。 + public void UnloadScene(string sceneAssetName, object userData) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + Log.Error("Scene asset name is invalid."); + return; + } + + if (!sceneAssetName.StartsWith("Assets/", StringComparison.Ordinal) || !sceneAssetName.EndsWith(".unity", StringComparison.Ordinal)) + { + Log.Error("Scene asset name '{0}' is invalid.", sceneAssetName); + return; + } + + m_SceneManager.UnloadScene(sceneAssetName, userData); + m_SceneOrder.Remove(sceneAssetName); + } + + /// + /// 设置场景顺序。 + /// + /// 场景资源名称。 + /// 要设置的场景顺序。 + public void SetSceneOrder(string sceneAssetName, int sceneOrder) + { + if (string.IsNullOrEmpty(sceneAssetName)) + { + Log.Error("Scene asset name is invalid."); + return; + } + + if (!sceneAssetName.StartsWith("Assets/", StringComparison.Ordinal) || !sceneAssetName.EndsWith(".unity", StringComparison.Ordinal)) + { + Log.Error("Scene asset name '{0}' is invalid.", sceneAssetName); + return; + } + + if (SceneIsLoading(sceneAssetName)) + { + m_SceneOrder[sceneAssetName] = sceneOrder; + return; + } + + if (SceneIsLoaded(sceneAssetName)) + { + m_SceneOrder[sceneAssetName] = sceneOrder; + RefreshSceneOrder(); + return; + } + + Log.Error("Scene '{0}' is not loaded or loading.", sceneAssetName); + } + + /// + /// 刷新当前场景主摄像机。 + /// + public void RefreshMainCamera() + { + m_MainCamera = Camera.main; + } + + private void RefreshSceneOrder() + { + if (m_SceneOrder.Count > 0) + { + string maxSceneName = null; + int maxSceneOrder = 0; + foreach (KeyValuePair sceneOrder in m_SceneOrder) + { + if (SceneIsLoading(sceneOrder.Key)) + { + continue; + } + + if (maxSceneName == null) + { + maxSceneName = sceneOrder.Key; + maxSceneOrder = sceneOrder.Value; + continue; + } + + if (sceneOrder.Value > maxSceneOrder) + { + maxSceneName = sceneOrder.Key; + maxSceneOrder = sceneOrder.Value; + } + } + + if (maxSceneName == null) + { + SetActiveScene(m_GameFrameworkScene); + return; + } + + Scene scene = UnityEngine.SceneManagement.SceneManager.GetSceneByName(GetSceneName(maxSceneName)); + if (!scene.IsValid()) + { + Log.Error("Active scene '{0}' is invalid.", maxSceneName); + return; + } + + SetActiveScene(scene); + } + else + { + SetActiveScene(m_GameFrameworkScene); + } + } + + private void SetActiveScene(Scene activeScene) + { + Scene lastActiveScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene(); + if (lastActiveScene != activeScene) + { + UnityEngine.SceneManagement.SceneManager.SetActiveScene(activeScene); + m_EventComponent.Fire(this, ActiveSceneChangedEventArgs.Create(lastActiveScene, activeScene)); + } + + RefreshMainCamera(); + } + + private void OnLoadSceneSuccess(object sender, GameFramework.Scene.LoadSceneSuccessEventArgs e) + { + if (!m_SceneOrder.ContainsKey(e.SceneAssetName)) + { + m_SceneOrder.Add(e.SceneAssetName, 0); + } + + m_EventComponent.Fire(this, LoadSceneSuccessEventArgs.Create(e)); + RefreshSceneOrder(); + } + + private void OnLoadSceneFailure(object sender, GameFramework.Scene.LoadSceneFailureEventArgs e) + { + Log.Warning("Load scene failure, scene asset name '{0}', error message '{1}'.", e.SceneAssetName, e.ErrorMessage); + m_EventComponent.Fire(this, LoadSceneFailureEventArgs.Create(e)); + } + + private void OnLoadSceneUpdate(object sender, GameFramework.Scene.LoadSceneUpdateEventArgs e) + { + m_EventComponent.Fire(this, LoadSceneUpdateEventArgs.Create(e)); + } + + private void OnLoadSceneDependencyAsset(object sender, GameFramework.Scene.LoadSceneDependencyAssetEventArgs e) + { + m_EventComponent.Fire(this, LoadSceneDependencyAssetEventArgs.Create(e)); + } + + private void OnUnloadSceneSuccess(object sender, GameFramework.Scene.UnloadSceneSuccessEventArgs e) + { + m_EventComponent.Fire(this, UnloadSceneSuccessEventArgs.Create(e)); + m_SceneOrder.Remove(e.SceneAssetName); + RefreshSceneOrder(); + } + + private void OnUnloadSceneFailure(object sender, GameFramework.Scene.UnloadSceneFailureEventArgs e) + { + Log.Warning("Unload scene failure, scene asset name '{0}'.", e.SceneAssetName); + m_EventComponent.Fire(this, UnloadSceneFailureEventArgs.Create(e)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/SceneComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/SceneComponent.cs.meta new file mode 100644 index 0000000..a5781ac --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/SceneComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b6242b052eb207b40b22e8fe77a315ba +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/UnloadSceneFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/UnloadSceneFailureEventArgs.cs new file mode 100644 index 0000000..d71bbd7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/UnloadSceneFailureEventArgs.cs @@ -0,0 +1,83 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 卸载场景失败事件。 + /// + public sealed class UnloadSceneFailureEventArgs : GameEventArgs + { + /// + /// 加载场景失败事件编号。 + /// + public static readonly int EventId = typeof(UnloadSceneFailureEventArgs).GetHashCode(); + + /// + /// 初始化卸载场景失败事件的新实例。 + /// + public UnloadSceneFailureEventArgs() + { + SceneAssetName = null; + UserData = null; + } + + /// + /// 获取加载场景失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取场景资源名称。 + /// + public string SceneAssetName + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建卸载场景失败事件。 + /// + /// 内部事件。 + /// 创建的卸载场景失败事件。 + public static UnloadSceneFailureEventArgs Create(GameFramework.Scene.UnloadSceneFailureEventArgs e) + { + UnloadSceneFailureEventArgs unloadSceneFailureEventArgs = ReferencePool.Acquire(); + unloadSceneFailureEventArgs.SceneAssetName = e.SceneAssetName; + unloadSceneFailureEventArgs.UserData = e.UserData; + return unloadSceneFailureEventArgs; + } + + /// + /// 清理卸载场景失败事件。 + /// + public override void Clear() + { + SceneAssetName = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/UnloadSceneFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/UnloadSceneFailureEventArgs.cs.meta new file mode 100644 index 0000000..52ea7e4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/UnloadSceneFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cfd40f0f395caf8498a268f03c5fea22 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/UnloadSceneSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/UnloadSceneSuccessEventArgs.cs new file mode 100644 index 0000000..b223277 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/UnloadSceneSuccessEventArgs.cs @@ -0,0 +1,83 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 卸载场景成功事件。 + /// + public sealed class UnloadSceneSuccessEventArgs : GameEventArgs + { + /// + /// 加载场景成功事件编号。 + /// + public static readonly int EventId = typeof(UnloadSceneSuccessEventArgs).GetHashCode(); + + /// + /// 初始化卸载场景成功事件的新实例。 + /// + public UnloadSceneSuccessEventArgs() + { + SceneAssetName = null; + UserData = null; + } + + /// + /// 获取加载场景成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取场景资源名称。 + /// + public string SceneAssetName + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建卸载场景成功事件。 + /// + /// 内部事件。 + /// 创建的卸载场景成功事件。 + public static UnloadSceneSuccessEventArgs Create(GameFramework.Scene.UnloadSceneSuccessEventArgs e) + { + UnloadSceneSuccessEventArgs unloadSceneSuccessEventArgs = ReferencePool.Acquire(); + unloadSceneSuccessEventArgs.SceneAssetName = e.SceneAssetName; + unloadSceneSuccessEventArgs.UserData = e.UserData; + return unloadSceneSuccessEventArgs; + } + + /// + /// 清理卸载场景成功事件。 + /// + public override void Clear() + { + SceneAssetName = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/UnloadSceneSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/UnloadSceneSuccessEventArgs.cs.meta new file mode 100644 index 0000000..d53c73a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Scene/UnloadSceneSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c38ffda9363f4c64686888e44d017e1f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting.meta new file mode 100644 index 0000000..5e1f342 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 92fcf07daa767d248bdf826a600dbf4a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSetting.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSetting.cs new file mode 100644 index 0000000..e8f62fe --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSetting.cs @@ -0,0 +1,313 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认游戏配置。 + /// + public sealed class DefaultSetting + { + private readonly SortedDictionary m_Settings = new SortedDictionary(StringComparer.Ordinal); + + /// + /// 初始化本地版本资源列表的新实例。 + /// + public DefaultSetting() + { + } + + /// + /// 获取游戏配置项数量。 + /// + public int Count + { + get + { + return m_Settings.Count; + } + } + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + public string[] GetAllSettingNames() + { + int index = 0; + string[] allSettingNames = new string[m_Settings.Count]; + foreach (KeyValuePair setting in m_Settings) + { + allSettingNames[index++] = setting.Key; + } + + return allSettingNames; + } + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + public void GetAllSettingNames(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + foreach (KeyValuePair setting in m_Settings) + { + results.Add(setting.Key); + } + } + + /// + /// 检查是否存在指定游戏配置项。 + /// + /// 要检查游戏配置项的名称。 + /// 指定的游戏配置项是否存在。 + public bool HasSetting(string settingName) + { + return m_Settings.ContainsKey(settingName); + } + + /// + /// 移除指定游戏配置项。 + /// + /// 要移除游戏配置项的名称。 + /// 是否移除指定游戏配置项成功。 + public bool RemoveSetting(string settingName) + { + return m_Settings.Remove(settingName); + } + + /// + /// 清空所有游戏配置项。 + /// + public void RemoveAllSettings() + { + m_Settings.Clear(); + } + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的布尔值。 + public bool GetBool(string settingName) + { + string value = null; + if (!m_Settings.TryGetValue(settingName, out value)) + { + Log.Warning("Setting '{0}' is not exist.", settingName); + return false; + } + + return int.Parse(value) != 0; + } + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的布尔值。 + public bool GetBool(string settingName, bool defaultValue) + { + string value = null; + if (!m_Settings.TryGetValue(settingName, out value)) + { + return defaultValue; + } + + return int.Parse(value) != 0; + } + + /// + /// 向指定游戏配置项写入布尔值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的布尔值。 + public void SetBool(string settingName, bool value) + { + m_Settings[settingName] = value ? "1" : "0"; + } + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的整数值。 + public int GetInt(string settingName) + { + string value = null; + if (!m_Settings.TryGetValue(settingName, out value)) + { + Log.Warning("Setting '{0}' is not exist.", settingName); + return 0; + } + + return int.Parse(value); + } + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的整数值。 + public int GetInt(string settingName, int defaultValue) + { + string value = null; + if (!m_Settings.TryGetValue(settingName, out value)) + { + return defaultValue; + } + + return int.Parse(value); + } + + /// + /// 向指定游戏配置项写入整数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的整数值。 + public void SetInt(string settingName, int value) + { + m_Settings[settingName] = value.ToString(); + } + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的浮点数值。 + public float GetFloat(string settingName) + { + string value = null; + if (!m_Settings.TryGetValue(settingName, out value)) + { + Log.Warning("Setting '{0}' is not exist.", settingName); + return 0f; + } + + return float.Parse(value); + } + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的浮点数值。 + public float GetFloat(string settingName, float defaultValue) + { + string value = null; + if (!m_Settings.TryGetValue(settingName, out value)) + { + return defaultValue; + } + + return float.Parse(value); + } + + /// + /// 向指定游戏配置项写入浮点数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的浮点数值。 + public void SetFloat(string settingName, float value) + { + m_Settings[settingName] = value.ToString(); + } + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的字符串值。 + public string GetString(string settingName) + { + string value = null; + if (!m_Settings.TryGetValue(settingName, out value)) + { + Log.Warning("Setting '{0}' is not exist.", settingName); + return null; + } + + return value; + } + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的字符串值。 + public string GetString(string settingName, string defaultValue) + { + string value = null; + if (!m_Settings.TryGetValue(settingName, out value)) + { + return defaultValue; + } + + return value; + } + + /// + /// 向指定游戏配置项写入字符串值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的字符串值。 + public void SetString(string settingName, string value) + { + m_Settings[settingName] = value; + } + + /// + /// 序列化数据。 + /// + /// 目标流。 + public void Serialize(Stream stream) + { + using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.UTF8)) + { + binaryWriter.Write7BitEncodedInt32(m_Settings.Count); + foreach (KeyValuePair setting in m_Settings) + { + binaryWriter.Write(setting.Key); + binaryWriter.Write(setting.Value); + } + } + } + + /// + /// 反序列化数据。 + /// + /// 指定流。 + public void Deserialize(Stream stream) + { + m_Settings.Clear(); + using (BinaryReader binaryReader = new BinaryReader(stream, Encoding.UTF8)) + { + int settingCount = binaryReader.Read7BitEncodedInt32(); + for (int i = 0; i < settingCount; i++) + { + m_Settings.Add(binaryReader.ReadString(), binaryReader.ReadString()); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSetting.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSetting.cs.meta new file mode 100644 index 0000000..3d43c75 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSetting.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7ab0df4276b162b41813b93d89dd9b6e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSettingHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSettingHelper.cs new file mode 100644 index 0000000..de64ab4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSettingHelper.cs @@ -0,0 +1,387 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Collections.Generic; +using System.IO; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认游戏配置辅助器。 + /// + public class DefaultSettingHelper : SettingHelperBase + { + private const string SettingFileName = "GameFrameworkSetting.dat"; + + private string m_FilePath = null; + private DefaultSetting m_Settings = null; + private DefaultSettingSerializer m_Serializer = null; + + /// + /// 获取游戏配置项数量。 + /// + public override int Count + { + get + { + return m_Settings != null ? m_Settings.Count : 0; + } + } + + /// + /// 获取游戏配置存储文件路径。 + /// + public string FilePath + { + get + { + return m_FilePath; + } + } + + /// + /// 获取游戏配置。 + /// + public DefaultSetting Setting + { + get + { + return m_Settings; + } + } + + /// + /// 获取游戏配置序列化器。 + /// + public DefaultSettingSerializer Serializer + { + get + { + return m_Serializer; + } + } + + /// + /// 加载游戏配置。 + /// + /// 是否加载游戏配置成功。 + public override bool Load() + { + try + { + if (!File.Exists(m_FilePath)) + { + return true; + } + + using (FileStream fileStream = new FileStream(m_FilePath, FileMode.Open, FileAccess.Read)) + { + m_Serializer.Deserialize(fileStream); + return true; + } + } + catch (Exception exception) + { + Log.Warning("Load settings failure with exception '{0}'.", exception); + return false; + } + } + + /// + /// 保存游戏配置。 + /// + /// 是否保存游戏配置成功。 + public override bool Save() + { + try + { + using (FileStream fileStream = new FileStream(m_FilePath, FileMode.Create, FileAccess.Write)) + { + return m_Serializer.Serialize(fileStream, m_Settings); + } + } + catch (Exception exception) + { + Log.Warning("Save settings failure with exception '{0}'.", exception); + return false; + } + } + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + public override string[] GetAllSettingNames() + { + return m_Settings.GetAllSettingNames(); + } + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + public override void GetAllSettingNames(List results) + { + m_Settings.GetAllSettingNames(results); + } + + /// + /// 检查是否存在指定游戏配置项。 + /// + /// 要检查游戏配置项的名称。 + /// 指定的游戏配置项是否存在。 + public override bool HasSetting(string settingName) + { + return m_Settings.HasSetting(settingName); + } + + /// + /// 移除指定游戏配置项。 + /// + /// 要移除游戏配置项的名称。 + /// 是否移除指定游戏配置项成功。 + public override bool RemoveSetting(string settingName) + { + return m_Settings.RemoveSetting(settingName); + } + + /// + /// 清空所有游戏配置项。 + /// + public override void RemoveAllSettings() + { + m_Settings.RemoveAllSettings(); + } + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的布尔值。 + public override bool GetBool(string settingName) + { + return m_Settings.GetBool(settingName); + } + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的布尔值。 + public override bool GetBool(string settingName, bool defaultValue) + { + return m_Settings.GetBool(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入布尔值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的布尔值。 + public override void SetBool(string settingName, bool value) + { + m_Settings.SetBool(settingName, value); + } + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的整数值。 + public override int GetInt(string settingName) + { + return m_Settings.GetInt(settingName); + } + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的整数值。 + public override int GetInt(string settingName, int defaultValue) + { + return m_Settings.GetInt(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入整数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的整数值。 + public override void SetInt(string settingName, int value) + { + m_Settings.SetInt(settingName, value); + } + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的浮点数值。 + public override float GetFloat(string settingName) + { + return m_Settings.GetFloat(settingName); + } + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的浮点数值。 + public override float GetFloat(string settingName, float defaultValue) + { + return m_Settings.GetFloat(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入浮点数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的浮点数值。 + public override void SetFloat(string settingName, float value) + { + m_Settings.SetFloat(settingName, value); + } + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的字符串值。 + public override string GetString(string settingName) + { + return m_Settings.GetString(settingName); + } + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的字符串值。 + public override string GetString(string settingName, string defaultValue) + { + return m_Settings.GetString(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入字符串值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的字符串值。 + public override void SetString(string settingName, string value) + { + m_Settings.SetString(settingName, value); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + public override T GetObject(string settingName) + { + return Utility.Json.ToObject(GetString(settingName)); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + public override object GetObject(Type objectType, string settingName) + { + return Utility.Json.ToObject(objectType, GetString(settingName)); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + public override T GetObject(string settingName, T defaultObj) + { + string json = GetString(settingName, null); + if (json == null) + { + return defaultObj; + } + + return Utility.Json.ToObject(json); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + public override object GetObject(Type objectType, string settingName, object defaultObj) + { + string json = GetString(settingName, null); + if (json == null) + { + return defaultObj; + } + + return Utility.Json.ToObject(objectType, json); + } + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入对象的类型。 + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + public override void SetObject(string settingName, T obj) + { + SetString(settingName, Utility.Json.ToJson(obj)); + } + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + public override void SetObject(string settingName, object obj) + { + SetString(settingName, Utility.Json.ToJson(obj)); + } + + private void Awake() + { + m_FilePath = Utility.Path.GetRegularPath(Path.Combine(Application.persistentDataPath, SettingFileName)); + m_Settings = new DefaultSetting(); + m_Serializer = new DefaultSettingSerializer(); + m_Serializer.RegisterSerializeCallback(0, SerializeDefaultSettingCallback); + m_Serializer.RegisterDeserializeCallback(0, DeserializeDefaultSettingCallback); + } + + private bool SerializeDefaultSettingCallback(Stream stream, DefaultSetting defaultSetting) + { + m_Settings.Serialize(stream); + return true; + } + + private DefaultSetting DeserializeDefaultSettingCallback(Stream stream) + { + m_Settings.Deserialize(stream); + return m_Settings; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSettingHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSettingHelper.cs.meta new file mode 100644 index 0000000..3b0363c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSettingHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 43823f1cc63fb3b49a5659ca1e8a9628 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSettingSerializer.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSettingSerializer.cs new file mode 100644 index 0000000..6df6902 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSettingSerializer.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认游戏配置序列化器。 + /// + public sealed class DefaultSettingSerializer : GameFrameworkSerializer + { + private static readonly byte[] Header = new byte[] { (byte)'G', (byte)'F', (byte)'S' }; + + /// + /// 初始化默认游戏配置序列化器的新实例。 + /// + public DefaultSettingSerializer() + { + } + + /// + /// 获取默认游戏配置头标识。 + /// + /// 默认游戏配置头标识。 + protected override byte[] GetHeader() + { + return Header; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSettingSerializer.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSettingSerializer.cs.meta new file mode 100644 index 0000000..43089c3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/DefaultSettingSerializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 68480f1e51ccec64eb66a1da9bd5cc99 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/PlayerPrefsSettingHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/PlayerPrefsSettingHelper.cs new file mode 100644 index 0000000..feb8925 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/PlayerPrefsSettingHelper.cs @@ -0,0 +1,312 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// PlayerPrefs 游戏配置辅助器。 + /// + public class PlayerPrefsSettingHelper : SettingHelperBase + { + /// + /// 获取游戏配置项数量。 + /// + public override int Count + { + get + { + return -1; + } + } + + /// + /// 加载游戏配置。 + /// + /// 是否加载游戏配置成功。 + public override bool Load() + { + return true; + } + + /// + /// 保存游戏配置。 + /// + /// 是否保存游戏配置成功。 + public override bool Save() + { + PlayerPrefs.Save(); + return true; + } + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + public override string[] GetAllSettingNames() + { + Log.Warning("GetAllSettingNames is not supported."); + return null; + } + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + public override void GetAllSettingNames(List results) + { + if (results == null) + { + throw new GameFrameworkException("Results is invalid."); + } + + results.Clear(); + Log.Warning("GetAllSettingNames is not supported."); + } + + /// + /// 检查是否存在指定游戏配置项。 + /// + /// 要检查游戏配置项的名称。 + /// 指定的游戏配置项是否存在。 + public override bool HasSetting(string settingName) + { + return PlayerPrefs.HasKey(settingName); + } + + /// + /// 移除指定游戏配置项。 + /// + /// 要移除游戏配置项的名称。 + /// 是否移除指定游戏配置项成功。 + public override bool RemoveSetting(string settingName) + { + if (!PlayerPrefs.HasKey(settingName)) + { + return false; + } + + PlayerPrefs.DeleteKey(settingName); + return true; + } + + /// + /// 清空所有游戏配置项。 + /// + public override void RemoveAllSettings() + { + PlayerPrefs.DeleteAll(); + } + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的布尔值。 + public override bool GetBool(string settingName) + { + return PlayerPrefs.GetInt(settingName) != 0; + } + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的布尔值。 + public override bool GetBool(string settingName, bool defaultValue) + { + return PlayerPrefs.GetInt(settingName, defaultValue ? 1 : 0) != 0; + } + + /// + /// 向指定游戏配置项写入布尔值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的布尔值。 + public override void SetBool(string settingName, bool value) + { + PlayerPrefs.SetInt(settingName, value ? 1 : 0); + } + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的整数值。 + public override int GetInt(string settingName) + { + return PlayerPrefs.GetInt(settingName); + } + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的整数值。 + public override int GetInt(string settingName, int defaultValue) + { + return PlayerPrefs.GetInt(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入整数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的整数值。 + public override void SetInt(string settingName, int value) + { + PlayerPrefs.SetInt(settingName, value); + } + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的浮点数值。 + public override float GetFloat(string settingName) + { + return PlayerPrefs.GetFloat(settingName); + } + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的浮点数值。 + public override float GetFloat(string settingName, float defaultValue) + { + return PlayerPrefs.GetFloat(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入浮点数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的浮点数值。 + public override void SetFloat(string settingName, float value) + { + PlayerPrefs.SetFloat(settingName, value); + } + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的字符串值。 + public override string GetString(string settingName) + { + return PlayerPrefs.GetString(settingName); + } + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的字符串值。 + public override string GetString(string settingName, string defaultValue) + { + return PlayerPrefs.GetString(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入字符串值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的字符串值。 + public override void SetString(string settingName, string value) + { + PlayerPrefs.SetString(settingName, value); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + public override T GetObject(string settingName) + { + return Utility.Json.ToObject(GetString(settingName)); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + public override object GetObject(Type objectType, string settingName) + { + return Utility.Json.ToObject(objectType, GetString(settingName)); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + public override T GetObject(string settingName, T defaultObj) + { + string json = GetString(settingName, null); + if (json == null) + { + return defaultObj; + } + + return Utility.Json.ToObject(json); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + public override object GetObject(Type objectType, string settingName, object defaultObj) + { + string json = GetString(settingName, null); + if (json == null) + { + return defaultObj; + } + + return Utility.Json.ToObject(objectType, json); + } + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入对象的类型。 + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + public override void SetObject(string settingName, T obj) + { + PlayerPrefs.SetString(settingName, Utility.Json.ToJson(obj)); + } + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + public override void SetObject(string settingName, object obj) + { + PlayerPrefs.SetString(settingName, Utility.Json.ToJson(obj)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/PlayerPrefsSettingHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/PlayerPrefsSettingHelper.cs.meta new file mode 100644 index 0000000..f8ad200 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/PlayerPrefsSettingHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a1323525062529f4b93e412ebda4914a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/SettingComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/SettingComponent.cs new file mode 100644 index 0000000..43fcc59 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/SettingComponent.cs @@ -0,0 +1,323 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Setting; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 游戏配置组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Setting")] + public sealed class SettingComponent : GameFrameworkComponent + { + private ISettingManager m_SettingManager = null; + + [SerializeField] + private string m_SettingHelperTypeName = "UnityGameFramework.Runtime.DefaultSettingHelper"; + + [SerializeField] + private SettingHelperBase m_CustomSettingHelper = null; + + /// + /// 获取游戏配置项数量。 + /// + public int Count + { + get + { + return m_SettingManager.Count; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_SettingManager = GameFrameworkEntry.GetModule(); + if (m_SettingManager == null) + { + Log.Fatal("Setting manager is invalid."); + return; + } + + SettingHelperBase settingHelper = Helper.CreateHelper(m_SettingHelperTypeName, m_CustomSettingHelper); + if (settingHelper == null) + { + Log.Error("Can not create setting helper."); + return; + } + + settingHelper.name = "Setting Helper"; + Transform transform = settingHelper.transform; + transform.SetParent(this.transform); + transform.localScale = Vector3.one; + + m_SettingManager.SetSettingHelper(settingHelper); + } + + private void Start() + { + if (!m_SettingManager.Load()) + { + Log.Error("Load settings failure."); + } + } + + /// + /// 保存游戏配置。 + /// + public void Save() + { + m_SettingManager.Save(); + } + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + public string[] GetAllSettingNames() + { + return m_SettingManager.GetAllSettingNames(); + } + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + public void GetAllSettingNames(List results) + { + m_SettingManager.GetAllSettingNames(results); + } + + /// + /// 检查是否存在指定游戏配置项。 + /// + /// 要检查游戏配置项的名称。 + /// 指定的游戏配置项是否存在。 + public bool HasSetting(string settingName) + { + return m_SettingManager.HasSetting(settingName); + } + + /// + /// 移除指定游戏配置项。 + /// + /// 要移除游戏配置项的名称。 + public void RemoveSetting(string settingName) + { + m_SettingManager.RemoveSetting(settingName); + } + + /// + /// 清空所有游戏配置项。 + /// + public void RemoveAllSettings() + { + m_SettingManager.RemoveAllSettings(); + } + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的布尔值。 + public bool GetBool(string settingName) + { + return m_SettingManager.GetBool(settingName); + } + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的布尔值。 + public bool GetBool(string settingName, bool defaultValue) + { + return m_SettingManager.GetBool(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入布尔值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的布尔值。 + public void SetBool(string settingName, bool value) + { + m_SettingManager.SetBool(settingName, value); + } + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的整数值。 + public int GetInt(string settingName) + { + return m_SettingManager.GetInt(settingName); + } + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的整数值。 + public int GetInt(string settingName, int defaultValue) + { + return m_SettingManager.GetInt(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入整数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的整数值。 + public void SetInt(string settingName, int value) + { + m_SettingManager.SetInt(settingName, value); + } + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的浮点数值。 + public float GetFloat(string settingName) + { + return m_SettingManager.GetFloat(settingName); + } + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的浮点数值。 + public float GetFloat(string settingName, float defaultValue) + { + return m_SettingManager.GetFloat(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入浮点数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的浮点数值。 + public void SetFloat(string settingName, float value) + { + m_SettingManager.SetFloat(settingName, value); + } + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的字符串值。 + public string GetString(string settingName) + { + return m_SettingManager.GetString(settingName); + } + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的字符串值。 + public string GetString(string settingName, string defaultValue) + { + return m_SettingManager.GetString(settingName, defaultValue); + } + + /// + /// 向指定游戏配置项写入字符串值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的字符串值。 + public void SetString(string settingName, string value) + { + m_SettingManager.SetString(settingName, value); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + public T GetObject(string settingName) + { + return m_SettingManager.GetObject(settingName); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + public object GetObject(Type objectType, string settingName) + { + return m_SettingManager.GetObject(objectType, settingName); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + public T GetObject(string settingName, T defaultObj) + { + return m_SettingManager.GetObject(settingName, defaultObj); + } + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + public object GetObject(Type objectType, string settingName, object defaultObj) + { + return m_SettingManager.GetObject(objectType, settingName, defaultObj); + } + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入对象的类型。 + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + public void SetObject(string settingName, T obj) + { + m_SettingManager.SetObject(settingName, obj); + } + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + public void SetObject(string settingName, object obj) + { + m_SettingManager.SetObject(settingName, obj); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/SettingComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/SettingComponent.cs.meta new file mode 100644 index 0000000..06c91a0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/SettingComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3c6e05d8d843cd94bb9aa026ed5dc517 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/SettingHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/SettingHelperBase.cs new file mode 100644 index 0000000..dba6d19 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/SettingHelperBase.cs @@ -0,0 +1,208 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Setting; +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 游戏配置辅助器基类。 + /// + public abstract class SettingHelperBase : MonoBehaviour, ISettingHelper + { + /// + /// 获取游戏配置项数量。 + /// + public abstract int Count + { + get; + } + + /// + /// 加载游戏配置。 + /// + /// 是否加载游戏配置成功。 + public abstract bool Load(); + + /// + /// 保存游戏配置。 + /// + /// 是否保存游戏配置成功。 + public abstract bool Save(); + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + public abstract string[] GetAllSettingNames(); + + /// + /// 获取所有游戏配置项的名称。 + /// + /// 所有游戏配置项的名称。 + public abstract void GetAllSettingNames(List results); + + /// + /// 检查是否存在指定游戏配置项。 + /// + /// 要检查游戏配置项的名称。 + /// 指定的游戏配置项是否存在。 + public abstract bool HasSetting(string settingName); + + /// + /// 移除指定游戏配置项。 + /// + /// 要移除游戏配置项的名称。 + /// 是否移除指定游戏配置项成功。 + public abstract bool RemoveSetting(string settingName); + + /// + /// 清空所有游戏配置项。 + /// + public abstract void RemoveAllSettings(); + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的布尔值。 + public abstract bool GetBool(string settingName); + + /// + /// 从指定游戏配置项中读取布尔值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的布尔值。 + public abstract bool GetBool(string settingName, bool defaultValue); + + /// + /// 向指定游戏配置项写入布尔值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的布尔值。 + public abstract void SetBool(string settingName, bool value); + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的整数值。 + public abstract int GetInt(string settingName); + + /// + /// 从指定游戏配置项中读取整数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的整数值。 + public abstract int GetInt(string settingName, int defaultValue); + + /// + /// 向指定游戏配置项写入整数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的整数值。 + public abstract void SetInt(string settingName, int value); + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的浮点数值。 + public abstract float GetFloat(string settingName); + + /// + /// 从指定游戏配置项中读取浮点数值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的浮点数值。 + public abstract float GetFloat(string settingName, float defaultValue); + + /// + /// 向指定游戏配置项写入浮点数值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的浮点数值。 + public abstract void SetFloat(string settingName, float value); + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 读取的字符串值。 + public abstract string GetString(string settingName); + + /// + /// 从指定游戏配置项中读取字符串值。 + /// + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认值。 + /// 读取的字符串值。 + public abstract string GetString(string settingName, string defaultValue); + + /// + /// 向指定游戏配置项写入字符串值。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的字符串值。 + public abstract void SetString(string settingName, string value); + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + public abstract T GetObject(string settingName); + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 读取的对象。 + public abstract object GetObject(Type objectType, string settingName); + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + public abstract T GetObject(string settingName, T defaultObj); + + /// + /// 从指定游戏配置项中读取对象。 + /// + /// 要读取对象的类型。 + /// 要获取游戏配置项的名称。 + /// 当指定的游戏配置项不存在时,返回此默认对象。 + /// 读取的对象。 + public abstract object GetObject(Type objectType, string settingName, object defaultObj); + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入对象的类型。 + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + public abstract void SetObject(string settingName, T obj); + + /// + /// 向指定游戏配置项写入对象。 + /// + /// 要写入游戏配置项的名称。 + /// 要写入的对象。 + public abstract void SetObject(string settingName, object obj); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/SettingHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/SettingHelperBase.cs.meta new file mode 100644 index 0000000..723752a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Setting/SettingHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cc7b39fb83dd08d46b2920dfbe6c4ca0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound.meta new file mode 100644 index 0000000..7672fc7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 633ea9a10bc00b44da15448d15f14ce1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundAgentHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundAgentHelper.cs new file mode 100644 index 0000000..ea4153d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundAgentHelper.cs @@ -0,0 +1,434 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Sound; +using System; +using System.Collections; +using UnityEngine; +using UnityEngine.Audio; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认声音代理辅助器。 + /// + public class DefaultSoundAgentHelper : SoundAgentHelperBase + { + private Transform m_CachedTransform = null; + private AudioSource m_AudioSource = null; + private EntityLogic m_BindingEntityLogic = null; + private float m_VolumeWhenPause = 0f; + private bool m_ApplicationPauseFlag = false; + private EventHandler m_ResetSoundAgentEventHandler = null; + + /// + /// 获取当前是否正在播放。 + /// + public override bool IsPlaying + { + get + { + return m_AudioSource.isPlaying; + } + } + + /// + /// 获取声音长度。 + /// + public override float Length + { + get + { + return m_AudioSource.clip != null ? m_AudioSource.clip.length : 0f; + } + } + + /// + /// 获取或设置播放位置。 + /// + public override float Time + { + get + { + return m_AudioSource.time; + } + set + { + m_AudioSource.time = value; + } + } + + /// + /// 获取或设置是否静音。 + /// + public override bool Mute + { + get + { + return m_AudioSource.mute; + } + set + { + m_AudioSource.mute = value; + } + } + + /// + /// 获取或设置是否循环播放。 + /// + public override bool Loop + { + get + { + return m_AudioSource.loop; + } + set + { + m_AudioSource.loop = value; + } + } + + /// + /// 获取或设置声音优先级。 + /// + public override int Priority + { + get + { + return 128 - m_AudioSource.priority; + } + set + { + m_AudioSource.priority = 128 - value; + } + } + + /// + /// 获取或设置音量大小。 + /// + public override float Volume + { + get + { + return m_AudioSource.volume; + } + set + { + m_AudioSource.volume = value; + } + } + + /// + /// 获取或设置声音音调。 + /// + public override float Pitch + { + get + { + return m_AudioSource.pitch; + } + set + { + m_AudioSource.pitch = value; + } + } + + /// + /// 获取或设置声音立体声声相。 + /// + public override float PanStereo + { + get + { + return m_AudioSource.panStereo; + } + set + { + m_AudioSource.panStereo = value; + } + } + + /// + /// 获取或设置声音空间混合量。 + /// + public override float SpatialBlend + { + get + { + return m_AudioSource.spatialBlend; + } + set + { + m_AudioSource.spatialBlend = value; + } + } + + /// + /// 获取或设置声音最大距离。 + /// + public override float MaxDistance + { + get + { + return m_AudioSource.maxDistance; + } + + set + { + m_AudioSource.maxDistance = value; + } + } + + /// + /// 获取或设置声音多普勒等级。 + /// + public override float DopplerLevel + { + get + { + return m_AudioSource.dopplerLevel; + } + set + { + m_AudioSource.dopplerLevel = value; + } + } + + /// + /// 获取或设置声音代理辅助器所在的混音组。 + /// + public override AudioMixerGroup AudioMixerGroup + { + get + { + return m_AudioSource.outputAudioMixerGroup; + } + set + { + m_AudioSource.outputAudioMixerGroup = value; + } + } + + /// + /// 重置声音代理事件。 + /// + public override event EventHandler ResetSoundAgent + { + add + { + m_ResetSoundAgentEventHandler += value; + } + remove + { + m_ResetSoundAgentEventHandler -= value; + } + } + + /// + /// 播放声音。 + /// + /// 声音淡入时间,以秒为单位。 + public override void Play(float fadeInSeconds) + { + StopAllCoroutines(); + + m_AudioSource.Play(); + if (fadeInSeconds > 0f) + { + float volume = m_AudioSource.volume; + m_AudioSource.volume = 0f; + StartCoroutine(FadeToVolume(m_AudioSource, volume, fadeInSeconds)); + } + } + + /// + /// 停止播放声音。 + /// + /// 声音淡出时间,以秒为单位。 + public override void Stop(float fadeOutSeconds) + { + StopAllCoroutines(); + + if (fadeOutSeconds > 0f && gameObject.activeInHierarchy) + { + StartCoroutine(StopCo(fadeOutSeconds)); + } + else + { + m_AudioSource.Stop(); + } + } + + /// + /// 暂停播放声音。 + /// + /// 声音淡出时间,以秒为单位。 + public override void Pause(float fadeOutSeconds) + { + StopAllCoroutines(); + + m_VolumeWhenPause = m_AudioSource.volume; + if (fadeOutSeconds > 0f && gameObject.activeInHierarchy) + { + StartCoroutine(PauseCo(fadeOutSeconds)); + } + else + { + m_AudioSource.Pause(); + } + } + + /// + /// 恢复播放声音。 + /// + /// 声音淡入时间,以秒为单位。 + public override void Resume(float fadeInSeconds) + { + StopAllCoroutines(); + + m_AudioSource.UnPause(); + if (fadeInSeconds > 0f) + { + StartCoroutine(FadeToVolume(m_AudioSource, m_VolumeWhenPause, fadeInSeconds)); + } + else + { + m_AudioSource.volume = m_VolumeWhenPause; + } + } + + /// + /// 重置声音代理辅助器。 + /// + public override void Reset() + { + m_CachedTransform.localPosition = Vector3.zero; + m_AudioSource.clip = null; + m_BindingEntityLogic = null; + m_VolumeWhenPause = 0f; + } + + /// + /// 设置声音资源。 + /// + /// 声音资源。 + /// 是否设置声音资源成功。 + public override bool SetSoundAsset(object soundAsset) + { + AudioClip audioClip = soundAsset as AudioClip; + if (audioClip == null) + { + return false; + } + + m_AudioSource.clip = audioClip; + return true; + } + + /// + /// 设置声音绑定的实体。 + /// + /// 声音绑定的实体。 + public override void SetBindingEntity(Entity bindingEntity) + { + m_BindingEntityLogic = bindingEntity.Logic; + if (m_BindingEntityLogic != null) + { + UpdateAgentPosition(); + return; + } + + if (m_ResetSoundAgentEventHandler != null) + { + ResetSoundAgentEventArgs resetSoundAgentEventArgs = ResetSoundAgentEventArgs.Create(); + m_ResetSoundAgentEventHandler(this, resetSoundAgentEventArgs); + ReferencePool.Release(resetSoundAgentEventArgs); + } + } + + /// + /// 设置声音所在的世界坐标。 + /// + /// 声音所在的世界坐标。 + public override void SetWorldPosition(Vector3 worldPosition) + { + m_CachedTransform.position = worldPosition; + } + + private void Awake() + { + m_CachedTransform = transform; + m_AudioSource = gameObject.GetOrAddComponent(); + m_AudioSource.playOnAwake = false; + m_AudioSource.rolloffMode = AudioRolloffMode.Custom; + } + + private void Update() + { + if (!m_ApplicationPauseFlag && !IsPlaying && m_AudioSource.clip != null && m_ResetSoundAgentEventHandler != null) + { + ResetSoundAgentEventArgs resetSoundAgentEventArgs = ResetSoundAgentEventArgs.Create(); + m_ResetSoundAgentEventHandler(this, resetSoundAgentEventArgs); + ReferencePool.Release(resetSoundAgentEventArgs); + return; + } + + if (m_BindingEntityLogic != null) + { + UpdateAgentPosition(); + } + } + + private void OnApplicationPause(bool pause) + { + m_ApplicationPauseFlag = pause; + } + + private void UpdateAgentPosition() + { + if (m_BindingEntityLogic.Available) + { + m_CachedTransform.position = m_BindingEntityLogic.CachedTransform.position; + return; + } + + if (m_ResetSoundAgentEventHandler != null) + { + ResetSoundAgentEventArgs resetSoundAgentEventArgs = ResetSoundAgentEventArgs.Create(); + m_ResetSoundAgentEventHandler(this, resetSoundAgentEventArgs); + ReferencePool.Release(resetSoundAgentEventArgs); + } + } + + private IEnumerator StopCo(float fadeOutSeconds) + { + yield return FadeToVolume(m_AudioSource, 0f, fadeOutSeconds); + m_AudioSource.Stop(); + } + + private IEnumerator PauseCo(float fadeOutSeconds) + { + yield return FadeToVolume(m_AudioSource, 0f, fadeOutSeconds); + m_AudioSource.Pause(); + } + + private IEnumerator FadeToVolume(AudioSource audioSource, float volume, float duration) + { + float time = 0f; + float originalVolume = audioSource.volume; + while (time < duration) + { + time += UnityEngine.Time.deltaTime; + audioSource.volume = Mathf.Lerp(originalVolume, volume, time / duration); + yield return new WaitForEndOfFrame(); + } + + audioSource.volume = volume; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundAgentHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundAgentHelper.cs.meta new file mode 100644 index 0000000..858633a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundAgentHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3e41f05fd242c0d4fb2a5bd81ccca27c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundGroupHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundGroupHelper.cs new file mode 100644 index 0000000..c471fe0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundGroupHelper.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认声音组辅助器。 + /// + public class DefaultSoundGroupHelper : SoundGroupHelperBase + { + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundGroupHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundGroupHelper.cs.meta new file mode 100644 index 0000000..0415cc1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundGroupHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d3b0f546449448c488d755cee4d701d2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundHelper.cs new file mode 100644 index 0000000..5fe0ad3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundHelper.cs @@ -0,0 +1,36 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认声音辅助器。 + /// + public class DefaultSoundHelper : SoundHelperBase + { + private ResourceComponent m_ResourceComponent = null; + + /// + /// 释放声音资源。 + /// + /// 要释放的声音资源。 + public override void ReleaseSoundAsset(object soundAsset) + { + m_ResourceComponent.UnloadAsset(soundAsset); + } + + private void Start() + { + m_ResourceComponent = GameEntry.GetComponent(); + if (m_ResourceComponent == null) + { + Log.Fatal("Resource component is invalid."); + return; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundHelper.cs.meta new file mode 100644 index 0000000..de77801 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/DefaultSoundHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7a025072340d72e4e8468db061720cde +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundDependencyAssetEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundDependencyAssetEventArgs.cs new file mode 100644 index 0000000..ce113fa --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundDependencyAssetEventArgs.cs @@ -0,0 +1,169 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using GameFramework.Sound; + +namespace UnityGameFramework.Runtime +{ + /// + /// 播放声音时加载依赖资源事件。 + /// + public sealed class PlaySoundDependencyAssetEventArgs : GameEventArgs + { + /// + /// 播放声音时加载依赖资源事件编号。 + /// + public static readonly int EventId = typeof(PlaySoundDependencyAssetEventArgs).GetHashCode(); + + /// + /// 初始化播放声音时加载依赖资源事件的新实例。 + /// + public PlaySoundDependencyAssetEventArgs() + { + SerialId = 0; + SoundAssetName = null; + SoundGroupName = null; + PlaySoundParams = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + BindingEntity = null; + UserData = null; + } + + /// + /// 获取播放声音时加载依赖资源事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取声音的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取声音资源名称。 + /// + public string SoundAssetName + { + get; + private set; + } + + /// + /// 获取声音组名称。 + /// + public string SoundGroupName + { + get; + private set; + } + + /// + /// 获取播放声音参数。 + /// + public PlaySoundParams PlaySoundParams + { + get; + private set; + } + + /// + /// 获取被加载的依赖资源名称。 + /// + public string DependencyAssetName + { + get; + private set; + } + + /// + /// 获取当前已加载依赖资源数量。 + /// + public int LoadedCount + { + get; + private set; + } + + /// + /// 获取总共加载依赖资源数量。 + /// + public int TotalCount + { + get; + private set; + } + + /// + /// 获取声音绑定的实体。 + /// + public Entity BindingEntity + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建播放声音时加载依赖资源事件。 + /// + /// 内部事件。 + /// 创建的播放声音时加载依赖资源事件。 + public static PlaySoundDependencyAssetEventArgs Create(GameFramework.Sound.PlaySoundDependencyAssetEventArgs e) + { + PlaySoundInfo playSoundInfo = (PlaySoundInfo)e.UserData; + PlaySoundDependencyAssetEventArgs playSoundDependencyAssetEventArgs = ReferencePool.Acquire(); + playSoundDependencyAssetEventArgs.SerialId = e.SerialId; + playSoundDependencyAssetEventArgs.SoundAssetName = e.SoundAssetName; + playSoundDependencyAssetEventArgs.SoundGroupName = e.SoundGroupName; + playSoundDependencyAssetEventArgs.PlaySoundParams = e.PlaySoundParams; + playSoundDependencyAssetEventArgs.DependencyAssetName = e.DependencyAssetName; + playSoundDependencyAssetEventArgs.LoadedCount = e.LoadedCount; + playSoundDependencyAssetEventArgs.TotalCount = e.TotalCount; + playSoundDependencyAssetEventArgs.BindingEntity = playSoundInfo.BindingEntity; + playSoundDependencyAssetEventArgs.UserData = playSoundInfo.UserData; + return playSoundDependencyAssetEventArgs; + } + + /// + /// 清理播放声音时加载依赖资源事件。 + /// + public override void Clear() + { + SerialId = 0; + SoundAssetName = null; + SoundGroupName = null; + PlaySoundParams = null; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + BindingEntity = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundDependencyAssetEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundDependencyAssetEventArgs.cs.meta new file mode 100644 index 0000000..ffdeb47 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundDependencyAssetEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 82bc0837101049b47bca9dc4c0dfadb2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundFailureEventArgs.cs new file mode 100644 index 0000000..ca40405 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundFailureEventArgs.cs @@ -0,0 +1,158 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using GameFramework.Sound; + +namespace UnityGameFramework.Runtime +{ + /// + /// 播放声音失败事件。 + /// + public sealed class PlaySoundFailureEventArgs : GameEventArgs + { + /// + /// 播放声音失败事件编号。 + /// + public static readonly int EventId = typeof(PlaySoundFailureEventArgs).GetHashCode(); + + /// + /// 初始化播放声音失败事件的新实例。 + /// + public PlaySoundFailureEventArgs() + { + SerialId = 0; + SoundAssetName = null; + SoundGroupName = null; + PlaySoundParams = null; + BindingEntity = null; + ErrorCode = 0; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取播放声音失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取声音的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取声音资源名称。 + /// + public string SoundAssetName + { + get; + private set; + } + + /// + /// 获取声音组名称。 + /// + public string SoundGroupName + { + get; + private set; + } + + /// + /// 获取播放声音参数。 + /// + public PlaySoundParams PlaySoundParams + { + get; + private set; + } + + /// + /// 获取声音绑定的实体。 + /// + public Entity BindingEntity + { + get; + private set; + } + + /// + /// 获取错误码。 + /// + public PlaySoundErrorCode ErrorCode + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建播放声音失败事件。 + /// + /// 内部事件。 + /// 创建的播放声音失败事件。 + public static PlaySoundFailureEventArgs Create(GameFramework.Sound.PlaySoundFailureEventArgs e) + { + PlaySoundInfo playSoundInfo = (PlaySoundInfo)e.UserData; + PlaySoundFailureEventArgs playSoundFailureEventArgs = ReferencePool.Acquire(); + playSoundFailureEventArgs.SerialId = e.SerialId; + playSoundFailureEventArgs.SoundAssetName = e.SoundAssetName; + playSoundFailureEventArgs.SoundGroupName = e.SoundGroupName; + playSoundFailureEventArgs.PlaySoundParams = e.PlaySoundParams; + playSoundFailureEventArgs.BindingEntity = playSoundInfo.BindingEntity; + playSoundFailureEventArgs.ErrorCode = e.ErrorCode; + playSoundFailureEventArgs.ErrorMessage = e.ErrorMessage; + playSoundFailureEventArgs.UserData = playSoundInfo.UserData; + ReferencePool.Release(playSoundInfo); + return playSoundFailureEventArgs; + } + + /// + /// 清理播放声音失败事件。 + /// + public override void Clear() + { + SerialId = 0; + SoundAssetName = null; + SoundGroupName = null; + PlaySoundParams = null; + BindingEntity = null; + ErrorCode = 0; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundFailureEventArgs.cs.meta new file mode 100644 index 0000000..f7b5d1d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e72fc153d76f6e04e9b0036f95f75b3c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundInfo.cs new file mode 100644 index 0000000..76f7ced --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundInfo.cs @@ -0,0 +1,66 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + internal sealed class PlaySoundInfo : IReference + { + private Entity m_BindingEntity; + private Vector3 m_WorldPosition; + private object m_UserData; + + public PlaySoundInfo() + { + m_BindingEntity = null; + m_WorldPosition = Vector3.zero; + m_UserData = null; + } + + public Entity BindingEntity + { + get + { + return m_BindingEntity; + } + } + + public Vector3 WorldPosition + { + get + { + return m_WorldPosition; + } + } + + public object UserData + { + get + { + return m_UserData; + } + } + + public static PlaySoundInfo Create(Entity bindingEntity, Vector3 worldPosition, object userData) + { + PlaySoundInfo playSoundInfo = ReferencePool.Acquire(); + playSoundInfo.m_BindingEntity = bindingEntity; + playSoundInfo.m_WorldPosition = worldPosition; + playSoundInfo.m_UserData = userData; + return playSoundInfo; + } + + public void Clear() + { + m_BindingEntity = null; + m_WorldPosition = Vector3.zero; + m_UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundInfo.cs.meta new file mode 100644 index 0000000..d0c67c6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7b0ac4f756eac174ba485dae0218a1a8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundSuccessEventArgs.cs new file mode 100644 index 0000000..2e39bc9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundSuccessEventArgs.cs @@ -0,0 +1,134 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using GameFramework.Sound; + +namespace UnityGameFramework.Runtime +{ + /// + /// 播放声音成功事件。 + /// + public sealed class PlaySoundSuccessEventArgs : GameEventArgs + { + /// + /// 播放声音成功事件编号。 + /// + public static readonly int EventId = typeof(PlaySoundSuccessEventArgs).GetHashCode(); + + /// + /// 初始化播放声音成功事件的新实例。 + /// + public PlaySoundSuccessEventArgs() + { + SerialId = 0; + SoundAssetName = null; + SoundAgent = null; + Duration = 0f; + BindingEntity = null; + UserData = null; + } + + /// + /// 获取播放声音成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取声音的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取声音资源名称。 + /// + public string SoundAssetName + { + get; + private set; + } + + /// + /// 获取用于播放的声音代理。 + /// + public ISoundAgent SoundAgent + { + get; + private set; + } + + /// + /// 获取加载持续时间。 + /// + public float Duration + { + get; + private set; + } + + /// + /// 获取声音绑定的实体。 + /// + public Entity BindingEntity + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建播放声音成功事件。 + /// + /// 内部事件。 + /// 创建的播放声音成功事件。 + public static PlaySoundSuccessEventArgs Create(GameFramework.Sound.PlaySoundSuccessEventArgs e) + { + PlaySoundInfo playSoundInfo = (PlaySoundInfo)e.UserData; + PlaySoundSuccessEventArgs playSoundSuccessEventArgs = ReferencePool.Acquire(); + playSoundSuccessEventArgs.SerialId = e.SerialId; + playSoundSuccessEventArgs.SoundAssetName = e.SoundAssetName; + playSoundSuccessEventArgs.SoundAgent = e.SoundAgent; + playSoundSuccessEventArgs.Duration = e.Duration; + playSoundSuccessEventArgs.BindingEntity = playSoundInfo.BindingEntity; + playSoundSuccessEventArgs.UserData = playSoundInfo.UserData; + ReferencePool.Release(playSoundInfo); + return playSoundSuccessEventArgs; + } + + /// + /// 清理播放声音成功事件。 + /// + public override void Clear() + { + SerialId = 0; + SoundAssetName = null; + SoundAgent = null; + Duration = 0f; + BindingEntity = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundSuccessEventArgs.cs.meta new file mode 100644 index 0000000..c687fb3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3ba92a17225be4a41a9824d08651692f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundUpdateEventArgs.cs new file mode 100644 index 0000000..35697ea --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundUpdateEventArgs.cs @@ -0,0 +1,145 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using GameFramework.Sound; + +namespace UnityGameFramework.Runtime +{ + /// + /// 播放声音更新事件。 + /// + public sealed class PlaySoundUpdateEventArgs : GameEventArgs + { + /// + /// 播放声音更新事件编号。 + /// + public static readonly int EventId = typeof(PlaySoundUpdateEventArgs).GetHashCode(); + + /// + /// 初始化播放声音更新事件的新实例。 + /// + public PlaySoundUpdateEventArgs() + { + SerialId = 0; + SoundAssetName = null; + SoundGroupName = null; + PlaySoundParams = null; + Progress = 0f; + BindingEntity = null; + UserData = null; + } + + /// + /// 获取播放声音更新事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取声音的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取声音资源名称。 + /// + public string SoundAssetName + { + get; + private set; + } + + /// + /// 获取声音组名称。 + /// + public string SoundGroupName + { + get; + private set; + } + + /// + /// 获取播放声音参数。 + /// + public PlaySoundParams PlaySoundParams + { + get; + private set; + } + + /// + /// 获取加载声音进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 获取声音绑定的实体。 + /// + public Entity BindingEntity + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建播放声音更新事件。 + /// + /// 内部事件。 + /// 创建的播放声音更新事件。 + public static PlaySoundUpdateEventArgs Create(GameFramework.Sound.PlaySoundUpdateEventArgs e) + { + PlaySoundInfo playSoundInfo = (PlaySoundInfo)e.UserData; + PlaySoundUpdateEventArgs playSoundUpdateEventArgs = ReferencePool.Acquire(); + playSoundUpdateEventArgs.SerialId = e.SerialId; + playSoundUpdateEventArgs.SoundAssetName = e.SoundAssetName; + playSoundUpdateEventArgs.SoundGroupName = e.SoundGroupName; + playSoundUpdateEventArgs.PlaySoundParams = e.PlaySoundParams; + playSoundUpdateEventArgs.Progress = e.Progress; + playSoundUpdateEventArgs.BindingEntity = playSoundInfo.BindingEntity; + playSoundUpdateEventArgs.UserData = playSoundInfo.UserData; + return playSoundUpdateEventArgs; + } + + /// + /// 清理播放声音更新事件。 + /// + public override void Clear() + { + SerialId = 0; + SoundAssetName = null; + SoundGroupName = null; + PlaySoundParams = null; + Progress = 0f; + BindingEntity = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundUpdateEventArgs.cs.meta new file mode 100644 index 0000000..99030a3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/PlaySoundUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: edad8ee73e896ab4cb00c9d37667699d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundAgentHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundAgentHelperBase.cs new file mode 100644 index 0000000..4cae2f5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundAgentHelperBase.cs @@ -0,0 +1,188 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Sound; +using System; +using UnityEngine; +using UnityEngine.Audio; + +namespace UnityGameFramework.Runtime +{ + /// + /// 声音代理辅助器基类。 + /// + public abstract class SoundAgentHelperBase : MonoBehaviour, ISoundAgentHelper + { + /// + /// 获取当前是否正在播放。 + /// + public abstract bool IsPlaying + { + get; + } + + /// + /// 获取声音长度。 + /// + public abstract float Length + { + get; + } + + /// + /// 获取或设置播放位置。 + /// + public abstract float Time + { + get; + set; + } + + /// + /// 获取或设置是否静音。 + /// + public abstract bool Mute + { + get; + set; + } + + /// + /// 获取或设置是否循环播放。 + /// + public abstract bool Loop + { + get; + set; + } + + /// + /// 获取或设置声音优先级。 + /// + public abstract int Priority + { + get; + set; + } + + /// + /// 获取或设置音量大小。 + /// + public abstract float Volume + { + get; + set; + } + + /// + /// 获取或设置声音音调。 + /// + public abstract float Pitch + { + get; + set; + } + + /// + /// 获取或设置声音立体声声相。 + /// + public abstract float PanStereo + { + get; + set; + } + + /// + /// 获取或设置声音空间混合量。 + /// + public abstract float SpatialBlend + { + get; + set; + } + + /// + /// 获取或设置声音最大距离。 + /// + public abstract float MaxDistance + { + get; + set; + } + + /// + /// 获取或设置声音多普勒等级。 + /// + public abstract float DopplerLevel + { + get; + set; + } + + /// + /// 获取或设置声音代理辅助器所在的混音组。 + /// + public abstract AudioMixerGroup AudioMixerGroup + { + get; + set; + } + + /// + /// 重置声音代理事件。 + /// + public abstract event EventHandler ResetSoundAgent; + + /// + /// 播放声音。 + /// + /// 声音淡入时间,以秒为单位。 + public abstract void Play(float fadeInSeconds); + + /// + /// 停止播放声音。 + /// + /// 声音淡出时间,以秒为单位。 + public abstract void Stop(float fadeOutSeconds); + + /// + /// 暂停播放声音。 + /// + /// 声音淡出时间,以秒为单位。 + public abstract void Pause(float fadeOutSeconds); + + /// + /// 恢复播放声音。 + /// + /// 声音淡入时间,以秒为单位。 + public abstract void Resume(float fadeInSeconds); + + /// + /// 重置声音代理辅助器。 + /// + public abstract void Reset(); + + /// + /// 设置声音资源。 + /// + /// 声音资源。 + /// 是否设置声音资源成功。 + public abstract bool SetSoundAsset(object soundAsset); + + /// + /// 设置声音绑定的实体。 + /// + /// 声音绑定的实体。 + public abstract void SetBindingEntity(Entity bindingEntity); + + /// + /// 设置声音所在的世界坐标。 + /// + /// 声音所在的世界坐标。 + public abstract void SetWorldPosition(Vector3 worldPosition); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundAgentHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundAgentHelperBase.cs.meta new file mode 100644 index 0000000..4d8c507 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundAgentHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 67ec8ad22a10aae41a982dbdd607ceef +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundComponent.SoundGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundComponent.SoundGroup.cs new file mode 100644 index 0000000..a9ec6bf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundComponent.SoundGroup.cs @@ -0,0 +1,74 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class SoundComponent : GameFrameworkComponent + { + [Serializable] + private sealed class SoundGroup + { + [SerializeField] + private string m_Name = null; + + [SerializeField] + private bool m_AvoidBeingReplacedBySamePriority = false; + + [SerializeField] + private bool m_Mute = false; + + [SerializeField, Range(0f, 1f)] + private float m_Volume = 1f; + + [SerializeField] + private int m_AgentHelperCount = 1; + + public string Name + { + get + { + return m_Name; + } + } + + public bool AvoidBeingReplacedBySamePriority + { + get + { + return m_AvoidBeingReplacedBySamePriority; + } + } + + public bool Mute + { + get + { + return m_Mute; + } + } + + public float Volume + { + get + { + return m_Volume; + } + } + + public int AgentHelperCount + { + get + { + return m_AgentHelperCount; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundComponent.SoundGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundComponent.SoundGroup.cs.meta new file mode 100644 index 0000000..fa377b6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundComponent.SoundGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 50effaea047572b4fae5b3500f1fc109 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundComponent.cs new file mode 100644 index 0000000..fd24768 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundComponent.cs @@ -0,0 +1,692 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Resource; +#if UNITY_5_3 +using GameFramework.Scene; +#endif +using GameFramework.Sound; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Audio; +using UnityEngine.SceneManagement; + +namespace UnityGameFramework.Runtime +{ + /// + /// 声音组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Sound")] + public sealed partial class SoundComponent : GameFrameworkComponent + { + private const int DefaultPriority = 0; + + private ISoundManager m_SoundManager = null; + private EventComponent m_EventComponent = null; + private AudioListener m_AudioListener = null; + + [SerializeField] + private bool m_EnablePlaySoundUpdateEvent = false; + + [SerializeField] + private bool m_EnablePlaySoundDependencyAssetEvent = false; + + [SerializeField] + private Transform m_InstanceRoot = null; + + [SerializeField] + private AudioMixer m_AudioMixer = null; + + [SerializeField] + private string m_SoundHelperTypeName = "UnityGameFramework.Runtime.DefaultSoundHelper"; + + [SerializeField] + private SoundHelperBase m_CustomSoundHelper = null; + + [SerializeField] + private string m_SoundGroupHelperTypeName = "UnityGameFramework.Runtime.DefaultSoundGroupHelper"; + + [SerializeField] + private SoundGroupHelperBase m_CustomSoundGroupHelper = null; + + [SerializeField] + private string m_SoundAgentHelperTypeName = "UnityGameFramework.Runtime.DefaultSoundAgentHelper"; + + [SerializeField] + private SoundAgentHelperBase m_CustomSoundAgentHelper = null; + + [SerializeField] + private SoundGroup[] m_SoundGroups = null; + + /// + /// 获取声音组数量。 + /// + public int SoundGroupCount + { + get + { + return m_SoundManager.SoundGroupCount; + } + } + + /// + /// 获取声音混响器。 + /// + public AudioMixer AudioMixer + { + get + { + return m_AudioMixer; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_SoundManager = GameFrameworkEntry.GetModule(); + if (m_SoundManager == null) + { + Log.Fatal("Sound manager is invalid."); + return; + } + + m_SoundManager.PlaySoundSuccess += OnPlaySoundSuccess; + m_SoundManager.PlaySoundFailure += OnPlaySoundFailure; + + if (m_EnablePlaySoundUpdateEvent) + { + m_SoundManager.PlaySoundUpdate += OnPlaySoundUpdate; + } + + if (m_EnablePlaySoundDependencyAssetEvent) + { + m_SoundManager.PlaySoundDependencyAsset += OnPlaySoundDependencyAsset; + } + + m_AudioListener = gameObject.GetOrAddComponent(); + +#if UNITY_5_4_OR_NEWER + SceneManager.sceneLoaded += OnSceneLoaded; + SceneManager.sceneUnloaded += OnSceneUnloaded; +#else + ISceneManager sceneManager = GameFrameworkEntry.GetModule(); + if (sceneManager == null) + { + Log.Fatal("Scene manager is invalid."); + return; + } + + sceneManager.LoadSceneSuccess += OnLoadSceneSuccess; + sceneManager.LoadSceneFailure += OnLoadSceneFailure; + sceneManager.UnloadSceneSuccess += OnUnloadSceneSuccess; + sceneManager.UnloadSceneFailure += OnUnloadSceneFailure; +#endif + } + + private void Start() + { + BaseComponent baseComponent = GameEntry.GetComponent(); + if (baseComponent == null) + { + Log.Fatal("Base component is invalid."); + return; + } + + m_EventComponent = GameEntry.GetComponent(); + if (m_EventComponent == null) + { + Log.Fatal("Event component is invalid."); + return; + } + + if (baseComponent.EditorResourceMode) + { + m_SoundManager.SetResourceManager(baseComponent.EditorResourceHelper); + } + else + { + m_SoundManager.SetResourceManager(GameFrameworkEntry.GetModule()); + } + + SoundHelperBase soundHelper = Helper.CreateHelper(m_SoundHelperTypeName, m_CustomSoundHelper); + if (soundHelper == null) + { + Log.Error("Can not create sound helper."); + return; + } + + soundHelper.name = "Sound Helper"; + Transform transform = soundHelper.transform; + transform.SetParent(this.transform); + transform.localScale = Vector3.one; + + m_SoundManager.SetSoundHelper(soundHelper); + + if (m_InstanceRoot == null) + { + m_InstanceRoot = new GameObject("Sound Instances").transform; + m_InstanceRoot.SetParent(gameObject.transform); + m_InstanceRoot.localScale = Vector3.one; + } + + for (int i = 0; i < m_SoundGroups.Length; i++) + { + if (!AddSoundGroup(m_SoundGroups[i].Name, m_SoundGroups[i].AvoidBeingReplacedBySamePriority, m_SoundGroups[i].Mute, m_SoundGroups[i].Volume, m_SoundGroups[i].AgentHelperCount)) + { + Log.Warning("Add sound group '{0}' failure.", m_SoundGroups[i].Name); + continue; + } + } + } + + private void OnDestroy() + { +#if UNITY_5_4_OR_NEWER + SceneManager.sceneLoaded -= OnSceneLoaded; + SceneManager.sceneUnloaded -= OnSceneUnloaded; +#endif + } + + /// + /// 是否存在指定声音组。 + /// + /// 声音组名称。 + /// 指定声音组是否存在。 + public bool HasSoundGroup(string soundGroupName) + { + return m_SoundManager.HasSoundGroup(soundGroupName); + } + + /// + /// 获取指定声音组。 + /// + /// 声音组名称。 + /// 要获取的声音组。 + public ISoundGroup GetSoundGroup(string soundGroupName) + { + return m_SoundManager.GetSoundGroup(soundGroupName); + } + + /// + /// 获取所有声音组。 + /// + /// 所有声音组。 + public ISoundGroup[] GetAllSoundGroups() + { + return m_SoundManager.GetAllSoundGroups(); + } + + /// + /// 获取所有声音组。 + /// + /// 所有声音组。 + public void GetAllSoundGroups(List results) + { + m_SoundManager.GetAllSoundGroups(results); + } + + /// + /// 增加声音组。 + /// + /// 声音组名称。 + /// 声音代理辅助器数量。 + /// 是否增加声音组成功。 + public bool AddSoundGroup(string soundGroupName, int soundAgentHelperCount) + { + return AddSoundGroup(soundGroupName, false, false, 1f, soundAgentHelperCount); + } + + /// + /// 增加声音组。 + /// + /// 声音组名称。 + /// 声音组中的声音是否避免被同优先级声音替换。 + /// 声音组是否静音。 + /// 声音组音量。 + /// 声音代理辅助器数量。 + /// 是否增加声音组成功。 + public bool AddSoundGroup(string soundGroupName, bool soundGroupAvoidBeingReplacedBySamePriority, bool soundGroupMute, float soundGroupVolume, int soundAgentHelperCount) + { + if (m_SoundManager.HasSoundGroup(soundGroupName)) + { + return false; + } + + SoundGroupHelperBase soundGroupHelper = Helper.CreateHelper(m_SoundGroupHelperTypeName, m_CustomSoundGroupHelper, SoundGroupCount); + if (soundGroupHelper == null) + { + Log.Error("Can not create sound group helper."); + return false; + } + + soundGroupHelper.name = Utility.Text.Format("Sound Group - {0}", soundGroupName); + Transform transform = soundGroupHelper.transform; + transform.SetParent(m_InstanceRoot); + transform.localScale = Vector3.one; + + if (m_AudioMixer != null) + { + AudioMixerGroup[] audioMixerGroups = m_AudioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}", soundGroupName)); + if (audioMixerGroups.Length > 0) + { + soundGroupHelper.AudioMixerGroup = audioMixerGroups[0]; + } + else + { + soundGroupHelper.AudioMixerGroup = m_AudioMixer.FindMatchingGroups("Master")[0]; + } + } + + if (!m_SoundManager.AddSoundGroup(soundGroupName, soundGroupAvoidBeingReplacedBySamePriority, soundGroupMute, soundGroupVolume, soundGroupHelper)) + { + return false; + } + + for (int i = 0; i < soundAgentHelperCount; i++) + { + if (!AddSoundAgentHelper(soundGroupName, soundGroupHelper, i)) + { + return false; + } + } + + return true; + } + + /// + /// 获取所有正在加载声音的序列编号。 + /// + /// 所有正在加载声音的序列编号。 + public int[] GetAllLoadingSoundSerialIds() + { + return m_SoundManager.GetAllLoadingSoundSerialIds(); + } + + /// + /// 获取所有正在加载声音的序列编号。 + /// + /// 所有正在加载声音的序列编号。 + public void GetAllLoadingSoundSerialIds(List results) + { + m_SoundManager.GetAllLoadingSoundSerialIds(results); + } + + /// + /// 是否正在加载声音。 + /// + /// 声音序列编号。 + /// 是否正在加载声音。 + public bool IsLoadingSound(int serialId) + { + return m_SoundManager.IsLoadingSound(serialId); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName) + { + return PlaySound(soundAssetName, soundGroupName, DefaultPriority, null, null, null); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, int priority) + { + return PlaySound(soundAssetName, soundGroupName, priority, null, null, null); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 播放声音参数。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, PlaySoundParams playSoundParams) + { + return PlaySound(soundAssetName, soundGroupName, DefaultPriority, playSoundParams, null, null); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 声音绑定的实体。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, Entity bindingEntity) + { + return PlaySound(soundAssetName, soundGroupName, DefaultPriority, null, bindingEntity, null); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 声音所在的世界坐标。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, Vector3 worldPosition) + { + return PlaySound(soundAssetName, soundGroupName, DefaultPriority, null, worldPosition, null); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 用户自定义数据。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, object userData) + { + return PlaySound(soundAssetName, soundGroupName, DefaultPriority, null, null, userData); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 播放声音参数。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams) + { + return PlaySound(soundAssetName, soundGroupName, priority, playSoundParams, null, null); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 播放声音参数。 + /// 用户自定义数据。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams, object userData) + { + return PlaySound(soundAssetName, soundGroupName, priority, playSoundParams, null, userData); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 播放声音参数。 + /// 声音绑定的实体。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams, Entity bindingEntity) + { + return PlaySound(soundAssetName, soundGroupName, priority, playSoundParams, bindingEntity, null); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 播放声音参数。 + /// 声音绑定的实体。 + /// 用户自定义数据。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams, Entity bindingEntity, object userData) + { + return m_SoundManager.PlaySound(soundAssetName, soundGroupName, priority, playSoundParams, PlaySoundInfo.Create(bindingEntity, Vector3.zero, userData)); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 播放声音参数。 + /// 声音所在的世界坐标。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams, Vector3 worldPosition) + { + return PlaySound(soundAssetName, soundGroupName, priority, playSoundParams, worldPosition, null); + } + + /// + /// 播放声音。 + /// + /// 声音资源名称。 + /// 声音组名称。 + /// 加载声音资源的优先级。 + /// 播放声音参数。 + /// 声音所在的世界坐标。 + /// 用户自定义数据。 + /// 声音的序列编号。 + public int PlaySound(string soundAssetName, string soundGroupName, int priority, PlaySoundParams playSoundParams, Vector3 worldPosition, object userData) + { + return m_SoundManager.PlaySound(soundAssetName, soundGroupName, priority, playSoundParams, PlaySoundInfo.Create(null, worldPosition, userData)); + } + + /// + /// 停止播放声音。 + /// + /// 要停止播放声音的序列编号。 + /// 是否停止播放声音成功。 + public bool StopSound(int serialId) + { + return m_SoundManager.StopSound(serialId); + } + + /// + /// 停止播放声音。 + /// + /// 要停止播放声音的序列编号。 + /// 声音淡出时间,以秒为单位。 + /// 是否停止播放声音成功。 + public bool StopSound(int serialId, float fadeOutSeconds) + { + return m_SoundManager.StopSound(serialId, fadeOutSeconds); + } + + /// + /// 停止所有已加载的声音。 + /// + public void StopAllLoadedSounds() + { + m_SoundManager.StopAllLoadedSounds(); + } + + /// + /// 停止所有已加载的声音。 + /// + /// 声音淡出时间,以秒为单位。 + public void StopAllLoadedSounds(float fadeOutSeconds) + { + m_SoundManager.StopAllLoadedSounds(fadeOutSeconds); + } + + /// + /// 停止所有正在加载的声音。 + /// + public void StopAllLoadingSounds() + { + m_SoundManager.StopAllLoadingSounds(); + } + + /// + /// 暂停播放声音。 + /// + /// 要暂停播放声音的序列编号。 + public void PauseSound(int serialId) + { + m_SoundManager.PauseSound(serialId); + } + + /// + /// 暂停播放声音。 + /// + /// 要暂停播放声音的序列编号。 + /// 声音淡出时间,以秒为单位。 + public void PauseSound(int serialId, float fadeOutSeconds) + { + m_SoundManager.PauseSound(serialId, fadeOutSeconds); + } + + /// + /// 恢复播放声音。 + /// + /// 要恢复播放声音的序列编号。 + public void ResumeSound(int serialId) + { + m_SoundManager.ResumeSound(serialId); + } + + /// + /// 恢复播放声音。 + /// + /// 要恢复播放声音的序列编号。 + /// 声音淡入时间,以秒为单位。 + public void ResumeSound(int serialId, float fadeInSeconds) + { + m_SoundManager.ResumeSound(serialId, fadeInSeconds); + } + + /// + /// 增加声音代理辅助器。 + /// + /// 声音组名称。 + /// 声音组辅助器。 + /// 声音代理辅助器索引。 + /// 是否增加声音代理辅助器成功。 + private bool AddSoundAgentHelper(string soundGroupName, SoundGroupHelperBase soundGroupHelper, int index) + { + SoundAgentHelperBase soundAgentHelper = Helper.CreateHelper(m_SoundAgentHelperTypeName, m_CustomSoundAgentHelper, index); + if (soundAgentHelper == null) + { + Log.Error("Can not create sound agent helper."); + return false; + } + + soundAgentHelper.name = Utility.Text.Format("Sound Agent Helper - {0} - {1}", soundGroupName, index); + Transform transform = soundAgentHelper.transform; + transform.SetParent(soundGroupHelper.transform); + transform.localScale = Vector3.one; + + if (m_AudioMixer != null) + { + AudioMixerGroup[] audioMixerGroups = m_AudioMixer.FindMatchingGroups(Utility.Text.Format("Master/{0}/{1}", soundGroupName, index)); + if (audioMixerGroups.Length > 0) + { + soundAgentHelper.AudioMixerGroup = audioMixerGroups[0]; + } + else + { + soundAgentHelper.AudioMixerGroup = soundGroupHelper.AudioMixerGroup; + } + } + + m_SoundManager.AddSoundAgentHelper(soundGroupName, soundAgentHelper); + + return true; + } + + private void OnPlaySoundSuccess(object sender, GameFramework.Sound.PlaySoundSuccessEventArgs e) + { + PlaySoundInfo playSoundInfo = (PlaySoundInfo)e.UserData; + if (playSoundInfo != null) + { + SoundAgentHelperBase soundAgentHelper = (SoundAgentHelperBase)e.SoundAgent.Helper; + if (playSoundInfo.BindingEntity != null) + { + soundAgentHelper.SetBindingEntity(playSoundInfo.BindingEntity); + } + else + { + soundAgentHelper.SetWorldPosition(playSoundInfo.WorldPosition); + } + } + + m_EventComponent.Fire(this, PlaySoundSuccessEventArgs.Create(e)); + } + + private void OnPlaySoundFailure(object sender, GameFramework.Sound.PlaySoundFailureEventArgs e) + { + string logMessage = Utility.Text.Format("Play sound failure, asset name '{0}', sound group name '{1}', error code '{2}', error message '{3}'.", e.SoundAssetName, e.SoundGroupName, e.ErrorCode, e.ErrorMessage); + if (e.ErrorCode == PlaySoundErrorCode.IgnoredDueToLowPriority) + { + Log.Info(logMessage); + } + else + { + Log.Warning(logMessage); + } + + m_EventComponent.Fire(this, PlaySoundFailureEventArgs.Create(e)); + } + + private void OnPlaySoundUpdate(object sender, GameFramework.Sound.PlaySoundUpdateEventArgs e) + { + m_EventComponent.Fire(this, PlaySoundUpdateEventArgs.Create(e)); + } + + private void OnPlaySoundDependencyAsset(object sender, GameFramework.Sound.PlaySoundDependencyAssetEventArgs e) + { + m_EventComponent.Fire(this, PlaySoundDependencyAssetEventArgs.Create(e)); + } + + private void OnLoadSceneSuccess(object sender, GameFramework.Scene.LoadSceneSuccessEventArgs e) + { + RefreshAudioListener(); + } + + private void OnLoadSceneFailure(object sender, GameFramework.Scene.LoadSceneFailureEventArgs e) + { + RefreshAudioListener(); + } + + private void OnUnloadSceneSuccess(object sender, GameFramework.Scene.UnloadSceneSuccessEventArgs e) + { + RefreshAudioListener(); + } + + private void OnUnloadSceneFailure(object sender, GameFramework.Scene.UnloadSceneFailureEventArgs e) + { + RefreshAudioListener(); + } + + private void OnSceneLoaded(Scene scene, LoadSceneMode loadSceneMode) + { + RefreshAudioListener(); + } + + private void OnSceneUnloaded(Scene scene) + { + RefreshAudioListener(); + } + + private void RefreshAudioListener() + { + m_AudioListener.enabled = FindObjectsOfType().Length <= 1; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundComponent.cs.meta new file mode 100644 index 0000000..198b47b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ed5533de69c4e5a4dabc7c23fce1fa98 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundGroupHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundGroupHelperBase.cs new file mode 100644 index 0000000..fc07733 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundGroupHelperBase.cs @@ -0,0 +1,37 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Sound; +using UnityEngine; +using UnityEngine.Audio; + +namespace UnityGameFramework.Runtime +{ + /// + /// 声音组辅助器基类。 + /// + public abstract class SoundGroupHelperBase : MonoBehaviour, ISoundGroupHelper + { + [SerializeField] + private AudioMixerGroup m_AudioMixerGroup = null; + + /// + /// 获取或设置声音组辅助器所在的混音组。 + /// + public AudioMixerGroup AudioMixerGroup + { + get + { + return m_AudioMixerGroup; + } + set + { + m_AudioMixerGroup = value; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundGroupHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundGroupHelperBase.cs.meta new file mode 100644 index 0000000..93ed86b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundGroupHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9b1aa5b8d134ac846a5a83fd661c9e92 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundHelperBase.cs new file mode 100644 index 0000000..cc7d2c5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundHelperBase.cs @@ -0,0 +1,24 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.Sound; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 声音辅助器基类。 + /// + public abstract class SoundHelperBase : MonoBehaviour, ISoundHelper + { + /// + /// 释放声音资源。 + /// + /// 要释放的声音资源。 + public abstract void ReleaseSoundAsset(object soundAsset); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundHelperBase.cs.meta new file mode 100644 index 0000000..b94f865 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Sound/SoundHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d63865838389abe428ccc3cee437a862 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI.meta new file mode 100644 index 0000000..79b74e3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 54c6b5aa3d448eb45a27b1f39e40db63 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/CloseUIFormCompleteEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/CloseUIFormCompleteEventArgs.cs new file mode 100644 index 0000000..90bcdea --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/CloseUIFormCompleteEventArgs.cs @@ -0,0 +1,108 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; +using GameFramework.UI; + +namespace UnityGameFramework.Runtime +{ + /// + /// 关闭界面完成事件。 + /// + public sealed class CloseUIFormCompleteEventArgs : GameEventArgs + { + /// + /// 关闭界面完成事件编号。 + /// + public static readonly int EventId = typeof(CloseUIFormCompleteEventArgs).GetHashCode(); + + /// + /// 初始化关闭界面完成事件的新实例。 + /// + public CloseUIFormCompleteEventArgs() + { + SerialId = 0; + UIFormAssetName = null; + UIGroup = null; + UserData = null; + } + + /// + /// 获取关闭界面完成事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取界面序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取界面资源名称。 + /// + public string UIFormAssetName + { + get; + private set; + } + + /// + /// 获取界面所属的界面组。 + /// + public IUIGroup UIGroup + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建关闭界面完成事件。 + /// + /// 内部事件。 + /// 创建的关闭界面完成事件。 + public static CloseUIFormCompleteEventArgs Create(GameFramework.UI.CloseUIFormCompleteEventArgs e) + { + CloseUIFormCompleteEventArgs closeUIFormCompleteEventArgs = ReferencePool.Acquire(); + closeUIFormCompleteEventArgs.SerialId = e.SerialId; + closeUIFormCompleteEventArgs.UIFormAssetName = e.UIFormAssetName; + closeUIFormCompleteEventArgs.UIGroup = e.UIGroup; + closeUIFormCompleteEventArgs.UserData = e.UserData; + return closeUIFormCompleteEventArgs; + } + + /// + /// 清理关闭界面完成事件。 + /// + public override void Clear() + { + SerialId = 0; + UIFormAssetName = null; + UIGroup = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/CloseUIFormCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/CloseUIFormCompleteEventArgs.cs.meta new file mode 100644 index 0000000..b3a1b2e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/CloseUIFormCompleteEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e5119cf2f6bdac343a0b73ee3a0aa400 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/DefaultUIFormHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/DefaultUIFormHelper.cs new file mode 100644 index 0000000..d6395f4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/DefaultUIFormHelper.cs @@ -0,0 +1,74 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.UI; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认界面辅助器。 + /// + public class DefaultUIFormHelper : UIFormHelperBase + { + private ResourceComponent m_ResourceComponent = null; + + /// + /// 实例化界面。 + /// + /// 要实例化的界面资源。 + /// 实例化后的界面。 + public override object InstantiateUIForm(object uiFormAsset) + { + return Instantiate((Object)uiFormAsset); + } + + /// + /// 创建界面。 + /// + /// 界面实例。 + /// 界面所属的界面组。 + /// 用户自定义数据。 + /// 界面。 + public override IUIForm CreateUIForm(object uiFormInstance, IUIGroup uiGroup, object userData) + { + GameObject gameObject = uiFormInstance as GameObject; + if (gameObject == null) + { + Log.Error("UI form instance is invalid."); + return null; + } + + Transform transform = gameObject.transform; + transform.SetParent(((MonoBehaviour)uiGroup.Helper).transform); + transform.localScale = Vector3.one; + + return gameObject.GetOrAddComponent(); + } + + /// + /// 释放界面。 + /// + /// 要释放的界面资源。 + /// 要释放的界面实例。 + public override void ReleaseUIForm(object uiFormAsset, object uiFormInstance) + { + m_ResourceComponent.UnloadAsset(uiFormAsset); + Destroy((Object)uiFormInstance); + } + + private void Start() + { + m_ResourceComponent = GameEntry.GetComponent(); + if (m_ResourceComponent == null) + { + Log.Fatal("Resource component is invalid."); + return; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/DefaultUIFormHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/DefaultUIFormHelper.cs.meta new file mode 100644 index 0000000..f9debfc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/DefaultUIFormHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e0703eb62bea8944aa3fe2aa95df420a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/DefaultUIGroupHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/DefaultUIGroupHelper.cs new file mode 100644 index 0000000..ecee4e1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/DefaultUIGroupHelper.cs @@ -0,0 +1,59 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; +using UnityEngine.UI; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认界面组辅助器。 + /// + public class DefaultUIGroupHelper : UIGroupHelperBase + { + ///// + ///// 设置界面组深度。 + ///// + ///// 界面组深度。 + //public override void SetDepth(int depth) + //{ + //} + public const int DepthFactor = 5000; + + private int m_Depth = 0; + private Canvas m_CachedCanvas = null; + + /// + /// 设置界面组深度。 + /// + /// 界面组深度。 + public override void SetDepth(int depth) + { + m_Depth = depth; + m_CachedCanvas.overrideSorting = true; + m_CachedCanvas.sortingOrder = DepthFactor * depth; + } + + private void Awake() + { + m_CachedCanvas = gameObject.GetOrAddComponent(); + gameObject.GetOrAddComponent(); + } + + private void Start() + { + m_CachedCanvas.overrideSorting = true; + m_CachedCanvas.sortingOrder = DepthFactor * m_Depth; + RectTransform transform = GetComponent(); + transform.anchorMin = Vector2.zero; + transform.anchorMax = Vector2.one; + transform.anchoredPosition = Vector2.zero; + transform.sizeDelta = Vector2.zero; + transform.localPosition = Vector3.zero; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/DefaultUIGroupHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/DefaultUIGroupHelper.cs.meta new file mode 100644 index 0000000..d6c9b1c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/DefaultUIGroupHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1a9d94772d704094da287912ccaf5b4a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormDependencyAssetEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormDependencyAssetEventArgs.cs new file mode 100644 index 0000000..e2f56fd --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormDependencyAssetEventArgs.cs @@ -0,0 +1,155 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 打开界面时加载依赖资源事件。 + /// + public sealed class OpenUIFormDependencyAssetEventArgs : GameEventArgs + { + /// + /// 打开界面时加载依赖资源事件编号。 + /// + public static readonly int EventId = typeof(OpenUIFormDependencyAssetEventArgs).GetHashCode(); + + /// + /// 初始化打开界面时加载依赖资源事件的新实例。 + /// + public OpenUIFormDependencyAssetEventArgs() + { + SerialId = 0; + UIFormAssetName = null; + UIGroupName = null; + PauseCoveredUIForm = false; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + + /// + /// 获取打开界面时加载依赖资源事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取界面序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取界面资源名称。 + /// + public string UIFormAssetName + { + get; + private set; + } + + /// + /// 获取界面组名称。 + /// + public string UIGroupName + { + get; + private set; + } + + /// + /// 获取是否暂停被覆盖的界面。 + /// + public bool PauseCoveredUIForm + { + get; + private set; + } + + /// + /// 获取被加载的依赖资源名称。 + /// + public string DependencyAssetName + { + get; + private set; + } + + /// + /// 获取当前已加载依赖资源数量。 + /// + public int LoadedCount + { + get; + private set; + } + + /// + /// 获取总共加载依赖资源数量。 + /// + public int TotalCount + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建打开界面时加载依赖资源事件。 + /// + /// 内部事件。 + /// 创建的打开界面时加载依赖资源事件。 + public static OpenUIFormDependencyAssetEventArgs Create(GameFramework.UI.OpenUIFormDependencyAssetEventArgs e) + { + OpenUIFormDependencyAssetEventArgs openUIFormDependencyAssetEventArgs = ReferencePool.Acquire(); + openUIFormDependencyAssetEventArgs.SerialId = e.SerialId; + openUIFormDependencyAssetEventArgs.UIFormAssetName = e.UIFormAssetName; + openUIFormDependencyAssetEventArgs.UIGroupName = e.UIGroupName; + openUIFormDependencyAssetEventArgs.PauseCoveredUIForm = e.PauseCoveredUIForm; + openUIFormDependencyAssetEventArgs.DependencyAssetName = e.DependencyAssetName; + openUIFormDependencyAssetEventArgs.LoadedCount = e.LoadedCount; + openUIFormDependencyAssetEventArgs.TotalCount = e.TotalCount; + openUIFormDependencyAssetEventArgs.UserData = e.UserData; + return openUIFormDependencyAssetEventArgs; + } + + /// + /// 清理打开界面时加载依赖资源事件。 + /// + public override void Clear() + { + SerialId = 0; + UIFormAssetName = null; + UIGroupName = null; + PauseCoveredUIForm = false; + DependencyAssetName = null; + LoadedCount = 0; + TotalCount = 0; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormDependencyAssetEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormDependencyAssetEventArgs.cs.meta new file mode 100644 index 0000000..a64998f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormDependencyAssetEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 29b2ea8e2fa48e143adc8e647e8103bf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormFailureEventArgs.cs new file mode 100644 index 0000000..7b3e082 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormFailureEventArgs.cs @@ -0,0 +1,131 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 打开界面失败事件。 + /// + public sealed class OpenUIFormFailureEventArgs : GameEventArgs + { + /// + /// 打开界面失败事件编号。 + /// + public static readonly int EventId = typeof(OpenUIFormFailureEventArgs).GetHashCode(); + + /// + /// 初始化打开界面失败事件的新实例。 + /// + public OpenUIFormFailureEventArgs() + { + SerialId = 0; + UIFormAssetName = null; + UIGroupName = null; + PauseCoveredUIForm = false; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取打开界面失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取界面序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取界面资源名称。 + /// + public string UIFormAssetName + { + get; + private set; + } + + /// + /// 获取界面组名称。 + /// + public string UIGroupName + { + get; + private set; + } + + /// + /// 获取是否暂停被覆盖的界面。 + /// + public bool PauseCoveredUIForm + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建打开界面失败事件。 + /// + /// 内部事件。 + /// 创建的打开界面失败事件。 + public static OpenUIFormFailureEventArgs Create(GameFramework.UI.OpenUIFormFailureEventArgs e) + { + OpenUIFormFailureEventArgs openUIFormFailureEventArgs = ReferencePool.Acquire(); + openUIFormFailureEventArgs.SerialId = e.SerialId; + openUIFormFailureEventArgs.UIFormAssetName = e.UIFormAssetName; + openUIFormFailureEventArgs.UIGroupName = e.UIGroupName; + openUIFormFailureEventArgs.PauseCoveredUIForm = e.PauseCoveredUIForm; + openUIFormFailureEventArgs.ErrorMessage = e.ErrorMessage; + openUIFormFailureEventArgs.UserData = e.UserData; + return openUIFormFailureEventArgs; + } + + /// + /// 清理打开界面失败事件。 + /// + public override void Clear() + { + SerialId = 0; + UIFormAssetName = null; + UIGroupName = null; + PauseCoveredUIForm = false; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormFailureEventArgs.cs.meta new file mode 100644 index 0000000..f61aa21 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e7a6ba1b6a998054a893693b3ae07794 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormSuccessEventArgs.cs new file mode 100644 index 0000000..f3748ba --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormSuccessEventArgs.cs @@ -0,0 +1,96 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 打开界面成功事件。 + /// + public sealed class OpenUIFormSuccessEventArgs : GameEventArgs + { + /// + /// 打开界面成功事件编号。 + /// + /// GetHashCode返回一个唯一的值 + public static readonly int EventId = typeof(OpenUIFormSuccessEventArgs).GetHashCode(); + + /// + /// 初始化打开界面成功事件的新实例。 + /// + public OpenUIFormSuccessEventArgs() + { + UIForm = null; + Duration = 0f; + UserData = null; + } + + /// + /// 获取打开界面成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取打开成功的界面。 + /// + public UIForm UIForm + { + get; + private set; + } + + /// + /// 获取加载持续时间。 + /// + public float Duration + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建打开界面成功事件。 + /// + /// 内部事件。 + /// 创建的打开界面成功事件。 + public static OpenUIFormSuccessEventArgs Create(GameFramework.UI.OpenUIFormSuccessEventArgs e) + { + OpenUIFormSuccessEventArgs openUIFormSuccessEventArgs = ReferencePool.Acquire(); + openUIFormSuccessEventArgs.UIForm = (UIForm)e.UIForm; + openUIFormSuccessEventArgs.Duration = e.Duration; + openUIFormSuccessEventArgs.UserData = e.UserData; + return openUIFormSuccessEventArgs; + } + + /// + /// 清理打开界面成功事件。 + /// + public override void Clear() + { + UIForm = null; + Duration = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormSuccessEventArgs.cs.meta new file mode 100644 index 0000000..ee3f598 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 269e4d0709b02614d8509248981e82d8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormUpdateEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormUpdateEventArgs.cs new file mode 100644 index 0000000..d11ef2b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormUpdateEventArgs.cs @@ -0,0 +1,131 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// 打开界面更新事件。 + /// + public sealed class OpenUIFormUpdateEventArgs : GameEventArgs + { + /// + /// 打开界面更新事件编号。 + /// + public static readonly int EventId = typeof(OpenUIFormUpdateEventArgs).GetHashCode(); + + /// + /// 初始化打开界面更新事件的新实例。 + /// + public OpenUIFormUpdateEventArgs() + { + SerialId = 0; + UIFormAssetName = null; + UIGroupName = null; + PauseCoveredUIForm = false; + Progress = 0f; + UserData = null; + } + + /// + /// 获取打开界面更新事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取界面序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取界面资源名称。 + /// + public string UIFormAssetName + { + get; + private set; + } + + /// + /// 获取界面组名称。 + /// + public string UIGroupName + { + get; + private set; + } + + /// + /// 获取是否暂停被覆盖的界面。 + /// + public bool PauseCoveredUIForm + { + get; + private set; + } + + /// + /// 获取打开界面进度。 + /// + public float Progress + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建打开界面更新事件。 + /// + /// 内部事件。 + /// 创建的打开界面更新事件。 + public static OpenUIFormUpdateEventArgs Create(GameFramework.UI.OpenUIFormUpdateEventArgs e) + { + OpenUIFormUpdateEventArgs openUIFormUpdateEventArgs = ReferencePool.Acquire(); + openUIFormUpdateEventArgs.SerialId = e.SerialId; + openUIFormUpdateEventArgs.UIFormAssetName = e.UIFormAssetName; + openUIFormUpdateEventArgs.UIGroupName = e.UIGroupName; + openUIFormUpdateEventArgs.PauseCoveredUIForm = e.PauseCoveredUIForm; + openUIFormUpdateEventArgs.Progress = e.Progress; + openUIFormUpdateEventArgs.UserData = e.UserData; + return openUIFormUpdateEventArgs; + } + + /// + /// 清理打开界面更新事件。 + /// + public override void Clear() + { + SerialId = 0; + UIFormAssetName = null; + UIGroupName = null; + PauseCoveredUIForm = false; + Progress = 0f; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormUpdateEventArgs.cs.meta new file mode 100644 index 0000000..e0c7f2f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/OpenUIFormUpdateEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 314460751754f5d468a04af842439e8a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIComponent.UIGroup.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIComponent.UIGroup.cs new file mode 100644 index 0000000..701e82a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIComponent.UIGroup.cs @@ -0,0 +1,41 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + public sealed partial class UIComponent : GameFrameworkComponent + { + [Serializable] + private sealed class UIGroup + { + [SerializeField] + private string m_Name = null; + + [SerializeField] + private int m_Depth = 0; + + public string Name + { + get + { + return m_Name; + } + } + + public int Depth + { + get + { + return m_Depth; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIComponent.UIGroup.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIComponent.UIGroup.cs.meta new file mode 100644 index 0000000..6c87b82 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIComponent.UIGroup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f90c498e6b5e013499a1536555584b93 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIComponent.cs new file mode 100644 index 0000000..b6349f3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIComponent.cs @@ -0,0 +1,732 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.ObjectPool; +using GameFramework.Resource; +using GameFramework.UI; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 界面组件。 + /// + [DisallowMultipleComponent]//不允许添加多个组件 + [AddComponentMenu("Game Framework/UI")] + public sealed partial class UIComponent : GameFrameworkComponent + { + private const int DefaultPriority = 0; + + private IUIManager m_UIManager = null; + private EventComponent m_EventComponent = null; + + private readonly List m_InternalUIFormResults = new List(); + + [SerializeField] + private bool m_EnableOpenUIFormSuccessEvent = true; + + [SerializeField] + private bool m_EnableOpenUIFormFailureEvent = true; + + [SerializeField] + private bool m_EnableOpenUIFormUpdateEvent = false; + + [SerializeField] + private bool m_EnableOpenUIFormDependencyAssetEvent = false; + + [SerializeField] + private bool m_EnableCloseUIFormCompleteEvent = true; + + [SerializeField] + private float m_InstanceAutoReleaseInterval = 60f; + + [SerializeField] + private int m_InstanceCapacity = 16; + + [SerializeField] + private float m_InstanceExpireTime = 60f; + + [SerializeField] + private int m_InstancePriority = 0; + + [SerializeField] + private Transform m_InstanceRoot = null; + + [SerializeField] + private string m_UIFormHelperTypeName = "UnityGameFramework.Runtime.DefaultUIFormHelper"; + + [SerializeField] + private UIFormHelperBase m_CustomUIFormHelper = null; + + [SerializeField] + private string m_UIGroupHelperTypeName = "UnityGameFramework.Runtime.DefaultUIGroupHelper"; + + [SerializeField] + private UIGroupHelperBase m_CustomUIGroupHelper = null; + + [SerializeField] + private UIGroup[] m_UIGroups = null; + + /// + /// 获取界面组数量。 + /// + public int UIGroupCount + { + get + { + return m_UIManager.UIGroupCount; + } + } + + /// + /// 获取或设置界面实例对象池自动释放可释放对象的间隔秒数。 + /// + public float InstanceAutoReleaseInterval + { + get + { + return m_UIManager.InstanceAutoReleaseInterval; + } + set + { + m_UIManager.InstanceAutoReleaseInterval = m_InstanceAutoReleaseInterval = value; + } + } + + /// + /// 获取或设置界面实例对象池的容量。 + /// + public int InstanceCapacity + { + get + { + return m_UIManager.InstanceCapacity; + } + set + { + m_UIManager.InstanceCapacity = m_InstanceCapacity = value; + } + } + + /// + /// 获取或设置界面实例对象池对象过期秒数。 + /// + public float InstanceExpireTime + { + get + { + return m_UIManager.InstanceExpireTime; + } + set + { + m_UIManager.InstanceExpireTime = m_InstanceExpireTime = value; + } + } + + /// + /// 获取或设置界面实例对象池的优先级。 + /// + public int InstancePriority + { + get + { + return m_UIManager.InstancePriority; + } + set + { + m_UIManager.InstancePriority = m_InstancePriority = value; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_UIManager = GameFrameworkEntry.GetModule(); + if (m_UIManager == null) + { + Log.Fatal("UI manager is invalid."); + return; + } + + if (m_EnableOpenUIFormSuccessEvent) + { + m_UIManager.OpenUIFormSuccess += OnOpenUIFormSuccess; + } + + m_UIManager.OpenUIFormFailure += OnOpenUIFormFailure; + + if (m_EnableOpenUIFormUpdateEvent) + { + m_UIManager.OpenUIFormUpdate += OnOpenUIFormUpdate; + } + + if (m_EnableOpenUIFormDependencyAssetEvent) + { + m_UIManager.OpenUIFormDependencyAsset += OnOpenUIFormDependencyAsset; + } + + if (m_EnableCloseUIFormCompleteEvent) + { + m_UIManager.CloseUIFormComplete += OnCloseUIFormComplete; + } + } + + private void Start() + { + BaseComponent baseComponent = GameEntry.GetComponent(); + if (baseComponent == null) + { + Log.Fatal("Base component is invalid."); + return; + } + + m_EventComponent = GameEntry.GetComponent(); + if (m_EventComponent == null) + { + Log.Fatal("Event component is invalid."); + return; + } + + if (baseComponent.EditorResourceMode) + { + m_UIManager.SetResourceManager(baseComponent.EditorResourceHelper); + } + else + { + m_UIManager.SetResourceManager(GameFrameworkEntry.GetModule()); + } + + m_UIManager.SetObjectPoolManager(GameFrameworkEntry.GetModule()); + m_UIManager.InstanceAutoReleaseInterval = m_InstanceAutoReleaseInterval; + m_UIManager.InstanceCapacity = m_InstanceCapacity; + m_UIManager.InstanceExpireTime = m_InstanceExpireTime; + m_UIManager.InstancePriority = m_InstancePriority; + + UIFormHelperBase uiFormHelper = Helper.CreateHelper(m_UIFormHelperTypeName, m_CustomUIFormHelper); + if (uiFormHelper == null) + { + Log.Error("Can not create UI form helper."); + return; + } + + uiFormHelper.name = "UI Form Helper"; + Transform transform = uiFormHelper.transform; + transform.SetParent(this.transform); + transform.localScale = Vector3.one; + + m_UIManager.SetUIFormHelper(uiFormHelper); + + if (m_InstanceRoot == null) + { + m_InstanceRoot = new GameObject("UI Form Instances").transform; + m_InstanceRoot.SetParent(gameObject.transform); + m_InstanceRoot.localScale = Vector3.one; + } + + m_InstanceRoot.gameObject.layer = LayerMask.NameToLayer("UI"); + + for (int i = 0; i < m_UIGroups.Length; i++) + { + if (!AddUIGroup(m_UIGroups[i].Name, m_UIGroups[i].Depth)) + { + Log.Warning("Add UI group '{0}' failure.", m_UIGroups[i].Name); + continue; + } + } + } + + /// + /// 是否存在界面组。 + /// + /// 界面组名称。 + /// 是否存在界面组。 + public bool HasUIGroup(string uiGroupName) + { + return m_UIManager.HasUIGroup(uiGroupName); + } + + /// + /// 获取界面组。 + /// + /// 界面组名称。 + /// 要获取的界面组。 + public IUIGroup GetUIGroup(string uiGroupName) + { + return m_UIManager.GetUIGroup(uiGroupName); + } + + /// + /// 获取所有界面组。 + /// + /// 所有界面组。 + public IUIGroup[] GetAllUIGroups() + { + return m_UIManager.GetAllUIGroups(); + } + + /// + /// 获取所有界面组。 + /// + /// 所有界面组。 + public void GetAllUIGroups(List results) + { + m_UIManager.GetAllUIGroups(results); + } + + /// + /// 增加界面组。 + /// + /// 界面组名称。 + /// 是否增加界面组成功。 + public bool AddUIGroup(string uiGroupName) + { + return AddUIGroup(uiGroupName, 0); + } + + /// + /// 增加界面组。 + /// + /// 界面组名称。 + /// 界面组深度。 + /// 是否增加界面组成功。 + public bool AddUIGroup(string uiGroupName, int depth) + { + if (m_UIManager.HasUIGroup(uiGroupName)) + { + return false; + } + + UIGroupHelperBase uiGroupHelper = Helper.CreateHelper(m_UIGroupHelperTypeName, m_CustomUIGroupHelper, UIGroupCount); + if (uiGroupHelper == null) + { + Log.Error("Can not create UI group helper."); + return false; + } + + uiGroupHelper.name = Utility.Text.Format("UI Group - {0}", uiGroupName); + uiGroupHelper.gameObject.layer = LayerMask.NameToLayer("UI"); + Transform transform = uiGroupHelper.transform; + transform.SetParent(m_InstanceRoot); + transform.localScale = Vector3.one; + + return m_UIManager.AddUIGroup(uiGroupName, depth, uiGroupHelper); + } + + /// + /// 是否存在界面。 + /// + /// 界面序列编号。 + /// 是否存在界面。 + public bool HasUIForm(int serialId) + { + return m_UIManager.HasUIForm(serialId); + } + + /// + /// 是否存在界面。 + /// + /// 界面资源名称。 + /// 是否存在界面。 + public bool HasUIForm(string uiFormAssetName) + { + return m_UIManager.HasUIForm(uiFormAssetName); + } + + /// + /// 获取界面。 + /// + /// 界面序列编号。 + /// 要获取的界面。 + public UIForm GetUIForm(int serialId) + { + return (UIForm)m_UIManager.GetUIForm(serialId); + } + + /// + /// 获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + public UIForm GetUIForm(string uiFormAssetName) + { + return (UIForm)m_UIManager.GetUIForm(uiFormAssetName); + } + + /// + /// 获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + public UIForm[] GetUIForms(string uiFormAssetName) + { + IUIForm[] uiForms = m_UIManager.GetUIForms(uiFormAssetName); + UIForm[] uiFormImpls = new UIForm[uiForms.Length]; + for (int i = 0; i < uiForms.Length; i++) + { + uiFormImpls[i] = (UIForm)uiForms[i]; + } + + return uiFormImpls; + } + + /// + /// 获取界面。 + /// + /// 界面资源名称。 + /// 要获取的界面。 + public void GetUIForms(string uiFormAssetName, List results) + { + if (results == null) + { + Log.Error("Results is invalid."); + return; + } + + results.Clear(); + m_UIManager.GetUIForms(uiFormAssetName, m_InternalUIFormResults); + foreach (IUIForm uiForm in m_InternalUIFormResults) + { + results.Add((UIForm)uiForm); + } + } + + /// + /// 获取所有已加载的界面。 + /// + /// 所有已加载的界面。 + public UIForm[] GetAllLoadedUIForms() + { + IUIForm[] uiForms = m_UIManager.GetAllLoadedUIForms(); + UIForm[] uiFormImpls = new UIForm[uiForms.Length]; + for (int i = 0; i < uiForms.Length; i++) + { + uiFormImpls[i] = (UIForm)uiForms[i]; + } + + return uiFormImpls; + } + + /// + /// 获取所有已加载的界面。 + /// + /// 所有已加载的界面。 + public void GetAllLoadedUIForms(List results) + { + if (results == null) + { + Log.Error("Results is invalid."); + return; + } + + results.Clear(); + m_UIManager.GetAllLoadedUIForms(m_InternalUIFormResults); + foreach (IUIForm uiForm in m_InternalUIFormResults) + { + results.Add((UIForm)uiForm); + } + } + + /// + /// 获取所有正在加载界面的序列编号。 + /// + /// 所有正在加载界面的序列编号。 + public int[] GetAllLoadingUIFormSerialIds() + { + return m_UIManager.GetAllLoadingUIFormSerialIds(); + } + + /// + /// 获取所有正在加载界面的序列编号。 + /// + /// 所有正在加载界面的序列编号。 + public void GetAllLoadingUIFormSerialIds(List results) + { + m_UIManager.GetAllLoadingUIFormSerialIds(results); + } + + /// + /// 是否正在加载界面。 + /// + /// 界面序列编号。 + /// 是否正在加载界面。 + public bool IsLoadingUIForm(int serialId) + { + return m_UIManager.IsLoadingUIForm(serialId); + } + + /// + /// 是否正在加载界面。 + /// + /// 界面资源名称。 + /// 是否正在加载界面。 + public bool IsLoadingUIForm(string uiFormAssetName) + { + return m_UIManager.IsLoadingUIForm(uiFormAssetName); + } + + /// + /// 是否是合法的界面。 + /// + /// 界面。 + /// 界面是否合法。 + public bool IsValidUIForm(UIForm uiForm) + { + return m_UIManager.IsValidUIForm(uiForm); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName) + { + return OpenUIForm(uiFormAssetName, uiGroupName, DefaultPriority, false, null); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 加载界面资源的优先级。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority) + { + return OpenUIForm(uiFormAssetName, uiGroupName, priority, false, null); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 是否暂停被覆盖的界面。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, bool pauseCoveredUIForm) + { + return OpenUIForm(uiFormAssetName, uiGroupName, DefaultPriority, pauseCoveredUIForm, null); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 用户自定义数据。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, object userData) + { + return OpenUIForm(uiFormAssetName, uiGroupName, DefaultPriority, false, userData); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 加载界面资源的优先级。 + /// 是否暂停被覆盖的界面。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, bool pauseCoveredUIForm) + { + return OpenUIForm(uiFormAssetName, uiGroupName, priority, pauseCoveredUIForm, null); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 加载界面资源的优先级。 + /// 用户自定义数据。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, object userData) + { + return OpenUIForm(uiFormAssetName, uiGroupName, priority, false, userData); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 是否暂停被覆盖的界面。 + /// 用户自定义数据。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, bool pauseCoveredUIForm, object userData) + { + return OpenUIForm(uiFormAssetName, uiGroupName, DefaultPriority, pauseCoveredUIForm, userData); + } + + /// + /// 打开界面。 + /// + /// 界面资源名称。 + /// 界面组名称。 + /// 加载界面资源的优先级。 + /// 是否暂停被覆盖的界面。 + /// 用户自定义数据。 + /// 界面的序列编号。 + public int OpenUIForm(string uiFormAssetName, string uiGroupName, int priority, bool pauseCoveredUIForm, object userData) + { + return m_UIManager.OpenUIForm(uiFormAssetName, uiGroupName, priority, pauseCoveredUIForm, userData); + } + + /// + /// 关闭界面。 + /// + /// 要关闭界面的序列编号。 + public void CloseUIForm(int serialId) + { + m_UIManager.CloseUIForm(serialId); + } + + /// + /// 关闭界面。 + /// + /// 要关闭界面的序列编号。 + /// 用户自定义数据。 + public void CloseUIForm(int serialId, object userData) + { + m_UIManager.CloseUIForm(serialId, userData); + } + + /// + /// 关闭界面。 + /// + /// 要关闭的界面。 + public void CloseUIForm(UIForm uiForm) + { + m_UIManager.CloseUIForm(uiForm); + } + + /// + /// 关闭界面。 + /// + /// 要关闭的界面。 + /// 用户自定义数据。 + public void CloseUIForm(UIForm uiForm, object userData) + { + m_UIManager.CloseUIForm(uiForm, userData); + } + + /// + /// 关闭所有已加载的界面。 + /// + public void CloseAllLoadedUIForms() + { + m_UIManager.CloseAllLoadedUIForms(); + } + + /// + /// 关闭所有已加载的界面。 + /// + /// 用户自定义数据。 + public void CloseAllLoadedUIForms(object userData) + { + m_UIManager.CloseAllLoadedUIForms(userData); + } + + /// + /// 关闭所有正在加载的界面。 + /// + public void CloseAllLoadingUIForms() + { + m_UIManager.CloseAllLoadingUIForms(); + } + + /// + /// 激活界面。 + /// + /// 要激活的界面。 + public void RefocusUIForm(UIForm uiForm) + { + m_UIManager.RefocusUIForm(uiForm); + } + + /// + /// 激活界面。 + /// + /// 要激活的界面。 + /// 用户自定义数据。 + public void RefocusUIForm(UIForm uiForm, object userData) + { + m_UIManager.RefocusUIForm(uiForm, userData); + } + + /// + /// 设置界面是否被加锁。 + /// + /// 要设置是否被加锁的界面。 + /// 界面是否被加锁。 + public void SetUIFormInstanceLocked(UIForm uiForm, bool locked) + { + if (uiForm == null) + { + Log.Warning("UI form is invalid."); + return; + } + + m_UIManager.SetUIFormInstanceLocked(uiForm.gameObject, locked); + } + + /// + /// 设置界面的优先级。 + /// + /// 要设置优先级的界面。 + /// 界面优先级。 + public void SetUIFormInstancePriority(UIForm uiForm, int priority) + { + if (uiForm == null) + { + Log.Warning("UI form is invalid."); + return; + } + + m_UIManager.SetUIFormInstancePriority(uiForm.gameObject, priority); + } + + private void OnOpenUIFormSuccess(object sender, GameFramework.UI.OpenUIFormSuccessEventArgs e) + { + m_EventComponent.Fire(this, OpenUIFormSuccessEventArgs.Create(e)); + //CustomDebug.Log("界面打开成功:" + e.UIForm.UIFormAssetName + "--" + e.UIForm.SerialId); + } + + private void OnOpenUIFormFailure(object sender, GameFramework.UI.OpenUIFormFailureEventArgs e) + { + Log.Warning("Open UI form failure, asset name '{0}', UI group name '{1}', pause covered UI form '{2}', error message '{3}'.", e.UIFormAssetName, e.UIGroupName, e.PauseCoveredUIForm, e.ErrorMessage); + if (m_EnableOpenUIFormFailureEvent) + { + m_EventComponent.Fire(this, OpenUIFormFailureEventArgs.Create(e)); + } + //CustomDebug.Log("界面打开失败:" + e.UIFormAssetName); + } + + private void OnOpenUIFormUpdate(object sender, GameFramework.UI.OpenUIFormUpdateEventArgs e) + { + m_EventComponent.Fire(this, OpenUIFormUpdateEventArgs.Create(e)); + } + + private void OnOpenUIFormDependencyAsset(object sender, GameFramework.UI.OpenUIFormDependencyAssetEventArgs e) + { + m_EventComponent.Fire(this, OpenUIFormDependencyAssetEventArgs.Create(e)); + } + + private void OnCloseUIFormComplete(object sender, GameFramework.UI.CloseUIFormCompleteEventArgs e) + { + m_EventComponent.Fire(this, CloseUIFormCompleteEventArgs.Create(e)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIComponent.cs.meta new file mode 100644 index 0000000..61af6f1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4a1ef15380caaed42b55022cadc93649 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIForm.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIForm.cs new file mode 100644 index 0000000..d41845b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIForm.cs @@ -0,0 +1,305 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.UI; +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 界面。 + /// + public sealed class UIForm : MonoBehaviour, IUIForm + { + private int m_SerialId; + private string m_UIFormAssetName; + private IUIGroup m_UIGroup; + private int m_DepthInUIGroup; + private bool m_PauseCoveredUIForm; + private UIFormLogic m_UIFormLogic; + + /// + /// 获取界面序列编号。 + /// + public int SerialId + { + get + { + return m_SerialId; + } + } + + /// + /// 获取界面资源名称。 + /// + public string UIFormAssetName + { + get + { + return m_UIFormAssetName; + } + } + + /// + /// 获取界面实例。 + /// + public object Handle + { + get + { + return gameObject; + } + } + + /// + /// 获取界面所属的界面组。 + /// + public IUIGroup UIGroup + { + get + { + return m_UIGroup; + } + } + + /// + /// 获取界面深度。 + /// + public int DepthInUIGroup + { + get + { + return m_DepthInUIGroup; + } + } + + /// + /// 获取是否暂停被覆盖的界面。 + /// + public bool PauseCoveredUIForm + { + get + { + return m_PauseCoveredUIForm; + } + } + + /// + /// 获取界面逻辑。 + /// + public UIFormLogic Logic + { + get + { + return m_UIFormLogic; + } + } + + /// + /// 初始化界面。 + /// + /// 界面序列编号。 + /// 界面资源名称。 + /// 界面所处的界面组。 + /// 是否暂停被覆盖的界面。 + /// 是否是新实例。 + /// 用户自定义数据。 + public void OnInit(int serialId, string uiFormAssetName, IUIGroup uiGroup, bool pauseCoveredUIForm, bool isNewInstance, object userData) + { + m_SerialId = serialId; + m_UIFormAssetName = uiFormAssetName; + m_UIGroup = uiGroup; + m_DepthInUIGroup = 0; + m_PauseCoveredUIForm = pauseCoveredUIForm; + + if (!isNewInstance) + { + return; + } + + m_UIFormLogic = GetComponent(); + if (m_UIFormLogic == null) + { + Log.Error("UI form '{0}' can not get UI form logic.", uiFormAssetName); + return; + } + + try + { + m_UIFormLogic.OnInit(userData); + } + catch (Exception exception) + { + Log.Error("UI form '[{0}]{1}' OnInit with exception '{2}'.", m_SerialId, m_UIFormAssetName, exception); + } + } + + /// + /// 界面回收。 + /// + public void OnRecycle() + { + try + { + m_UIFormLogic.OnRecycle(); + } + catch (Exception exception) + { + Log.Error("UI form '[{0}]{1}' OnRecycle with exception '{2}'.", m_SerialId, m_UIFormAssetName, exception); + } + + m_SerialId = 0; + m_DepthInUIGroup = 0; + m_PauseCoveredUIForm = true; + } + + /// + /// 界面打开。 + /// + /// 用户自定义数据。 + public void OnOpen(object userData) + { + try + { + m_UIFormLogic.OnOpen(userData); + } + catch (Exception exception) + { + Log.Error("UI form '[{0}]{1}' OnOpen with exception '{2}'.", m_SerialId, m_UIFormAssetName, exception); + } + } + + /// + /// 界面关闭。 + /// + /// 是否是关闭界面管理器时触发。 + /// 用户自定义数据。 + public void OnClose(bool isShutdown, object userData) + { + try + { + m_UIFormLogic.OnClose(isShutdown, userData); + } + catch (Exception exception) + { + Log.Error("UI form '[{0}]{1}' OnClose with exception '{2}'.", m_SerialId, m_UIFormAssetName, exception); + } + } + + /// + /// 界面暂停。 + /// + public void OnPause() + { + try + { + m_UIFormLogic.OnPause(); + } + catch (Exception exception) + { + Log.Error("UI form '[{0}]{1}' OnPause with exception '{2}'.", m_SerialId, m_UIFormAssetName, exception); + } + } + + /// + /// 界面暂停恢复。 + /// + public void OnResume() + { + try + { + m_UIFormLogic.OnResume(); + } + catch (Exception exception) + { + Log.Error("UI form '[{0}]{1}' OnResume with exception '{2}'.", m_SerialId, m_UIFormAssetName, exception); + } + } + + /// + /// 界面遮挡。 + /// + public void OnCover() + { + try + { + m_UIFormLogic.OnCover(); + } + catch (Exception exception) + { + Log.Error("UI form '[{0}]{1}' OnCover with exception '{2}'.", m_SerialId, m_UIFormAssetName, exception); + } + } + + /// + /// 界面遮挡恢复。 + /// + public void OnReveal() + { + try + { + m_UIFormLogic.OnReveal(); + } + catch (Exception exception) + { + Log.Error("UI form '[{0}]{1}' OnReveal with exception '{2}'.", m_SerialId, m_UIFormAssetName, exception); + } + } + + /// + /// 界面激活。 + /// + /// 用户自定义数据。 + public void OnRefocus(object userData) + { + try + { + m_UIFormLogic.OnRefocus(userData); + } + catch (Exception exception) + { + Log.Error("UI form '[{0}]{1}' OnRefocus with exception '{2}'.", m_SerialId, m_UIFormAssetName, exception); + } + } + + /// + /// 界面轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + public void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + try + { + m_UIFormLogic.OnUpdate(elapseSeconds, realElapseSeconds); + } + catch (Exception exception) + { + Log.Error("UI form '[{0}]{1}' OnUpdate with exception '{2}'.", m_SerialId, m_UIFormAssetName, exception); + } + } + + /// + /// 界面深度改变。 + /// + /// 界面组深度。 + /// 界面在界面组中的深度。 + public void OnDepthChanged(int uiGroupDepth, int depthInUIGroup) + { + m_DepthInUIGroup = depthInUIGroup; + try + { + m_UIFormLogic.OnDepthChanged(uiGroupDepth, depthInUIGroup); + } + catch (Exception exception) + { + Log.Error("UI form '[{0}]{1}' OnDepthChanged with exception '{2}'.", m_SerialId, m_UIFormAssetName, exception); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIForm.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIForm.cs.meta new file mode 100644 index 0000000..94042ec --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIForm.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f627c32af5133a24f829e711fafe42fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIFormHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIFormHelperBase.cs new file mode 100644 index 0000000..f1cd5a6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIFormHelperBase.cs @@ -0,0 +1,41 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.UI; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 界面辅助器基类。 + /// + public abstract class UIFormHelperBase : MonoBehaviour, IUIFormHelper + { + /// + /// 实例化界面。 + /// + /// 要实例化的界面资源。 + /// 实例化后的界面。 + public abstract object InstantiateUIForm(object uiFormAsset); + + /// + /// 创建界面。 + /// + /// 界面实例。 + /// 界面所属的界面组。 + /// 用户自定义数据。 + /// 界面。 + public abstract IUIForm CreateUIForm(object uiFormInstance, IUIGroup uiGroup, object userData); + + /// + /// 释放界面。 + /// + /// 要释放的界面资源。 + /// 要释放的界面实例。 + public abstract void ReleaseUIForm(object uiFormAsset, object uiFormInstance); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIFormHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIFormHelperBase.cs.meta new file mode 100644 index 0000000..11576a0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIFormHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a33f1f48cf25a4a44bd85661139f76ee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIFormLogic.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIFormLogic.cs new file mode 100644 index 0000000..6fe5946 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIFormLogic.cs @@ -0,0 +1,207 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 界面逻辑基类。 + /// + public abstract class UIFormLogic : MonoBehaviour + { + private bool m_Available = false; + private bool m_Visible = false; + private UIForm m_UIForm = null; + private Transform m_CachedTransform = null; + private int m_OriginalLayer = 0; + + /// + /// 获取界面。 + /// + public UIForm UIForm + { + get + { + return m_UIForm; + } + } + + /// + /// 获取或设置界面名称。 + /// + public string Name + { + get + { + return gameObject.name; + } + set + { + gameObject.name = value; + } + } + + /// + /// 获取界面是否可用。 + /// + public bool Available + { + get + { + return m_Available; + } + } + + /// + /// 获取或设置界面是否可见。 + /// + public bool Visible + { + get + { + return m_Available && m_Visible; + } + set + { + if (!m_Available) + { + Log.Warning("UI form '{0}' is not available.", Name); + return; + } + + if (m_Visible == value) + { + return; + } + + m_Visible = value; + InternalSetVisible(value); + } + } + + /// + /// 获取已缓存的 Transform。 + /// + public Transform CachedTransform + { + get + { + return m_CachedTransform; + } + } + + /// + /// 界面初始化。 + /// + /// 用户自定义数据。 + protected internal virtual void OnInit(object userData) + { + if (m_CachedTransform == null) + { + m_CachedTransform = transform; + } + + m_UIForm = GetComponent(); + m_OriginalLayer = gameObject.layer; + } + + /// + /// 界面回收。 + /// + protected internal virtual void OnRecycle() + { + } + + /// + /// 界面打开。 + /// + /// 用户自定义数据。 + protected internal virtual void OnOpen(object userData) + { + m_Available = true; + Visible = true; + } + + /// + /// 界面关闭。 + /// + /// 是否是关闭界面管理器时触发。 + /// 用户自定义数据。 + protected internal virtual void OnClose(bool isShutdown, object userData) + { + gameObject.SetLayerRecursively(m_OriginalLayer); + Visible = false; + m_Available = false; + } + + /// + /// 界面暂停。 + /// + protected internal virtual void OnPause() + { + Visible = false; + } + + /// + /// 界面暂停恢复。 + /// + protected internal virtual void OnResume() + { + Visible = true; + } + + /// + /// 界面遮挡。 + /// + protected internal virtual void OnCover() + { + } + + /// + /// 界面遮挡恢复。 + /// + protected internal virtual void OnReveal() + { + } + + /// + /// 界面激活。 + /// + /// 用户自定义数据。 + protected internal virtual void OnRefocus(object userData) + { + } + + /// + /// 界面轮询。 + /// + /// 逻辑流逝时间,以秒为单位。 + /// 真实流逝时间,以秒为单位。 + protected internal virtual void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + } + + /// + /// 界面深度改变。 + /// + /// 界面组深度。 + /// 界面在界面组中的深度。 + protected internal virtual void OnDepthChanged(int uiGroupDepth, int depthInUIGroup) + { + } + + /// + /// 设置界面的可见性。 + /// + /// 界面的可见性。 + protected virtual void InternalSetVisible(bool visible) + { + gameObject.SetActive(visible); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIFormLogic.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIFormLogic.cs.meta new file mode 100644 index 0000000..5c483ab --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIFormLogic.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0293f872933ead649893db69d7f4e2ce +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIGroupHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIGroupHelperBase.cs new file mode 100644 index 0000000..a11bc4c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIGroupHelperBase.cs @@ -0,0 +1,24 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.UI; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 界面组辅助器基类。 + /// + public abstract class UIGroupHelperBase : MonoBehaviour, IUIGroupHelper + { + /// + /// 设置界面组深度。 + /// + /// 界面组深度。 + public abstract void SetDepth(int depth); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIGroupHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIGroupHelperBase.cs.meta new file mode 100644 index 0000000..db56957 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIGroupHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 02539b9fb3e30984ea1707e6f87bc3d2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIIntKey.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIIntKey.cs new file mode 100644 index 0000000..0ffdd1d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIIntKey.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 界面整型主键。 + /// + public sealed class UIIntKey : MonoBehaviour + { + [SerializeField] + private int m_Key = 0; + + /// + /// 获取或设置主键。 + /// + public int Key + { + get + { + return m_Key; + } + set + { + m_Key = value; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIIntKey.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIIntKey.cs.meta new file mode 100644 index 0000000..0cd4cfc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIIntKey.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 606f38525c5bccb4d9355c54a60746f6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIStringKey.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIStringKey.cs new file mode 100644 index 0000000..cafe10d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIStringKey.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 界面字符型主键。 + /// + public sealed class UIStringKey : MonoBehaviour + { + [SerializeField] + private string m_Key = null; + + /// + /// 获取或设置主键。 + /// + public string Key + { + get + { + return m_Key ?? string.Empty; + } + set + { + m_Key = value; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIStringKey.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIStringKey.cs.meta new file mode 100644 index 0000000..cf6f683 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UI/UIStringKey.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 087a56c75d247be4f8f7cf82ceb68e4b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UnityGameFramework.Runtime.asmdef b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UnityGameFramework.Runtime.asmdef new file mode 100644 index 0000000..25a41e2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UnityGameFramework.Runtime.asmdef @@ -0,0 +1,16 @@ +{ + "name": "UnityGameFramework.Runtime", + "rootNamespace": "", + "references": [ + "GameFramework" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UnityGameFramework.Runtime.asmdef.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UnityGameFramework.Runtime.asmdef.meta new file mode 100644 index 0000000..647e4e6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/UnityGameFramework.Runtime.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 01b55c6a61e21dd4890790ede7b78e56 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility.meta new file mode 100644 index 0000000..da20d06 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d5515dfbdcfab2040b332669de5c9a8a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/BinaryExtension.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/BinaryExtension.cs new file mode 100644 index 0000000..2da4628 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/BinaryExtension.cs @@ -0,0 +1,197 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.IO; + +/// +/// 对 BinaryReader 和 BinaryWriter 的扩展方法。 +/// +public static class BinaryExtension +{ + private static readonly byte[] s_CachedBytes = new byte[byte.MaxValue + 1]; + + /// + /// 从二进制流读取编码后的 32 位有符号整数。 + /// + /// 要读取的二进制流。 + /// 读取的 32 位有符号整数。 + public static int Read7BitEncodedInt32(this BinaryReader binaryReader) + { + int value = 0; + int shift = 0; + byte b; + do + { + if (shift >= 35) + { + throw new GameFrameworkException("7 bit encoded int is invalid."); + } + + b = binaryReader.ReadByte(); + value |= (b & 0x7f) << shift; + shift += 7; + } while ((b & 0x80) != 0); + + return value; + } + + /// + /// 向二进制流写入编码后的 32 位有符号整数。 + /// + /// 要写入的二进制流。 + /// 要写入的 32 位有符号整数。 + public static void Write7BitEncodedInt32(this BinaryWriter binaryWriter, int value) + { + uint num = (uint)value; + while (num >= 0x80) + { + binaryWriter.Write((byte)(num | 0x80)); + num >>= 7; + } + + binaryWriter.Write((byte)num); + } + + /// + /// 从二进制流读取编码后的 32 位无符号整数。 + /// + /// 要读取的二进制流。 + /// 读取的 32 位无符号整数。 + public static uint Read7BitEncodedUInt32(this BinaryReader binaryReader) + { + return (uint)Read7BitEncodedInt32(binaryReader); + } + + /// + /// 向二进制流写入编码后的 32 位无符号整数。 + /// + /// 要写入的二进制流。 + /// 要写入的 32 位无符号整数。 + public static void Write7BitEncodedUInt32(this BinaryWriter binaryWriter, uint value) + { + Write7BitEncodedInt32(binaryWriter, (int)value); + } + + /// + /// 从二进制流读取编码后的 64 位有符号整数。 + /// + /// 要读取的二进制流。 + /// 读取的 64 位有符号整数。 + public static long Read7BitEncodedInt64(this BinaryReader binaryReader) + { + long value = 0L; + int shift = 0; + byte b; + do + { + if (shift >= 70) + { + throw new GameFrameworkException("7 bit encoded int is invalid."); + } + + b = binaryReader.ReadByte(); + value |= (b & 0x7fL) << shift; + shift += 7; + } while ((b & 0x80) != 0); + + return value; + } + + /// + /// 向二进制流写入编码后的 64 位有符号整数。 + /// + /// 要写入的二进制流。 + /// 要写入的 64 位有符号整数。 + public static void Write7BitEncodedInt64(this BinaryWriter binaryWriter, long value) + { + ulong num = (ulong)value; + while (num >= 0x80) + { + binaryWriter.Write((byte)(num | 0x80)); + num >>= 7; + } + + binaryWriter.Write((byte)num); + } + + /// + /// 从二进制流读取编码后的 64 位无符号整数。 + /// + /// 要读取的二进制流。 + /// 读取的 64 位无符号整数。 + public static ulong Read7BitEncodedUInt64(this BinaryReader binaryReader) + { + return (ulong)Read7BitEncodedInt64(binaryReader); + } + + /// + /// 向二进制流写入编码后的 64 位无符号整数。 + /// + /// 要写入的二进制流。 + /// 要写入的 64 位无符号整数。 + public static void Write7BitEncodedUInt64(this BinaryWriter binaryWriter, ulong value) + { + Write7BitEncodedInt64(binaryWriter, (long)value); + } + + /// + /// 从二进制流读取加密字符串。 + /// + /// 要读取的二进制流。 + /// 密钥数组。 + /// 读取的字符串。 + public static string ReadEncryptedString(this BinaryReader binaryReader, byte[] encryptBytes) + { + byte length = binaryReader.ReadByte(); + if (length <= 0) + { + return null; + } + + if (length > byte.MaxValue) + { + throw new GameFrameworkException("String is too long."); + } + + for (byte i = 0; i < length; i++) + { + s_CachedBytes[i] = binaryReader.ReadByte(); + } + + Utility.Encryption.GetSelfXorBytes(s_CachedBytes, 0, length, encryptBytes); + string value = Utility.Converter.GetString(s_CachedBytes, 0, length); + Array.Clear(s_CachedBytes, 0, length); + return value; + } + + /// + /// 向二进制流写入加密字符串。 + /// + /// 要写入的二进制流。 + /// 要写入的字符串。 + /// 密钥数组。 + public static void WriteEncryptedString(this BinaryWriter binaryWriter, string value, byte[] encryptBytes) + { + if (string.IsNullOrEmpty(value)) + { + binaryWriter.Write((byte)0); + return; + } + + int length = Utility.Converter.GetBytes(value, s_CachedBytes); + if (length > byte.MaxValue) + { + throw new GameFrameworkException(Utility.Text.Format("String '{0}' is too long.", value)); + } + + Utility.Encryption.GetSelfXorBytes(s_CachedBytes, encryptBytes); + binaryWriter.Write((byte)length); + binaryWriter.Write(s_CachedBytes, 0, length); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/BinaryExtension.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/BinaryExtension.cs.meta new file mode 100644 index 0000000..11cc1b2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/BinaryExtension.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a9c8ae7c81e4c674a88100f89ad5812c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultCompressionHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultCompressionHelper.cs new file mode 100644 index 0000000..c5990bb --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultCompressionHelper.cs @@ -0,0 +1,212 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using ICSharpCode.SharpZipLib.GZip; +using System; +using System.IO; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认压缩解压缩辅助器。 + /// + public class DefaultCompressionHelper : Utility.Compression.ICompressionHelper + { + private const int CachedBytesLength = 0x1000; + private readonly byte[] m_CachedBytes = new byte[CachedBytesLength]; + + /// + /// 压缩数据。 + /// + /// 要压缩的数据的二进制流。 + /// 要压缩的数据的二进制流的偏移。 + /// 要压缩的数据的二进制流的长度。 + /// 压缩后的数据的二进制流。 + /// 是否压缩数据成功。 + public bool Compress(byte[] bytes, int offset, int length, Stream compressedStream) + { + if (bytes == null) + { + return false; + } + + if (offset < 0 || length < 0 || offset + length > bytes.Length) + { + return false; + } + + if (compressedStream == null) + { + return false; + } + + try + { + GZipOutputStream gZipOutputStream = new GZipOutputStream(compressedStream); + gZipOutputStream.Write(bytes, offset, length); + gZipOutputStream.Finish(); + ProcessHeader(compressedStream); + return true; + } + catch + { + return false; + } + } + + /// + /// 压缩数据。 + /// + /// 要压缩的数据的二进制流。 + /// 压缩后的数据的二进制流。 + /// 是否压缩数据成功。 + public bool Compress(Stream stream, Stream compressedStream) + { + if (stream == null) + { + return false; + } + + if (compressedStream == null) + { + return false; + } + + try + { + GZipOutputStream gZipOutputStream = new GZipOutputStream(compressedStream); + int bytesRead = 0; + while ((bytesRead = stream.Read(m_CachedBytes, 0, CachedBytesLength)) > 0) + { + gZipOutputStream.Write(m_CachedBytes, 0, bytesRead); + } + + gZipOutputStream.Finish(); + ProcessHeader(compressedStream); + return true; + } + catch + { + return false; + } + finally + { + Array.Clear(m_CachedBytes, 0, CachedBytesLength); + } + } + + /// + /// 解压缩数据。 + /// + /// 要解压缩的数据的二进制流。 + /// 要解压缩的数据的二进制流的偏移。 + /// 要解压缩的数据的二进制流的长度。 + /// 解压缩后的数据的二进制流。 + /// 是否解压缩数据成功。 + public bool Decompress(byte[] bytes, int offset, int length, Stream decompressedStream) + { + if (bytes == null) + { + return false; + } + + if (offset < 0 || length < 0 || offset + length > bytes.Length) + { + return false; + } + + if (decompressedStream == null) + { + return false; + } + + MemoryStream memoryStream = null; + try + { + memoryStream = new MemoryStream(bytes, offset, length, false); + using (GZipInputStream gZipInputStream = new GZipInputStream(memoryStream)) + { + int bytesRead = 0; + while ((bytesRead = gZipInputStream.Read(m_CachedBytes, 0, CachedBytesLength)) > 0) + { + decompressedStream.Write(m_CachedBytes, 0, bytesRead); + } + } + + return true; + } + catch + { + return false; + } + finally + { + if (memoryStream != null) + { + memoryStream.Dispose(); + memoryStream = null; + } + + Array.Clear(m_CachedBytes, 0, CachedBytesLength); + } + } + + /// + /// 解压缩数据。 + /// + /// 要解压缩的数据的二进制流。 + /// 解压缩后的数据的二进制流。 + /// 是否解压缩数据成功。 + public bool Decompress(Stream stream, Stream decompressedStream) + { + if (stream == null) + { + return false; + } + + if (decompressedStream == null) + { + return false; + } + + try + { + GZipInputStream gZipInputStream = new GZipInputStream(stream); + int bytesRead = 0; + while ((bytesRead = gZipInputStream.Read(m_CachedBytes, 0, CachedBytesLength)) > 0) + { + decompressedStream.Write(m_CachedBytes, 0, bytesRead); + } + + return true; + } + catch + { + return false; + } + finally + { + Array.Clear(m_CachedBytes, 0, CachedBytesLength); + } + } + + private static void ProcessHeader(Stream compressedStream) + { + if (compressedStream.Length >= 8L) + { + long current = compressedStream.Position; + compressedStream.Position = 4L; + compressedStream.WriteByte(25); + compressedStream.WriteByte(134); + compressedStream.WriteByte(2); + compressedStream.WriteByte(32); + compressedStream.Position = current; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultCompressionHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultCompressionHelper.cs.meta new file mode 100644 index 0000000..193ed8a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultCompressionHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1d572c5f6d619fd4cab0970b865300f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultJsonHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultJsonHelper.cs new file mode 100644 index 0000000..daa90cf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultJsonHelper.cs @@ -0,0 +1,56 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认 JSON 函数集辅助器。 + /// + public class DefaultJsonHelper : Utility.Json.IJsonHelper + { + /// + /// 将对象序列化为 JSON 字符串。 + /// + /// 要序列化的对象。 + /// 序列化后的 JSON 字符串。 + public string ToJson(object obj) + { + return JsonUtility.ToJson(obj); + //return JsonMapper.ToJson(obj); + //return JsonConvert.SerializeObject(obj); + } + + /// + /// 将 JSON 字符串反序列化为对象。 + /// + /// 对象类型。 + /// 要反序列化的 JSON 字符串。 + /// 反序列化后的对象。 + public T ToObject(string json) + { + return JsonUtility.FromJson(json); + //return JsonMapper.ToObject(json); + //return JsonConvert.DeserializeObject(json); + } + + /// + /// 将 JSON 字符串反序列化为对象。 + /// + /// 对象类型。 + /// 要反序列化的 JSON 字符串。 + /// 反序列化后的对象。 + public object ToObject(Type objectType, string json) + { + return JsonUtility.FromJson(json, objectType); + //throw new NotSupportedException("ToObject(Type objectType, string json)"); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultJsonHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultJsonHelper.cs.meta new file mode 100644 index 0000000..72bb5e4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultJsonHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7bba1aecb54101942a686f78ca5888b2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultLogHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultLogHelper.cs new file mode 100644 index 0000000..c390ba6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultLogHelper.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认游戏框架日志辅助器。 + /// + public class DefaultLogHelper : GameFrameworkLog.ILogHelper + { + /// + /// 记录日志。 + /// + /// 日志等级。 + /// 日志内容。 + public void Log(GameFrameworkLogLevel level, object message) + { + switch (level) + { + case GameFrameworkLogLevel.Debug: + Debug.Log(Utility.Text.Format("{0}", message)); + break; + + case GameFrameworkLogLevel.Info: + Debug.Log(message.ToString()); + break; + + case GameFrameworkLogLevel.Warning: + Debug.LogWarning(message.ToString()); + break; + + case GameFrameworkLogLevel.Error: + Debug.LogError(message.ToString()); + break; + + default: + throw new GameFrameworkException(message.ToString()); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultLogHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultLogHelper.cs.meta new file mode 100644 index 0000000..e102ffe --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultLogHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 646cb891dff23ba49982a2710fd1a218 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultTextHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultTextHelper.cs new file mode 100644 index 0000000..901bd47 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultTextHelper.cs @@ -0,0 +1,592 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; +using System.Text; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认字符辅助器。 + /// + public class DefaultTextHelper : Utility.Text.ITextHelper + { + private const int StringBuilderCapacity = 1024; + + [ThreadStatic] + private static StringBuilder s_CachedStringBuilder = null; + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数的类型。 + /// 字符串格式。 + /// 字符串参数。 + /// 格式化后的字符串。 + public string Format(string format, T arg) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4, arg5); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4, arg5, arg6); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串参数 13 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 字符串参数 13。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串参数 13 的类型。 + /// 字符串参数 14 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 字符串参数 13。 + /// 字符串参数 14。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串参数 13 的类型。 + /// 字符串参数 14 的类型。 + /// 字符串参数 15 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 字符串参数 13。 + /// 字符串参数 14。 + /// 字符串参数 15。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); + return s_CachedStringBuilder.ToString(); + } + + /// + /// 获取格式化字符串。 + /// + /// 字符串参数 1 的类型。 + /// 字符串参数 2 的类型。 + /// 字符串参数 3 的类型。 + /// 字符串参数 4 的类型。 + /// 字符串参数 5 的类型。 + /// 字符串参数 6 的类型。 + /// 字符串参数 7 的类型。 + /// 字符串参数 8 的类型。 + /// 字符串参数 9 的类型。 + /// 字符串参数 10 的类型。 + /// 字符串参数 11 的类型。 + /// 字符串参数 12 的类型。 + /// 字符串参数 13 的类型。 + /// 字符串参数 14 的类型。 + /// 字符串参数 15 的类型。 + /// 字符串参数 16 的类型。 + /// 字符串格式。 + /// 字符串参数 1。 + /// 字符串参数 2。 + /// 字符串参数 3。 + /// 字符串参数 4。 + /// 字符串参数 5。 + /// 字符串参数 6。 + /// 字符串参数 7。 + /// 字符串参数 8。 + /// 字符串参数 9。 + /// 字符串参数 10。 + /// 字符串参数 11。 + /// 字符串参数 12。 + /// 字符串参数 13。 + /// 字符串参数 14。 + /// 字符串参数 15。 + /// 字符串参数 16。 + /// 格式化后的字符串。 + public string Format(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + if (format == null) + { + throw new GameFrameworkException("Format is invalid."); + } + + CheckCachedStringBuilder(); + s_CachedStringBuilder.Length = 0; + s_CachedStringBuilder.AppendFormat(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); + return s_CachedStringBuilder.ToString(); + } + + private static void CheckCachedStringBuilder() + { + if (s_CachedStringBuilder == null) + { + s_CachedStringBuilder = new StringBuilder(StringBuilderCapacity); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultTextHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultTextHelper.cs.meta new file mode 100644 index 0000000..1621105 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultTextHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 371f2cb893135444b96dec3d77b5ec04 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultVersionHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultVersionHelper.cs new file mode 100644 index 0000000..a4d67be --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultVersionHelper.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 默认版本号辅助器。 + /// + public class DefaultVersionHelper : Version.IVersionHelper + { + /// + /// 获取游戏版本号。 + /// + public string GameVersion + { + get + { + return Application.version; + } + } + + /// + /// 获取内部游戏版本号。 + /// + public int InternalGameVersion + { + get + { + return 0; + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultVersionHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultVersionHelper.cs.meta new file mode 100644 index 0000000..1d628be --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/DefaultVersionHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8d95b198d6da721458ed6ffc6fc1697c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/Helper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/Helper.cs new file mode 100644 index 0000000..f91e615 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/Helper.cs @@ -0,0 +1,75 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// 辅助器创建器相关的实用函数。 + /// + public static class Helper + { + /// + /// 创建辅助器。 + /// + /// 要创建的辅助器类型。 + /// 要创建的辅助器类型名称。 + /// 若要创建的辅助器类型为空时,使用的自定义辅助器类型。 + /// 创建的辅助器。 + public static T CreateHelper(string helperTypeName, T customHelper) where T : MonoBehaviour + { + return CreateHelper(helperTypeName, customHelper, 0); + } + + /// + /// 创建辅助器。 + /// + /// 要创建的辅助器类型。 + /// 要创建的辅助器类型名称。 + /// 若要创建的辅助器类型为空时,使用的自定义辅助器类型。 + /// 要创建的辅助器索引。 + /// 创建的辅助器。 + public static T CreateHelper(string helperTypeName, T customHelper, int index) where T : MonoBehaviour + { + T helper = null; + if (!string.IsNullOrEmpty(helperTypeName)) + { + System.Type helperType = Utility.Assembly.GetType(helperTypeName); + if (helperType == null) + { + Log.Warning("Can not find helper type '{0}'.", helperTypeName); + return null; + } + + if (!typeof(T).IsAssignableFrom(helperType)) + { + Log.Warning("Type '{0}' is not assignable from '{1}'.", typeof(T).FullName, helperType.FullName); + return null; + } + + helper = (T)new GameObject().AddComponent(helperType); + } + else if (customHelper == null) + { + Log.Warning("You must set custom helper with '{0}' type first.", typeof(T).FullName); + return null; + } + else if (customHelper.gameObject.InScene()) + { + helper = index > 0 ? Object.Instantiate(customHelper) : customHelper; + } + else + { + helper = Object.Instantiate(customHelper); + } + + return helper; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/Helper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/Helper.cs.meta new file mode 100644 index 0000000..f805aa4 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/Helper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e7b03d310d08d45429a94d6f62c942b4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/Log.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/Log.cs new file mode 100644 index 0000000..d0a5b36 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/Log.cs @@ -0,0 +1,2728 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System.Diagnostics; + +namespace UnityGameFramework.Runtime +{ + /// + /// 日志工具集。 + /// + public static class Log + { + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志内容。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(object message) + { + GameFrameworkLog.Debug(message); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志内容。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string message) + { + GameFrameworkLog.Debug(message); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数的类型。 + /// 日志格式。 + /// 日志参数。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T arg) + { + GameFrameworkLog.Debug(format, arg); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2) + { + GameFrameworkLog.Debug(format, arg1, arg2); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4, arg5); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4, arg5, arg6); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); + } + + /// + /// 打印调试级别日志,用于记录调试类日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志参数 16 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 日志参数 16。 + /// 仅在带有 ENABLE_LOG、ENABLE_DEBUG_LOG 或 ENABLE_DEBUG_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_DEBUG_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + public static void Debug(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + GameFrameworkLog.Debug(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志内容。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(object message) + { + GameFrameworkLog.Info(message); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志内容。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string message) + { + GameFrameworkLog.Info(message); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数的类型。 + /// 日志格式。 + /// 日志参数。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T arg) + { + GameFrameworkLog.Info(format, arg); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2) + { + GameFrameworkLog.Info(format, arg1, arg2); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4, arg5); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4, arg5, arg6); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); + } + + /// + /// 打印信息级别日志,用于记录程序正常运行日志信息。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志参数 16 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 日志参数 16。 + /// 仅在带有 ENABLE_LOG、ENABLE_INFO_LOG、ENABLE_DEBUG_AND_ABOVE_LOG 或 ENABLE_INFO_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_INFO_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + public static void Info(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + GameFrameworkLog.Info(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志内容。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(object message) + { + GameFrameworkLog.Warning(message); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志内容。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string message) + { + GameFrameworkLog.Warning(message); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数的类型。 + /// 日志格式。 + /// 日志参数。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T arg) + { + GameFrameworkLog.Warning(format, arg); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2) + { + GameFrameworkLog.Warning(format, arg1, arg2); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4, arg5); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4, arg5, arg6); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); + } + + /// + /// 打印警告级别日志,建议在发生局部功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志参数 16 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 日志参数 16。 + /// 仅在带有 ENABLE_LOG、ENABLE_WARNING_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG 或 ENABLE_WARNING_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_WARNING_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + public static void Warning(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + GameFrameworkLog.Warning(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志内容。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(object message) + { + GameFrameworkLog.Error(message); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志内容。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string message) + { + GameFrameworkLog.Error(message); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数的类型。 + /// 日志格式。 + /// 日志参数。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T arg) + { + GameFrameworkLog.Error(format, arg); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2) + { + GameFrameworkLog.Error(format, arg1, arg2); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4, arg5); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4, arg5, arg6); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); + } + + /// + /// 打印错误级别日志,建议在发生功能逻辑错误,但尚不会导致游戏崩溃或异常时使用。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志参数 16 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 日志参数 16。 + /// 仅在带有 ENABLE_LOG、ENABLE_ERROR_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG 或 ENABLE_ERROR_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_ERROR_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + public static void Error(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + GameFrameworkLog.Error(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志内容。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(object message) + { + GameFrameworkLog.Fatal(message); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志内容。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string message) + { + GameFrameworkLog.Fatal(message); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数的类型。 + /// 日志格式。 + /// 日志参数。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T arg) + { + GameFrameworkLog.Fatal(format, arg); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2) + { + GameFrameworkLog.Fatal(format, arg1, arg2); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4, arg5); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4, arg5, arg6); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); + } + + /// + /// 打印严重错误级别日志,建议在发生严重错误,可能导致游戏崩溃或异常时使用,此时应尝试重启进程或重建游戏框架。 + /// + /// 日志参数 1 的类型。 + /// 日志参数 2 的类型。 + /// 日志参数 3 的类型。 + /// 日志参数 4 的类型。 + /// 日志参数 5 的类型。 + /// 日志参数 6 的类型。 + /// 日志参数 7 的类型。 + /// 日志参数 8 的类型。 + /// 日志参数 9 的类型。 + /// 日志参数 10 的类型。 + /// 日志参数 11 的类型。 + /// 日志参数 12 的类型。 + /// 日志参数 13 的类型。 + /// 日志参数 14 的类型。 + /// 日志参数 15 的类型。 + /// 日志参数 16 的类型。 + /// 日志格式。 + /// 日志参数 1。 + /// 日志参数 2。 + /// 日志参数 3。 + /// 日志参数 4。 + /// 日志参数 5。 + /// 日志参数 6。 + /// 日志参数 7。 + /// 日志参数 8。 + /// 日志参数 9。 + /// 日志参数 10。 + /// 日志参数 11。 + /// 日志参数 12。 + /// 日志参数 13。 + /// 日志参数 14。 + /// 日志参数 15。 + /// 日志参数 16。 + /// 仅在带有 ENABLE_LOG、ENABLE_FATAL_LOG、ENABLE_DEBUG_AND_ABOVE_LOG、ENABLE_INFO_AND_ABOVE_LOG、ENABLE_WARNING_AND_ABOVE_LOG、ENABLE_ERROR_AND_ABOVE_LOG 或 ENABLE_FATAL_AND_ABOVE_LOG 预编译选项时生效。 + [Conditional("ENABLE_LOG")] + [Conditional("ENABLE_FATAL_LOG")] + [Conditional("ENABLE_DEBUG_AND_ABOVE_LOG")] + [Conditional("ENABLE_INFO_AND_ABOVE_LOG")] + [Conditional("ENABLE_WARNING_AND_ABOVE_LOG")] + [Conditional("ENABLE_ERROR_AND_ABOVE_LOG")] + [Conditional("ENABLE_FATAL_AND_ABOVE_LOG")] + public static void Fatal(string format, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + { + GameFrameworkLog.Fatal(format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/Log.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/Log.cs.meta new file mode 100644 index 0000000..136d75d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/Log.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dea5e7b095c6d3b4ea334c381fcd16fb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/StringExtension.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/StringExtension.cs new file mode 100644 index 0000000..bcb3ea8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/StringExtension.cs @@ -0,0 +1,66 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +/// +/// 对 string 的扩展方法。 +/// +public static class StringExtension +{ + /// + /// 从指定字符串中的指定位置处开始读取一行。 + /// + /// 指定的字符串。 + /// 从指定位置处开始读取一行,读取后将返回下一行开始的位置。 + /// 读取的一行字符串。 + public static string ReadLine(this string rawString, ref int position) + { + if (position < 0) + { + return null; + } + + int length = rawString.Length; + int offset = position; + while (offset < length) + { + char ch = rawString[offset]; + switch (ch) + { + case '\r': + case '\n': + if (offset > position) + { + string line = rawString.Substring(position, offset - position); + position = offset + 1; + if ((ch == '\r') && (position < length) && (rawString[position] == '\n')) + { + position++; + } + + return line; + } + + offset++; + position++; + break; + + default: + offset++; + break; + } + } + + if (offset > position) + { + string line = rawString.Substring(position, offset - position); + position = offset; + return line; + } + + return null; + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/StringExtension.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/StringExtension.cs.meta new file mode 100644 index 0000000..7bcb29f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/StringExtension.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 809e5c16ec9bc7440ab85cb3626d9263 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/UnityExtension.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/UnityExtension.cs new file mode 100644 index 0000000..e71f51a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/UnityExtension.cs @@ -0,0 +1,347 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using UnityEngine; + +/// +/// 对 Unity 的扩展方法。 +/// +public static class UnityExtension +{ + private static readonly List s_CachedTransforms = new List(); + + /// + /// 获取或增加组件。 + /// + /// 要获取或增加的组件。 + /// 目标对象。 + /// 获取或增加的组件。 + public static T GetOrAddComponent(this GameObject gameObject) where T : Component + { + T component = gameObject.GetComponent(); + if (component == null) + { + component = gameObject.AddComponent(); + } + + return component; + } + + /// + /// 获取或增加组件。 + /// + /// 目标对象。 + /// 要获取或增加的组件类型。 + /// 获取或增加的组件。 + public static Component GetOrAddComponent(this GameObject gameObject, Type type) + { + Component component = gameObject.GetComponent(type); + if (component == null) + { + component = gameObject.AddComponent(type); + } + + return component; + } + + /// + /// 获取 GameObject 是否在场景中。 + /// + /// 目标对象。 + /// GameObject 是否在场景中。 + /// 若返回 true,表明此 GameObject 是一个场景中的实例对象;若返回 false,表明此 GameObject 是一个 Prefab。 + public static bool InScene(this GameObject gameObject) + { + return gameObject.scene.name != null; + } + + /// + /// 递归设置游戏对象的层次。 + /// + /// 对象。 + /// 目标层次的编号。 + public static void SetLayerRecursively(this GameObject gameObject, int layer) + { + gameObject.GetComponentsInChildren(true, s_CachedTransforms); + for (int i = 0; i < s_CachedTransforms.Count; i++) + { + s_CachedTransforms[i].gameObject.layer = layer; + } + + s_CachedTransforms.Clear(); + } + + /// + /// 取 的 (x, y, z) 转换为 的 (x, z)。 + /// + /// 要转换的 Vector3。 + /// 转换后的 Vector2。 + public static Vector2 ToVector2(this Vector3 vector3) + { + return new Vector2(vector3.x, vector3.z); + } + + /// + /// 取 的 (x, y) 转换为 的 (x, 0, y)。 + /// + /// 要转换的 Vector2。 + /// 转换后的 Vector3。 + public static Vector3 ToVector3(this Vector2 vector2) + { + return new Vector3(vector2.x, 0f, vector2.y); + } + + /// + /// 取 的 (x, y) 和给定参数 y 转换为 的 (x, 参数 y, y)。 + /// + /// 要转换的 Vector2。 + /// Vector3 的 y 值。 + /// 转换后的 Vector3。 + public static Vector3 ToVector3(this Vector2 vector2, float y) + { + return new Vector3(vector2.x, y, vector2.y); + } + + #region Transform + + /// + /// 设置绝对位置的 x 坐标。 + /// + /// 对象。 + /// x 坐标值。 + public static void SetPositionX(this Transform transform, float newValue) + { + Vector3 v = transform.position; + v.x = newValue; + transform.position = v; + } + + /// + /// 设置绝对位置的 y 坐标。 + /// + /// 对象。 + /// y 坐标值。 + public static void SetPositionY(this Transform transform, float newValue) + { + Vector3 v = transform.position; + v.y = newValue; + transform.position = v; + } + + /// + /// 设置绝对位置的 z 坐标。 + /// + /// 对象。 + /// z 坐标值。 + public static void SetPositionZ(this Transform transform, float newValue) + { + Vector3 v = transform.position; + v.z = newValue; + transform.position = v; + } + + /// + /// 增加绝对位置的 x 坐标。 + /// + /// 对象。 + /// x 坐标值增量。 + public static void AddPositionX(this Transform transform, float deltaValue) + { + Vector3 v = transform.position; + v.x += deltaValue; + transform.position = v; + } + + /// + /// 增加绝对位置的 y 坐标。 + /// + /// 对象。 + /// y 坐标值增量。 + public static void AddPositionY(this Transform transform, float deltaValue) + { + Vector3 v = transform.position; + v.y += deltaValue; + transform.position = v; + } + + /// + /// 增加绝对位置的 z 坐标。 + /// + /// 对象。 + /// z 坐标值增量。 + public static void AddPositionZ(this Transform transform, float deltaValue) + { + Vector3 v = transform.position; + v.z += deltaValue; + transform.position = v; + } + + /// + /// 设置相对位置的 x 坐标。 + /// + /// 对象。 + /// x 坐标值。 + public static void SetLocalPositionX(this Transform transform, float newValue) + { + Vector3 v = transform.localPosition; + v.x = newValue; + transform.localPosition = v; + } + + /// + /// 设置相对位置的 y 坐标。 + /// + /// 对象。 + /// y 坐标值。 + public static void SetLocalPositionY(this Transform transform, float newValue) + { + Vector3 v = transform.localPosition; + v.y = newValue; + transform.localPosition = v; + } + + /// + /// 设置相对位置的 z 坐标。 + /// + /// 对象。 + /// z 坐标值。 + public static void SetLocalPositionZ(this Transform transform, float newValue) + { + Vector3 v = transform.localPosition; + v.z = newValue; + transform.localPosition = v; + } + + /// + /// 增加相对位置的 x 坐标。 + /// + /// 对象。 + /// x 坐标值。 + public static void AddLocalPositionX(this Transform transform, float deltaValue) + { + Vector3 v = transform.localPosition; + v.x += deltaValue; + transform.localPosition = v; + } + + /// + /// 增加相对位置的 y 坐标。 + /// + /// 对象。 + /// y 坐标值。 + public static void AddLocalPositionY(this Transform transform, float deltaValue) + { + Vector3 v = transform.localPosition; + v.y += deltaValue; + transform.localPosition = v; + } + + /// + /// 增加相对位置的 z 坐标。 + /// + /// 对象。 + /// z 坐标值。 + public static void AddLocalPositionZ(this Transform transform, float deltaValue) + { + Vector3 v = transform.localPosition; + v.z += deltaValue; + transform.localPosition = v; + } + + /// + /// 设置相对尺寸的 x 分量。 + /// + /// 对象。 + /// x 分量值。 + public static void SetLocalScaleX(this Transform transform, float newValue) + { + Vector3 v = transform.localScale; + v.x = newValue; + transform.localScale = v; + } + + /// + /// 设置相对尺寸的 y 分量。 + /// + /// 对象。 + /// y 分量值。 + public static void SetLocalScaleY(this Transform transform, float newValue) + { + Vector3 v = transform.localScale; + v.y = newValue; + transform.localScale = v; + } + + /// + /// 设置相对尺寸的 z 分量。 + /// + /// 对象。 + /// z 分量值。 + public static void SetLocalScaleZ(this Transform transform, float newValue) + { + Vector3 v = transform.localScale; + v.z = newValue; + transform.localScale = v; + } + + /// + /// 增加相对尺寸的 x 分量。 + /// + /// 对象。 + /// x 分量增量。 + public static void AddLocalScaleX(this Transform transform, float deltaValue) + { + Vector3 v = transform.localScale; + v.x += deltaValue; + transform.localScale = v; + } + + /// + /// 增加相对尺寸的 y 分量。 + /// + /// 对象。 + /// y 分量增量。 + public static void AddLocalScaleY(this Transform transform, float deltaValue) + { + Vector3 v = transform.localScale; + v.y += deltaValue; + transform.localScale = v; + } + + /// + /// 增加相对尺寸的 z 分量。 + /// + /// 对象。 + /// z 分量增量。 + public static void AddLocalScaleZ(this Transform transform, float deltaValue) + { + Vector3 v = transform.localScale; + v.z += deltaValue; + transform.localScale = v; + } + + /// + /// 二维空间下使 指向指向目标点的算法,使用世界坐标。 + /// + /// 对象。 + /// 要朝向的二维坐标点。 + /// 假定其 forward 向量为 + public static void LookAt2D(this Transform transform, Vector2 lookAtPoint2D) + { + Vector3 vector = lookAtPoint2D.ToVector3() - transform.position; + vector.y = 0f; + + if (vector.magnitude > 0f) + { + transform.rotation = Quaternion.LookRotation(vector.normalized, Vector3.up); + } + } + + #endregion Transform +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/UnityExtension.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/UnityExtension.cs.meta new file mode 100644 index 0000000..7738c7d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Utility/UnityExtension.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 24f918603ece9974690d60aa69d97be2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable.meta new file mode 100644 index 0000000..e345c4f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f71cb3d04c9a3342b05140a90a66e9f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarBoolean.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarBoolean.cs new file mode 100644 index 0000000..1def04d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarBoolean.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.Boolean 变量类。 + /// + public sealed class VarBoolean : Variable + { + /// + /// 初始化 System.Boolean 变量类的新实例。 + /// + public VarBoolean() + { + } + + /// + /// 从 System.Boolean 到 System.Boolean 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarBoolean(bool value) + { + VarBoolean varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.Boolean 变量类到 System.Boolean 的隐式转换。 + /// + /// 值。 + public static implicit operator bool(VarBoolean value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarBoolean.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarBoolean.cs.meta new file mode 100644 index 0000000..10ec55f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarBoolean.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 951d24bf51d09c64e8cd2ac824a363b4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarByte.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarByte.cs new file mode 100644 index 0000000..d238bc7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarByte.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.Byte 变量类。 + /// + public sealed class VarByte : Variable + { + /// + /// 初始化 System.Byte 变量类的新实例。 + /// + public VarByte() + { + } + + /// + /// 从 System.Byte 到 System.Byte 变量类的隐式转换。 + /// + /// 值。 + /// implicit operator 隐式转换关键字 + public static implicit operator VarByte(byte value) + { + VarByte varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.Byte 变量类到 System.Byte 的隐式转换。 + /// + /// 值。 + public static implicit operator byte(VarByte value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarByte.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarByte.cs.meta new file mode 100644 index 0000000..631cca8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarByte.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 028b1842c42f7bf4999e1aaffed3b451 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarByteArray.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarByteArray.cs new file mode 100644 index 0000000..17edeaf --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarByteArray.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.Byte 数组变量类。 + /// + public sealed class VarByteArray : Variable + { + /// + /// 初始化 System.Byte 数组变量类的新实例。 + /// + public VarByteArray() + { + } + + /// + /// 从 System.Byte 数组到 System.Byte 数组变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarByteArray(byte[] value) + { + VarByteArray varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.Byte 数组变量类到 System.Byte 数组的隐式转换。 + /// + /// 值。 + public static implicit operator byte[](VarByteArray value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarByteArray.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarByteArray.cs.meta new file mode 100644 index 0000000..e2ccc9f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarByteArray.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dbb9b35f2ec6f8f4bb8bb6c361eb8ef6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarChar.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarChar.cs new file mode 100644 index 0000000..0a38411 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarChar.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.Char 变量类。 + /// + public sealed class VarChar : Variable + { + /// + /// 初始化 System.Char 变量类的新实例。 + /// + public VarChar() + { + } + + /// + /// 从 System.Char 到 System.Char 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarChar(char value) + { + VarChar varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.Char 变量类到 System.Char 的隐式转换。 + /// + /// 值。 + public static implicit operator char(VarChar value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarChar.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarChar.cs.meta new file mode 100644 index 0000000..3b78eb9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarChar.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 17c91d9b1ebba834385874fcf8c1076a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarCharArray.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarCharArray.cs new file mode 100644 index 0000000..30763cc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarCharArray.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.Char 数组变量类。 + /// + public sealed class VarCharArray : Variable + { + /// + /// 初始化 System.Char 数组变量类的新实例。 + /// + public VarCharArray() + { + } + + /// + /// 从 System.Char 数组到 System.Char 数组变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarCharArray(char[] value) + { + VarCharArray varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.Char 数组变量类到 System.Char 数组的隐式转换。 + /// + /// 值。 + public static implicit operator char[](VarCharArray value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarCharArray.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarCharArray.cs.meta new file mode 100644 index 0000000..64422cc --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarCharArray.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 74c192285e6e9d8469961735fd7bc29e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarColor.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarColor.cs new file mode 100644 index 0000000..61432c3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarColor.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// UnityEngine.Color 变量类。 + /// + public sealed class VarColor : Variable + { + /// + /// 初始化 UnityEngine.Color 变量类的新实例。 + /// + public VarColor() + { + } + + /// + /// 从 UnityEngine.Color 到 UnityEngine.Color 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarColor(Color value) + { + VarColor varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 UnityEngine.Color 变量类到 UnityEngine.Color 的隐式转换。 + /// + /// 值。 + public static implicit operator Color(VarColor value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarColor.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarColor.cs.meta new file mode 100644 index 0000000..f6b2dbe --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarColor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b7b2e4000c824c341bd90a5886dd0893 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarColor32.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarColor32.cs new file mode 100644 index 0000000..02ec02b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarColor32.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// UnityEngine.Color32 变量类。 + /// + public sealed class VarColor32 : Variable + { + /// + /// 初始化 UnityEngine.Color32 变量类的新实例。 + /// + public VarColor32() + { + } + + /// + /// 从 UnityEngine.Color32 到 UnityEngine.Color32 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarColor32(Color32 value) + { + VarColor32 varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 UnityEngine.Color32 变量类到 UnityEngine.Color32 的隐式转换。 + /// + /// 值。 + public static implicit operator Color32(VarColor32 value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarColor32.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarColor32.cs.meta new file mode 100644 index 0000000..c5c4af6 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarColor32.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f31aea41afccdc843a7cc7de09a7fc9e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDateTime.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDateTime.cs new file mode 100644 index 0000000..7d83c79 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDateTime.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using System; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.DateTime 变量类。 + /// + public sealed class VarDateTime : Variable + { + /// + /// 初始化 System.DateTime 变量类的新实例。 + /// + public VarDateTime() + { + } + + /// + /// 从 System.DateTime 到 System.DateTime 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarDateTime(DateTime value) + { + VarDateTime varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.DateTime 变量类到 System.DateTime 的隐式转换。 + /// + /// 值。 + public static implicit operator DateTime(VarDateTime value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDateTime.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDateTime.cs.meta new file mode 100644 index 0000000..7b03c2c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDateTime.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0b58529251d8325439e3988047d2f019 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDecimal.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDecimal.cs new file mode 100644 index 0000000..43257e1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDecimal.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.Decimal 变量类。 + /// + public sealed class VarDecimal : Variable + { + /// + /// 初始化 System.Decimal 变量类的新实例。 + /// + public VarDecimal() + { + } + + /// + /// 从 System.Decimal 到 System.Decimal 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarDecimal(decimal value) + { + VarDecimal varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.Decimal 变量类到 System.Decimal 的隐式转换。 + /// + /// 值。 + public static implicit operator decimal(VarDecimal value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDecimal.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDecimal.cs.meta new file mode 100644 index 0000000..ac5b497 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDecimal.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c8bd5d553ed3aea4485bf78964f09708 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDouble.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDouble.cs new file mode 100644 index 0000000..9b6da5e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDouble.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.Double 变量类。 + /// + public sealed class VarDouble : Variable + { + /// + /// 初始化 System.Double 变量类的新实例。 + /// + public VarDouble() + { + } + + /// + /// 从 System.Double 到 System.Double 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarDouble(double value) + { + VarDouble varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.Double 变量类到 System.Double 的隐式转换。 + /// + /// 值。 + public static implicit operator double(VarDouble value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDouble.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDouble.cs.meta new file mode 100644 index 0000000..98661ba --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarDouble.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 55b52e85a025f734495ed0e888633468 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarGameObject.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarGameObject.cs new file mode 100644 index 0000000..c0cc5c2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarGameObject.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// UnityEngine.GameObject 变量类。 + /// + public sealed class VarGameObject : Variable + { + /// + /// 初始化 UnityEngine.GameObject 变量类的新实例。 + /// + public VarGameObject() + { + } + + /// + /// 从 UnityEngine.GameObject 到 UnityEngine.GameObject 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarGameObject(GameObject value) + { + VarGameObject varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 UnityEngine.GameObject 变量类到 UnityEngine.GameObject 的隐式转换。 + /// + /// 值。 + public static implicit operator GameObject(VarGameObject value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarGameObject.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarGameObject.cs.meta new file mode 100644 index 0000000..7fda629 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarGameObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9c339e4000da5e645993ae5bb3c79554 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt16.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt16.cs new file mode 100644 index 0000000..055656b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt16.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.Int16 变量类。 + /// + public sealed class VarInt16 : Variable + { + /// + /// 初始化 System.Int16 变量类的新实例。 + /// + public VarInt16() + { + } + + /// + /// 从 System.Int16 到 System.Int16 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarInt16(short value) + { + VarInt16 varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.Int16 变量类到 System.Int16 的隐式转换。 + /// + /// 值。 + public static implicit operator short(VarInt16 value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt16.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt16.cs.meta new file mode 100644 index 0000000..4a27d15 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt16.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fb22474f50a73704ebdc00b32ba1fd93 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt32.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt32.cs new file mode 100644 index 0000000..1a04cf9 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt32.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.Int32 变量类。 + /// + public sealed class VarInt32 : Variable + { + /// + /// 初始化 System.Int32 变量类的新实例。 + /// + public VarInt32() + { + } + + /// + /// 从 System.Int32 到 System.Int32 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarInt32(int value) + { + VarInt32 varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.Int32 变量类到 System.Int32 的隐式转换。 + /// + /// 值。 + public static implicit operator int(VarInt32 value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt32.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt32.cs.meta new file mode 100644 index 0000000..8f4d62d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt32.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f82188cc963752848a236f4fed834740 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt64.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt64.cs new file mode 100644 index 0000000..9cdc090 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt64.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.Int64 变量类。 + /// + public sealed class VarInt64 : Variable + { + /// + /// 初始化 System.Int64 变量类的新实例。 + /// + public VarInt64() + { + } + + /// + /// 从 System.Int64 到 System.Int64 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarInt64(long value) + { + VarInt64 varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.Int64 变量类到 System.Int64 的隐式转换。 + /// + /// 值。 + public static implicit operator long(VarInt64 value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt64.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt64.cs.meta new file mode 100644 index 0000000..a52a798 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarInt64.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 13f2695725ed09648a9fc2b506584a0c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarMaterial.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarMaterial.cs new file mode 100644 index 0000000..09f73f3 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarMaterial.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// UnityEngine.Material 变量类。 + /// + public sealed class VarMaterial : Variable + { + /// + /// 初始化 UnityEngine.Material 变量类的新实例。 + /// + public VarMaterial() + { + } + + /// + /// 从 UnityEngine.Material 到 UnityEngine.Material 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarMaterial(Material value) + { + VarMaterial varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 UnityEngine.Material 变量类到 UnityEngine.Material 的隐式转换。 + /// + /// 值。 + public static implicit operator Material(VarMaterial value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarMaterial.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarMaterial.cs.meta new file mode 100644 index 0000000..6b6a0e2 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarMaterial.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 45b6448300498c842a0facd7b2b6d45c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarObject.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarObject.cs new file mode 100644 index 0000000..1d6f175 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarObject.cs @@ -0,0 +1,24 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.Object 变量类。 + /// + public sealed class VarObject : Variable + { + /// + /// 初始化 System.Object 变量类的新实例。 + /// + public VarObject() + { + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarObject.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarObject.cs.meta new file mode 100644 index 0000000..dae3a94 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f3b2d458c0eb0244c905a819c9fec4f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarQuaternion.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarQuaternion.cs new file mode 100644 index 0000000..077ec3f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarQuaternion.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// UnityEngine.Quaternion 变量类。 + /// + public sealed class VarQuaternion : Variable + { + /// + /// 初始化 UnityEngine.Quaternion 变量类的新实例。 + /// + public VarQuaternion() + { + } + + /// + /// 从 UnityEngine.Quaternion 到 UnityEngine.Quaternion 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarQuaternion(Quaternion value) + { + VarQuaternion varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 UnityEngine.Quaternion 变量类到 UnityEngine.Quaternion 的隐式转换。 + /// + /// 值。 + public static implicit operator Quaternion(VarQuaternion value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarQuaternion.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarQuaternion.cs.meta new file mode 100644 index 0000000..213ce68 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarQuaternion.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 411c1800741f3594d80ef8ce06797ca4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarRect.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarRect.cs new file mode 100644 index 0000000..f328111 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarRect.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// UnityEngine.Rect 变量类。 + /// + public sealed class VarRect : Variable + { + /// + /// 初始化 UnityEngine.Rect 变量类的新实例。 + /// + public VarRect() + { + } + + /// + /// 从 UnityEngine.Rect 到 UnityEngine.Rect 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarRect(Rect value) + { + VarRect varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 UnityEngine.Rect 变量类到 UnityEngine.Rect 的隐式转换。 + /// + /// 值。 + public static implicit operator Rect(VarRect value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarRect.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarRect.cs.meta new file mode 100644 index 0000000..8167184 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarRect.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ee11011c267861947bfbd3353b91bd12 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarSByte.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarSByte.cs new file mode 100644 index 0000000..cabd656 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarSByte.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.SByte 变量类。 + /// + public sealed class VarSByte : Variable + { + /// + /// 初始化 System.SByte 变量类的新实例。 + /// + public VarSByte() + { + } + + /// + /// 从 System.SByte 到 System.SByte 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarSByte(sbyte value) + { + VarSByte varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.SByte 变量类到 System.SByte 的隐式转换。 + /// + /// 值。 + public static implicit operator sbyte(VarSByte value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarSByte.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarSByte.cs.meta new file mode 100644 index 0000000..d4a8514 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarSByte.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1e0877a15fd8ef34699d6e817a9c04bd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarSingle.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarSingle.cs new file mode 100644 index 0000000..520d6a8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarSingle.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.Single 变量类。 + /// + public sealed class VarSingle : Variable + { + /// + /// 初始化 System.Single 变量类的新实例。 + /// + public VarSingle() + { + } + + /// + /// 从 System.Single 到 System.Single 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarSingle(float value) + { + VarSingle varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.Single 变量类到 System.Single 的隐式转换。 + /// + /// 值。 + public static implicit operator float(VarSingle value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarSingle.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarSingle.cs.meta new file mode 100644 index 0000000..f53d09e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarSingle.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3a31b440f69e7f04f9afabe202d14550 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarString.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarString.cs new file mode 100644 index 0000000..c44016e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarString.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.String 变量类。 + /// + public sealed class VarString : Variable + { + /// + /// 初始化 System.String 变量类的新实例。 + /// + public VarString() + { + } + + /// + /// 从 System.String 到 System.String 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarString(string value) + { + VarString varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.String 变量类到 System.String 的隐式转换。 + /// + /// 值。 + public static implicit operator string(VarString value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarString.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarString.cs.meta new file mode 100644 index 0000000..a602417 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarString.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d45679f4a06fe6244ad4ff88dca368a4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarTexture.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarTexture.cs new file mode 100644 index 0000000..acd4df5 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarTexture.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// UnityEngine.Texture 变量类。 + /// + public sealed class VarTexture : Variable + { + /// + /// 初始化 UnityEngine.Texture 变量类的新实例。 + /// + public VarTexture() + { + } + + /// + /// 从 UnityEngine.Texture 到 UnityEngine.Texture 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarTexture(Texture value) + { + VarTexture varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 UnityEngine.Texture 变量类到 UnityEngine.Texture 的隐式转换。 + /// + /// 值。 + public static implicit operator Texture(VarTexture value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarTexture.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarTexture.cs.meta new file mode 100644 index 0000000..4f72c27 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarTexture.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c0f43d324b63e5d48933b078ca2cc5f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarTransform.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarTransform.cs new file mode 100644 index 0000000..f017173 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarTransform.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// UnityEngine.Transform 变量类。 + /// + public sealed class VarTransform : Variable + { + /// + /// 初始化 UnityEngine.Transform 变量类的新实例。 + /// + public VarTransform() + { + } + + /// + /// 从 UnityEngine.Transform 到 UnityEngine.Transform 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarTransform(Transform value) + { + VarTransform varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 UnityEngine.Transform 变量类到 UnityEngine.Transform 的隐式转换。 + /// + /// 值。 + public static implicit operator Transform(VarTransform value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarTransform.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarTransform.cs.meta new file mode 100644 index 0000000..51d1324 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarTransform.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dff6037db6354304d82d9aaf079d5c63 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt16.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt16.cs new file mode 100644 index 0000000..09a2dd7 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt16.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.UInt16 变量类。 + /// + public sealed class VarUInt16 : Variable + { + /// + /// 初始化 System.UInt16 变量类的新实例。 + /// + public VarUInt16() + { + } + + /// + /// 从 System.UInt16 到 System.UInt16 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarUInt16(ushort value) + { + VarUInt16 varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.UInt16 变量类到 System.UInt16 的隐式转换。 + /// + /// 值。 + public static implicit operator ushort(VarUInt16 value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt16.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt16.cs.meta new file mode 100644 index 0000000..6303851 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt16.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c158720cba058174995252c289e561b8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt32.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt32.cs new file mode 100644 index 0000000..e95cdf0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt32.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.UInt32 变量类。 + /// + public sealed class VarUInt32 : Variable + { + /// + /// 初始化 System.UInt32 变量类的新实例。 + /// + public VarUInt32() + { + } + + /// + /// 从 System.UInt32 到 System.UInt32 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarUInt32(uint value) + { + VarUInt32 varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.UInt32 变量类到 System.UInt32 的隐式转换。 + /// + /// 值。 + public static implicit operator uint(VarUInt32 value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt32.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt32.cs.meta new file mode 100644 index 0000000..2a2b4e1 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt32.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ec67b25d499a2d34fa1c450a9d165ab0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt64.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt64.cs new file mode 100644 index 0000000..f140563 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt64.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; + +namespace UnityGameFramework.Runtime +{ + /// + /// System.UInt64 变量类。 + /// + public sealed class VarUInt64 : Variable + { + /// + /// 初始化 System.UInt64 变量类的新实例。 + /// + public VarUInt64() + { + } + + /// + /// 从 System.UInt64 到 System.UInt64 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarUInt64(ulong value) + { + VarUInt64 varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 System.UInt64 变量类到 System.UInt64 的隐式转换。 + /// + /// 值。 + public static implicit operator ulong(VarUInt64 value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt64.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt64.cs.meta new file mode 100644 index 0000000..78ae7a0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUInt64.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d0195ac43c505b248a7d9d41beff1436 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUnityObject.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUnityObject.cs new file mode 100644 index 0000000..8caa56e --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUnityObject.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// UnityEngine.Object 变量类。 + /// + public sealed class VarUnityObject : Variable + { + /// + /// 初始化 UnityEngine.Object 变量类的新实例。 + /// + public VarUnityObject() + { + } + + /// + /// 从 UnityEngine.Object 到 UnityEngine.Object 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarUnityObject(Object value) + { + VarUnityObject varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 UnityEngine.Object 变量类到 UnityEngine.Object 的隐式转换。 + /// + /// 值。 + public static implicit operator Object(VarUnityObject value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUnityObject.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUnityObject.cs.meta new file mode 100644 index 0000000..b0adfea --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarUnityObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc9d733f793fc00468089f8cdd6c1835 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector2.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector2.cs new file mode 100644 index 0000000..09280ee --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector2.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// UnityEngine.Vector2 变量类。 + /// + public sealed class VarVector2 : Variable + { + /// + /// 初始化 UnityEngine.Vector2 变量类的新实例。 + /// + public VarVector2() + { + } + + /// + /// 从 UnityEngine.Vector2 到 UnityEngine.Vector2 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarVector2(Vector2 value) + { + VarVector2 varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 UnityEngine.Vector2 变量类到 UnityEngine.Vector2 的隐式转换。 + /// + /// 值。 + public static implicit operator Vector2(VarVector2 value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector2.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector2.cs.meta new file mode 100644 index 0000000..78ad39a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector2.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef03a8d73e6be4348802fc28c4777c49 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector3.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector3.cs new file mode 100644 index 0000000..e6d381a --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector3.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// UnityEngine.Vector3 变量类。 + /// + public sealed class VarVector3 : Variable + { + /// + /// 初始化 UnityEngine.Vector3 变量类的新实例。 + /// + public VarVector3() + { + } + + /// + /// 从 UnityEngine.Vector3 到 UnityEngine.Vector3 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarVector3(Vector3 value) + { + VarVector3 varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 UnityEngine.Vector3 变量类到 UnityEngine.Vector3 的隐式转换。 + /// + /// 值。 + public static implicit operator Vector3(VarVector3 value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector3.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector3.cs.meta new file mode 100644 index 0000000..0fd91e0 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector3.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b041a74c058fe54418735010bcfd2a21 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector4.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector4.cs new file mode 100644 index 0000000..476526b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector4.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// UnityEngine.Vector4 变量类。 + /// + public sealed class VarVector4 : Variable + { + /// + /// 初始化 UnityEngine.Vector4 变量类的新实例。 + /// + public VarVector4() + { + } + + /// + /// 从 UnityEngine.Vector4 到 UnityEngine.Vector4 变量类的隐式转换。 + /// + /// 值。 + public static implicit operator VarVector4(Vector4 value) + { + VarVector4 varValue = ReferencePool.Acquire(); + varValue.Value = value; + return varValue; + } + + /// + /// 从 UnityEngine.Vector4 变量类到 UnityEngine.Vector4 的隐式转换。 + /// + /// 值。 + public static implicit operator Vector4(VarVector4 value) + { + return value.Value; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector4.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector4.cs.meta new file mode 100644 index 0000000..f6d7301 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/Variable/VarVector4.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 30950f09797d4354e883c8c4d2caa7b7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest.meta new file mode 100644 index 0000000..cf8106c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 66fef66090127fe46a41b9c2b8f79880 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/UnityWebRequestAgentHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/UnityWebRequestAgentHelper.cs new file mode 100644 index 0000000..542fa48 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/UnityWebRequestAgentHelper.cs @@ -0,0 +1,186 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.WebRequest; +using System; +#if UNITY_5_4_OR_NEWER +using UnityEngine.Networking; +#else +using UnityEngine.Experimental.Networking; +#endif +using Utility = GameFramework.Utility; + +namespace UnityGameFramework.Runtime +{ + /// + /// 使用 UnityWebRequest 实现的 Web 请求代理辅助器。 + /// + public class UnityWebRequestAgentHelper : WebRequestAgentHelperBase, IDisposable + { + private UnityWebRequest m_UnityWebRequest = null; + private bool m_Disposed = false; + + private EventHandler m_WebRequestAgentHelperCompleteEventHandler = null; + private EventHandler m_WebRequestAgentHelperErrorEventHandler = null; + + /// + /// Web 请求代理辅助器完成事件。 + /// + public override event EventHandler WebRequestAgentHelperComplete + { + add + { + m_WebRequestAgentHelperCompleteEventHandler += value; + } + remove + { + m_WebRequestAgentHelperCompleteEventHandler -= value; + } + } + + /// + /// Web 请求代理辅助器错误事件。 + /// + public override event EventHandler WebRequestAgentHelperError + { + add + { + m_WebRequestAgentHelperErrorEventHandler += value; + } + remove + { + m_WebRequestAgentHelperErrorEventHandler -= value; + } + } + + /// + /// 通过 Web 请求代理辅助器发送请求。 + /// + /// 要发送的远程地址。 + /// 用户自定义数据。 + public override void Request(string webRequestUri, object userData) + { + if (m_WebRequestAgentHelperCompleteEventHandler == null || m_WebRequestAgentHelperErrorEventHandler == null) + { + Log.Fatal("Web request agent helper handler is invalid."); + return; + } + + WWWFormInfo wwwFormInfo = (WWWFormInfo)userData; + if (wwwFormInfo.WWWForm == null) + { + m_UnityWebRequest = UnityWebRequest.Get(webRequestUri); + } + else + { + m_UnityWebRequest = UnityWebRequest.Post(webRequestUri, wwwFormInfo.WWWForm); + } + +#if UNITY_2017_2_OR_NEWER + m_UnityWebRequest.SendWebRequest(); +#else + m_UnityWebRequest.Send(); +#endif + } + + /// + /// 通过 Web 请求代理辅助器发送请求。 + /// + /// 要发送的远程地址。 + /// 要发送的数据流。 + /// 用户自定义数据。 + public override void Request(string webRequestUri, byte[] postData, object userData) + { + if (m_WebRequestAgentHelperCompleteEventHandler == null || m_WebRequestAgentHelperErrorEventHandler == null) + { + Log.Fatal("Web request agent helper handler is invalid."); + return; + } + + m_UnityWebRequest = UnityWebRequest.PostWwwForm(webRequestUri, Utility.Converter.GetString(postData)); +#if UNITY_2017_2_OR_NEWER + m_UnityWebRequest.SendWebRequest(); +#else + m_UnityWebRequest.Send(); +#endif + } + + /// + /// 重置 Web 请求代理辅助器。 + /// + public override void Reset() + { + if (m_UnityWebRequest != null) + { + m_UnityWebRequest.Dispose(); + m_UnityWebRequest = null; + } + } + + /// + /// 释放资源。 + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// 释放资源。 + /// + /// 释放资源标记。 + protected virtual void Dispose(bool disposing) + { + if (m_Disposed) + { + return; + } + + if (disposing) + { + if (m_UnityWebRequest != null) + { + m_UnityWebRequest.Dispose(); + m_UnityWebRequest = null; + } + } + + m_Disposed = true; + } + + private void Update() + { + if (m_UnityWebRequest == null || !m_UnityWebRequest.isDone) + { + return; + } + + bool isError = false; +#if UNITY_2020_2_OR_NEWER + isError = m_UnityWebRequest.result != UnityWebRequest.Result.Success; +#elif UNITY_2017_1_OR_NEWER + isError = m_UnityWebRequest.isNetworkError || m_UnityWebRequest.isHttpError; +#else + isError = m_UnityWebRequest.isError; +#endif + if (isError) + { + WebRequestAgentHelperErrorEventArgs webRequestAgentHelperErrorEventArgs = WebRequestAgentHelperErrorEventArgs.Create(m_UnityWebRequest.error); + m_WebRequestAgentHelperErrorEventHandler(this, webRequestAgentHelperErrorEventArgs); + ReferencePool.Release(webRequestAgentHelperErrorEventArgs); + } + else if (m_UnityWebRequest.downloadHandler.isDone) + { + WebRequestAgentHelperCompleteEventArgs webRequestAgentHelperCompleteEventArgs = WebRequestAgentHelperCompleteEventArgs.Create(m_UnityWebRequest.downloadHandler.data); + m_WebRequestAgentHelperCompleteEventHandler(this, webRequestAgentHelperCompleteEventArgs); + ReferencePool.Release(webRequestAgentHelperCompleteEventArgs); + } + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/UnityWebRequestAgentHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/UnityWebRequestAgentHelper.cs.meta new file mode 100644 index 0000000..ad86a1b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/UnityWebRequestAgentHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7e3014b70cd4acd41bed5c829dff3c30 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WWWFormInfo.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WWWFormInfo.cs new file mode 100644 index 0000000..c89333c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WWWFormInfo.cs @@ -0,0 +1,54 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + internal sealed class WWWFormInfo : IReference + { + private WWWForm m_WWWForm; + private object m_UserData; + + public WWWFormInfo() + { + m_WWWForm = null; + m_UserData = null; + } + + public WWWForm WWWForm + { + get + { + return m_WWWForm; + } + } + + public object UserData + { + get + { + return m_UserData; + } + } + + public static WWWFormInfo Create(WWWForm wwwForm, object userData) + { + WWWFormInfo wwwFormInfo = ReferencePool.Acquire(); + wwwFormInfo.m_WWWForm = wwwForm; + wwwFormInfo.m_UserData = userData; + return wwwFormInfo; + } + + public void Clear() + { + m_WWWForm = null; + m_UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WWWFormInfo.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WWWFormInfo.cs.meta new file mode 100644 index 0000000..0df35db --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WWWFormInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 88d3d7e0a6b8b374783b6dc413adfbd7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WWWWebRequestAgentHelper.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WWWWebRequestAgentHelper.cs new file mode 100644 index 0000000..69a5c7f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WWWWebRequestAgentHelper.cs @@ -0,0 +1,166 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +#if !UNITY_2018_3_OR_NEWER + +using GameFramework; +using GameFramework.WebRequest; +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// WWW Web 请求代理辅助器。 + /// + public class WWWWebRequestAgentHelper : WebRequestAgentHelperBase, IDisposable + { + private WWW m_WWW = null; + private bool m_Disposed = false; + + private EventHandler m_WebRequestAgentHelperCompleteEventHandler = null; + private EventHandler m_WebRequestAgentHelperErrorEventHandler = null; + + /// + /// Web 请求代理辅助器完成事件。 + /// + public override event EventHandler WebRequestAgentHelperComplete + { + add + { + m_WebRequestAgentHelperCompleteEventHandler += value; + } + remove + { + m_WebRequestAgentHelperCompleteEventHandler -= value; + } + } + + /// + /// Web 请求代理辅助器错误事件。 + /// + public override event EventHandler WebRequestAgentHelperError + { + add + { + m_WebRequestAgentHelperErrorEventHandler += value; + } + remove + { + m_WebRequestAgentHelperErrorEventHandler -= value; + } + } + + /// + /// 通过 Web 请求代理辅助器发送请求。 + /// + /// 要发送的远程地址。 + /// 用户自定义数据。 + public override void Request(string webRequestUri, object userData) + { + if (m_WebRequestAgentHelperCompleteEventHandler == null || m_WebRequestAgentHelperErrorEventHandler == null) + { + Log.Fatal("Web request agent helper handler is invalid."); + return; + } + + WWWFormInfo wwwFormInfo = (WWWFormInfo)userData; + if (wwwFormInfo.WWWForm == null) + { + m_WWW = new WWW(webRequestUri); + } + else + { + m_WWW = new WWW(webRequestUri, wwwFormInfo.WWWForm); + } + } + + /// + /// 通过 Web 请求代理辅助器发送请求。 + /// + /// 要发送的远程地址。 + /// 要发送的数据流。 + /// 用户自定义数据。 + public override void Request(string webRequestUri, byte[] postData, object userData) + { + if (m_WebRequestAgentHelperCompleteEventHandler == null || m_WebRequestAgentHelperErrorEventHandler == null) + { + Log.Fatal("Web request agent helper handler is invalid."); + return; + } + + m_WWW = new WWW(webRequestUri, postData); + } + + /// + /// 重置 Web 请求代理辅助器。 + /// + public override void Reset() + { + if (m_WWW != null) + { + m_WWW.Dispose(); + m_WWW = null; + } + } + + /// + /// 释放资源。 + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// 释放资源。 + /// + /// 释放资源标记。 + protected virtual void Dispose(bool disposing) + { + if (m_Disposed) + { + return; + } + + if (disposing) + { + if (m_WWW != null) + { + m_WWW.Dispose(); + m_WWW = null; + } + } + + m_Disposed = true; + } + + private void Update() + { + if (m_WWW == null || !m_WWW.isDone) + { + return; + } + + if (!string.IsNullOrEmpty(m_WWW.error)) + { + WebRequestAgentHelperErrorEventArgs webRequestAgentHelperErrorEventArgs = WebRequestAgentHelperErrorEventArgs.Create(m_WWW.error); + m_WebRequestAgentHelperErrorEventHandler(this, webRequestAgentHelperErrorEventArgs); + ReferencePool.Release(webRequestAgentHelperErrorEventArgs); + } + else + { + WebRequestAgentHelperCompleteEventArgs webRequestAgentHelperCompleteEventArgs = WebRequestAgentHelperCompleteEventArgs.Create(m_WWW.bytes); + m_WebRequestAgentHelperCompleteEventHandler(this, webRequestAgentHelperCompleteEventArgs); + ReferencePool.Release(webRequestAgentHelperCompleteEventArgs); + } + } + } +} + +#endif diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WWWWebRequestAgentHelper.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WWWWebRequestAgentHelper.cs.meta new file mode 100644 index 0000000..bd828ba --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WWWWebRequestAgentHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 58f7b74a3eef2eb478e90ba95fe21d9f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestAgentHelperBase.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestAgentHelperBase.cs new file mode 100644 index 0000000..c52343d --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestAgentHelperBase.cs @@ -0,0 +1,49 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework.WebRequest; +using System; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// Web 请求代理辅助器基类。 + /// + public abstract class WebRequestAgentHelperBase : MonoBehaviour, IWebRequestAgentHelper + { + /// + /// Web 请求代理辅助器完成事件。 + /// + public abstract event EventHandler WebRequestAgentHelperComplete; + + /// + /// Web 请求代理辅助器错误事件。 + /// + public abstract event EventHandler WebRequestAgentHelperError; + + /// + /// 通过 Web 请求代理辅助器发送 Web 请求。 + /// + /// Web 请求地址。 + /// 用户自定义数据。 + public abstract void Request(string webRequestUri, object userData); + + /// + /// 通过 Web 请求代理辅助器发送 Web 请求。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// 用户自定义数据。 + public abstract void Request(string webRequestUri, byte[] postData, object userData); + + /// + /// 重置 Web 请求代理辅助器。 + /// + public abstract void Reset(); + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestAgentHelperBase.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestAgentHelperBase.cs.meta new file mode 100644 index 0000000..b391d02 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestAgentHelperBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 435dc9e1aa25c4344b27aa10088d4f1a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestComponent.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestComponent.cs new file mode 100644 index 0000000..43682a8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestComponent.cs @@ -0,0 +1,564 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.WebRequest; +using System.Collections.Generic; +using UnityEngine; + +namespace UnityGameFramework.Runtime +{ + /// + /// Web 请求组件。 + /// + [DisallowMultipleComponent] + [AddComponentMenu("Game Framework/Web Request")] + public sealed class WebRequestComponent : GameFrameworkComponent + { + private const int DefaultPriority = 0; + + private IWebRequestManager m_WebRequestManager = null; + private EventComponent m_EventComponent = null; + + [SerializeField] + private Transform m_InstanceRoot = null; + + [SerializeField] + private string m_WebRequestAgentHelperTypeName = "UnityGameFramework.Runtime.UnityWebRequestAgentHelper"; + + [SerializeField] + private WebRequestAgentHelperBase m_CustomWebRequestAgentHelper = null; + + [SerializeField] + private int m_WebRequestAgentHelperCount = 1; + + [SerializeField] + private float m_Timeout = 30f; + + /// + /// 获取 Web 请求代理总数量。 + /// + public int TotalAgentCount + { + get + { + return m_WebRequestManager.TotalAgentCount; + } + } + + /// + /// 获取可用 Web 请求代理数量。 + /// + public int FreeAgentCount + { + get + { + return m_WebRequestManager.FreeAgentCount; + } + } + + /// + /// 获取工作中 Web 请求代理数量。 + /// + public int WorkingAgentCount + { + get + { + return m_WebRequestManager.WorkingAgentCount; + } + } + + /// + /// 获取等待 Web 请求数量。 + /// + public int WaitingTaskCount + { + get + { + return m_WebRequestManager.WaitingTaskCount; + } + } + + /// + /// 获取或设置 Web 请求超时时长,以秒为单位。 + /// + public float Timeout + { + get + { + return m_WebRequestManager.Timeout; + } + set + { + m_WebRequestManager.Timeout = m_Timeout = value; + } + } + + /// + /// 游戏框架组件初始化。 + /// + protected override void Awake() + { + base.Awake(); + + m_WebRequestManager = GameFrameworkEntry.GetModule(); + if (m_WebRequestManager == null) + { + Log.Fatal("Web request manager is invalid."); + return; + } + + m_WebRequestManager.Timeout = m_Timeout; + m_WebRequestManager.WebRequestStart += OnWebRequestStart; + m_WebRequestManager.WebRequestSuccess += OnWebRequestSuccess; + m_WebRequestManager.WebRequestFailure += OnWebRequestFailure; + } + + private void Start() + { + m_EventComponent = GameEntry.GetComponent(); + if (m_EventComponent == null) + { + Log.Fatal("Event component is invalid."); + return; + } + + if (m_InstanceRoot == null) + { + m_InstanceRoot = new GameObject("Web Request Agent Instances").transform; + m_InstanceRoot.SetParent(gameObject.transform); + m_InstanceRoot.localScale = Vector3.one; + } + + for (int i = 0; i < m_WebRequestAgentHelperCount; i++) + { + AddWebRequestAgentHelper(i); + } + } + + /// + /// 根据 Web 请求任务的序列编号获取 Web 请求任务的信息。 + /// + /// 要获取信息的 Web 请求任务的序列编号。 + /// Web 请求任务的信息。 + public TaskInfo GetWebRequestInfo(int serialId) + { + return m_WebRequestManager.GetWebRequestInfo(serialId); + } + + /// + /// 根据 Web 请求任务的标签获取 Web 请求任务的信息。 + /// + /// 要获取信息的 Web 请求任务的标签。 + /// Web 请求任务的信息。 + public TaskInfo[] GetWebRequestInfos(string tag) + { + return m_WebRequestManager.GetWebRequestInfos(tag); + } + + /// + /// 根据 Web 请求任务的标签获取 Web 请求任务的信息。 + /// + /// 要获取信息的 Web 请求任务的标签。 + /// Web 请求任务的信息。 + public void GetAllWebRequestInfos(string tag, List results) + { + m_WebRequestManager.GetAllWebRequestInfos(tag, results); + } + + /// + /// 获取所有 Web 请求任务的信息。 + /// + /// 所有 Web 请求任务的信息。 + public TaskInfo[] GetAllWebRequestInfos() + { + return m_WebRequestManager.GetAllWebRequestInfos(); + } + + /// + /// 获取所有 Web 请求任务的信息。 + /// + /// 所有 Web 请求任务的信息。 + public void GetAllWebRequestInfos(List results) + { + m_WebRequestManager.GetAllWebRequestInfos(results); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri) + { + return AddWebRequest(webRequestUri, null, null, null, DefaultPriority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData) + { + return AddWebRequest(webRequestUri, postData, null, null, DefaultPriority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// WWW 表单。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, WWWForm wwwForm) + { + return AddWebRequest(webRequestUri, null, wwwForm, null, DefaultPriority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的标签。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, string tag) + { + return AddWebRequest(webRequestUri, null, null, tag, DefaultPriority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, int priority) + { + return AddWebRequest(webRequestUri, null, null, null, priority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, object userData) + { + return AddWebRequest(webRequestUri, null, null, null, DefaultPriority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, string tag) + { + return AddWebRequest(webRequestUri, postData, null, tag, DefaultPriority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// WWW 表单。 + /// Web 请求任务的标签。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, WWWForm wwwForm, string tag) + { + return AddWebRequest(webRequestUri, null, wwwForm, tag, DefaultPriority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, int priority) + { + return AddWebRequest(webRequestUri, postData, null, null, priority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// WWW 表单。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, WWWForm wwwForm, int priority) + { + return AddWebRequest(webRequestUri, null, wwwForm, null, priority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, object userData) + { + return AddWebRequest(webRequestUri, postData, null, null, DefaultPriority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// WWW 表单。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, WWWForm wwwForm, object userData) + { + return AddWebRequest(webRequestUri, null, wwwForm, null, DefaultPriority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, string tag, int priority) + { + return AddWebRequest(webRequestUri, null, null, tag, priority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的标签。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, string tag, object userData) + { + return AddWebRequest(webRequestUri, null, null, tag, DefaultPriority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, int priority, object userData) + { + return AddWebRequest(webRequestUri, null, null, null, priority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, string tag, int priority) + { + return AddWebRequest(webRequestUri, postData, null, tag, priority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// WWW 表单。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, WWWForm wwwForm, string tag, int priority) + { + return AddWebRequest(webRequestUri, null, wwwForm, tag, priority, null); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, string tag, object userData) + { + return AddWebRequest(webRequestUri, postData, null, tag, DefaultPriority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// WWW 表单。 + /// Web 请求任务的标签。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, WWWForm wwwForm, string tag, object userData) + { + return AddWebRequest(webRequestUri, null, wwwForm, tag, DefaultPriority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, int priority, object userData) + { + return AddWebRequest(webRequestUri, postData, null, null, priority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// WWW 表单。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, WWWForm wwwForm, int priority, object userData) + { + return AddWebRequest(webRequestUri, null, wwwForm, null, priority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, string tag, int priority, object userData) + { + return AddWebRequest(webRequestUri, null, null, tag, priority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, byte[] postData, string tag, int priority, object userData) + { + return AddWebRequest(webRequestUri, postData, null, tag, priority, userData); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// WWW 表单。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + public int AddWebRequest(string webRequestUri, WWWForm wwwForm, string tag, int priority, object userData) + { + return AddWebRequest(webRequestUri, null, wwwForm, tag, priority, userData); + } + + /// + /// 根据 Web 请求任务的序列编号移除 Web 请求任务。 + /// + /// 要移除 Web 请求任务的序列编号。 + /// 是否移除 Web 请求任务成功。 + public bool RemoveWebRequest(int serialId) + { + return m_WebRequestManager.RemoveWebRequest(serialId); + } + + /// + /// 根据 Web 请求任务的标签移除 Web 请求任务。 + /// + /// 要移除 Web 请求任务的标签。 + /// 移除 Web 请求任务的数量。 + public int RemoveWebRequests(string tag) + { + return m_WebRequestManager.RemoveWebRequests(tag); + } + + /// + /// 移除所有 Web 请求任务。 + /// + /// 移除 Web 请求任务的数量。 + public int RemoveAllWebRequests() + { + return m_WebRequestManager.RemoveAllWebRequests(); + } + + /// + /// 增加 Web 请求代理辅助器。 + /// + /// Web 请求代理辅助器索引。 + private void AddWebRequestAgentHelper(int index) + { + WebRequestAgentHelperBase webRequestAgentHelper = Helper.CreateHelper(m_WebRequestAgentHelperTypeName, m_CustomWebRequestAgentHelper, index); + if (webRequestAgentHelper == null) + { + Log.Error("Can not create web request agent helper."); + return; + } + + webRequestAgentHelper.name = Utility.Text.Format("Web Request Agent Helper - {0}", index); + Transform transform = webRequestAgentHelper.transform; + transform.SetParent(m_InstanceRoot); + transform.localScale = Vector3.one; + + m_WebRequestManager.AddWebRequestAgentHelper(webRequestAgentHelper); + } + + /// + /// 增加 Web 请求任务。 + /// + /// Web 请求地址。 + /// 要发送的数据流。 + /// WWW 表单。 + /// Web 请求任务的标签。 + /// Web 请求任务的优先级。 + /// 用户自定义数据。 + /// 新增 Web 请求任务的序列编号。 + private int AddWebRequest(string webRequestUri, byte[] postData, WWWForm wwwForm, string tag, int priority, object userData) + { + return m_WebRequestManager.AddWebRequest(webRequestUri, postData, tag, priority, WWWFormInfo.Create(wwwForm, userData)); + } + + private void OnWebRequestStart(object sender, GameFramework.WebRequest.WebRequestStartEventArgs e) + { + m_EventComponent.Fire(this, WebRequestStartEventArgs.Create(e)); + } + + private void OnWebRequestSuccess(object sender, GameFramework.WebRequest.WebRequestSuccessEventArgs e) + { + m_EventComponent.Fire(this, WebRequestSuccessEventArgs.Create(e)); + } + + private void OnWebRequestFailure(object sender, GameFramework.WebRequest.WebRequestFailureEventArgs e) + { + Log.Warning("Web request failure, web request serial id '{0}', web request uri '{1}', error message '{2}'.", e.SerialId, e.WebRequestUri, e.ErrorMessage); + m_EventComponent.Fire(this, WebRequestFailureEventArgs.Create(e)); + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestComponent.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestComponent.cs.meta new file mode 100644 index 0000000..6bbb4c8 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 02988897571ac8b49a59c1a50037bd88 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestFailureEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestFailureEventArgs.cs new file mode 100644 index 0000000..46a150f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestFailureEventArgs.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// Web 请求失败事件。 + /// + public sealed class WebRequestFailureEventArgs : GameEventArgs + { + /// + /// Web 请求失败事件编号。 + /// + public static readonly int EventId = typeof(WebRequestFailureEventArgs).GetHashCode(); + + /// + /// 初始化 Web 请求失败事件的新实例。 + /// + public WebRequestFailureEventArgs() + { + SerialId = 0; + WebRequestUri = null; + ErrorMessage = null; + UserData = null; + } + + /// + /// 获取 Web 请求失败事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取 Web 请求任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取 Web 请求地址。 + /// + public string WebRequestUri + { + get; + private set; + } + + /// + /// 获取错误信息。 + /// + public string ErrorMessage + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建 Web 请求失败事件。 + /// + /// 内部事件。 + /// 创建的 Web 请求失败事件。 + public static WebRequestFailureEventArgs Create(GameFramework.WebRequest.WebRequestFailureEventArgs e) + { + WWWFormInfo wwwFormInfo = (WWWFormInfo)e.UserData; + WebRequestFailureEventArgs webRequestFailureEventArgs = ReferencePool.Acquire(); + webRequestFailureEventArgs.SerialId = e.SerialId; + webRequestFailureEventArgs.WebRequestUri = e.WebRequestUri; + webRequestFailureEventArgs.ErrorMessage = e.ErrorMessage; + webRequestFailureEventArgs.UserData = wwwFormInfo.UserData; + ReferencePool.Release(wwwFormInfo); + return webRequestFailureEventArgs; + } + + /// + /// 清理 Web 请求失败事件。 + /// + public override void Clear() + { + SerialId = 0; + WebRequestUri = null; + ErrorMessage = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestFailureEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestFailureEventArgs.cs.meta new file mode 100644 index 0000000..b93a924 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestFailureEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 582d860310370aa47b4fa671963e0200 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestStartEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestStartEventArgs.cs new file mode 100644 index 0000000..2042b0f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestStartEventArgs.cs @@ -0,0 +1,96 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// Web 请求开始事件。 + /// + public sealed class WebRequestStartEventArgs : GameEventArgs + { + /// + /// Web 请求开始事件编号。 + /// + public static readonly int EventId = typeof(WebRequestStartEventArgs).GetHashCode(); + + /// + /// 初始化 Web 请求开始事件的新实例。 + /// + public WebRequestStartEventArgs() + { + SerialId = 0; + WebRequestUri = null; + UserData = null; + } + + /// + /// 获取 Web 请求开始事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取 Web 请求任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取 Web 请求地址。 + /// + public string WebRequestUri + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 创建 Web 请求开始事件。 + /// + /// 内部事件。 + /// 创建的 Web 请求开始事件。 + public static WebRequestStartEventArgs Create(GameFramework.WebRequest.WebRequestStartEventArgs e) + { + WWWFormInfo wwwFormInfo = (WWWFormInfo)e.UserData; + WebRequestStartEventArgs webRequestStartEventArgs = ReferencePool.Acquire(); + webRequestStartEventArgs.SerialId = e.SerialId; + webRequestStartEventArgs.WebRequestUri = e.WebRequestUri; + webRequestStartEventArgs.UserData = wwwFormInfo.UserData; + return webRequestStartEventArgs; + } + + /// + /// 清理 Web 请求开始事件。 + /// + public override void Clear() + { + SerialId = 0; + WebRequestUri = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestStartEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestStartEventArgs.cs.meta new file mode 100644 index 0000000..6007375 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestStartEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3f73533092cec3d498691d5805a8f856 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestSuccessEventArgs.cs b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestSuccessEventArgs.cs new file mode 100644 index 0000000..915967c --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestSuccessEventArgs.cs @@ -0,0 +1,111 @@ +//------------------------------------------------------------ +// Game Framework +// Copyright © 2013-2021 Jiang Yin. All rights reserved. +// Homepage: https://gameframework.cn/ +// Feedback: mailto:ellan@gameframework.cn +//------------------------------------------------------------ + +using GameFramework; +using GameFramework.Event; + +namespace UnityGameFramework.Runtime +{ + /// + /// Web 请求成功事件。 + /// + public sealed class WebRequestSuccessEventArgs : GameEventArgs + { + private byte[] m_WebResponseBytes = null; + + /// + /// Web 请求成功事件编号。 + /// + public static readonly int EventId = typeof(WebRequestSuccessEventArgs).GetHashCode(); + + /// + /// 初始化 Web 请求成功事件的新实例。 + /// + public WebRequestSuccessEventArgs() + { + SerialId = 0; + WebRequestUri = null; + m_WebResponseBytes = null; + UserData = null; + } + + /// + /// 获取 Web 请求成功事件编号。 + /// + public override int Id + { + get + { + return EventId; + } + } + + /// + /// 获取 Web 请求任务的序列编号。 + /// + public int SerialId + { + get; + private set; + } + + /// + /// 获取 Web 请求地址。 + /// + public string WebRequestUri + { + get; + private set; + } + + /// + /// 获取用户自定义数据。 + /// + public object UserData + { + get; + private set; + } + + /// + /// 获取 Web 响应的数据流。 + /// + /// Web 响应的数据流。 + public byte[] GetWebResponseBytes() + { + return m_WebResponseBytes; + } + + /// + /// 创建 Web 请求成功事件。 + /// + /// 内部事件。 + /// 创建的 Web 请求成功事件。 + public static WebRequestSuccessEventArgs Create(GameFramework.WebRequest.WebRequestSuccessEventArgs e) + { + WWWFormInfo wwwFormInfo = (WWWFormInfo)e.UserData; + WebRequestSuccessEventArgs webRequestSuccessEventArgs = ReferencePool.Acquire(); + webRequestSuccessEventArgs.SerialId = e.SerialId; + webRequestSuccessEventArgs.WebRequestUri = e.WebRequestUri; + webRequestSuccessEventArgs.m_WebResponseBytes = e.GetWebResponseBytes(); + webRequestSuccessEventArgs.UserData = wwwFormInfo.UserData; + ReferencePool.Release(wwwFormInfo); + return webRequestSuccessEventArgs; + } + + /// + /// 清理 Web 请求成功事件。 + /// + public override void Clear() + { + SerialId = 0; + WebRequestUri = null; + m_WebResponseBytes = null; + UserData = null; + } + } +} diff --git a/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestSuccessEventArgs.cs.meta new file mode 100644 index 0000000..d545c35 --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/Runtime/UnityGameFramework/WebRequest/WebRequestSuccessEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 12523ea48f6be044592256bf32605f5d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.gameframework/package.json b/Packages/com.bywaystudios.gameframework/package.json new file mode 100644 index 0000000..8fc813b --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/package.json @@ -0,0 +1,11 @@ +{ + "name": "com.bywaystudios.gameframework", + "displayName": "GameFramework", + "version": "0.1.4", + "description": "Custom GameFramework code", + "repository": { + "url": "git@gitea.bywaystudios.com:wangshiyao/GameFrameworkPackage.git", + "type": "git", + "revision": "301b54d8cb21d2bbeb382815a938a5f36feded30" + } +} diff --git a/Packages/com.bywaystudios.gameframework/package.json.meta b/Packages/com.bywaystudios.gameframework/package.json.meta new file mode 100644 index 0000000..33a4d4f --- /dev/null +++ b/Packages/com.bywaystudios.gameframework/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d7134fc52ccdf1240a2f118533f0bc5b +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime.meta b/Packages/com.bywaystudios.thrift/Runtime.meta new file mode 100644 index 0000000..ef0e018 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3a88ce6a250be42458ee10a717243914 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Collections.meta b/Packages/com.bywaystudios.thrift/Runtime/Collections.meta new file mode 100644 index 0000000..d6703a0 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Collections.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9570817580e1c32429e39fada8dd7b18 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Collections/TCollections.cs b/Packages/com.bywaystudios.thrift/Runtime/Collections/TCollections.cs new file mode 100644 index 0000000..21ee3bb --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Collections/TCollections.cs @@ -0,0 +1,115 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Collections; +using System.Collections.Generic; + +namespace Thrift.Collections +{ + // ReSharper disable once InconsistentNaming + public static class TCollections + { + /// + /// This will return true if the two collections are value-wise the same. + /// If the collection contains a collection, the collections will be compared using this method. + /// + public static bool Equals(IEnumerable first, IEnumerable second) + { + if (first == null && second == null) + { + return true; + } + + if (first == null || second == null) + { + return false; + } + + // for dictionaries, we need to compare keys and values separately + // because KeyValuePair.Equals() will not do what we want + var fdict = first as IDictionary; + var sdict = second as IDictionary; + if ((fdict != null) || (sdict != null)) + { + if ((fdict == null) || (sdict == null)) + return false; + return TCollections.Equals(fdict.Keys, sdict.Keys) + && TCollections.Equals(fdict.Values, sdict.Values); + } + + var fiter = first.GetEnumerator(); + var siter = second.GetEnumerator(); + + var fnext = fiter.MoveNext(); + var snext = siter.MoveNext(); + + while (fnext && snext) + { + var fenum = fiter.Current as IEnumerable; + var senum = siter.Current as IEnumerable; + + if (fenum != null && senum != null) + { + if (!Equals(fenum, senum)) + { + return false; + } + } + else if (fenum == null ^ senum == null) + { + return false; + } + else if (!Equals(fiter.Current, siter.Current)) + { + return false; + } + + fnext = fiter.MoveNext(); + snext = siter.MoveNext(); + } + + return fnext == snext; + } + + /// + /// This returns a hashcode based on the value of the enumerable. + /// + public static int GetHashCode(IEnumerable enumerable) + { + if (enumerable == null) + { + return 0; + } + + var hashcode = 0; + + foreach (var obj in enumerable) + { + var objHash = (obj is IEnumerable enum2) ? GetHashCode(enum2) : obj.GetHashCode(); + + unchecked + { + hashcode = (hashcode * 397) ^ (objHash); + } + } + + return hashcode; + } + + + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Collections/TCollections.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Collections/TCollections.cs.meta new file mode 100644 index 0000000..dbbd69a --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Collections/TCollections.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6bd25820bab7e434aab147a0e6c0e8e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Collections/THashSet.cs b/Packages/com.bywaystudios.thrift/Runtime/Collections/THashSet.cs new file mode 100644 index 0000000..fc2a507 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Collections/THashSet.cs @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Thrift.Collections +{ + // ReSharper disable once InconsistentNaming + [Obsolete("deprecated, use HashSet instead")] + public class THashSet : System.Collections.Generic.HashSet + { + public THashSet() + : base() + { + } + + public THashSet(int capacity) +#if NET5_0_OR_GREATER + : base(capacity) +#elif NETFRAMEWORK || NETSTANDARD + : base(/*capacity not supported*/) +#else +#error Unknown platform +#endif + { + } + + public THashSet(IEnumerable collection) + : base(collection) + { + } + + } +} + diff --git a/Packages/com.bywaystudios.thrift/Runtime/Collections/THashSet.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Collections/THashSet.cs.meta new file mode 100644 index 0000000..89570ea --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Collections/THashSet.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e4336f3dc60386743b1c02f11df6fc99 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/GlobalSuppressions.cs b/Packages/com.bywaystudios.thrift/Runtime/GlobalSuppressions.cs new file mode 100644 index 0000000..cb5fc01 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/GlobalSuppressions.cs @@ -0,0 +1,34 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + + +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +// suppress certain messages for compatibility reasons with older C# versions we want to support +[assembly: SuppressMessage("Style", "IDE0057", Justification = "compatibility", Scope = "module")] +[assembly: SuppressMessage("Style", "IDE0066", Justification = "compatibility", Scope = "module")] +[assembly: SuppressMessage("Style", "IDE0090", Justification = "compatibility", Scope = "module")] +[assembly: SuppressMessage("Style", "IDE0063", Justification = "compatibility", Scope = "module")] +[assembly: SuppressMessage("Style", "IDE0130", Justification = "compatibility", Scope = "module")] +[assembly: SuppressMessage("Style", "IDE0290", Justification = "compatibility", Scope = "module")] +[assembly: SuppressMessage("Style", "CS0114", Justification = "known issue, see JIRA ticket", Scope = "module")] + diff --git a/Packages/com.bywaystudios.thrift/Runtime/GlobalSuppressions.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/GlobalSuppressions.cs.meta new file mode 100644 index 0000000..c2ddcbf --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/GlobalSuppressions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 595997754e2b7f541b41beda5001eabe +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Properties.meta b/Packages/com.bywaystudios.thrift/Runtime/Properties.meta new file mode 100644 index 0000000..94eb87e --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Properties.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5646b840c862f5a43a9f7fd65fd98e5f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Properties/AssemblyInfo.cs b/Packages/com.bywaystudios.thrift/Runtime/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..84be980 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Properties/AssemblyInfo.cs @@ -0,0 +1,56 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Thrift")] +[assembly: AssemblyDescription("C# .NET Core bindings for the Apache Thrift RPC system")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +//@TODO where to put License information? + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a exType in this assembly from +// COM, set the ComVisible attribute to true on that exType. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("df3f8ef0-e0a3-4c86-a65b-8ec84e016b1d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("0.22.0.0")] +[assembly: AssemblyFileVersion("0.22.0.0")] diff --git a/Packages/com.bywaystudios.thrift/Runtime/Properties/AssemblyInfo.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Properties/AssemblyInfo.cs.meta new file mode 100644 index 0000000..dd46057 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Properties/AssemblyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cc3f9dc06d8829e43ab512a42384f133 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol.meta new file mode 100644 index 0000000..39b15a0 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 172a2294fc8d1c74c9afd1ea617e1b86 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities.meta new file mode 100644 index 0000000..421321a --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c6156f3fc3227424282ffe1caa5276ff +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TField.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TField.cs new file mode 100644 index 0000000..92fd41a --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TField.cs @@ -0,0 +1,40 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0290 // net8 - primary CTOR + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TField + { + public TField(string name, TType type, short id) + { + Name = name; + Type = type; + ID = id; + } + + public string Name { get; set; } + + public TType Type { get; set; } + + // ReSharper disable once InconsistentNaming - do not rename - it used for generation + public short ID { get; set; } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TField.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TField.cs.meta new file mode 100644 index 0000000..66497d6 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TField.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4cf4634e90ef156469d9c18a5ef260ba +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TList.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TList.cs new file mode 100644 index 0000000..7e5c545 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TList.cs @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0290 // net8 - primary CTOR + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TList + { + public TList(TType elementType, int count) + { + ElementType = elementType; + Count = count; + } + + public TType ElementType { get; set; } + + public int Count { get; set; } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TList.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TList.cs.meta new file mode 100644 index 0000000..7d835c0 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e853389f4c494204897e587c81be25ca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMap.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMap.cs new file mode 100644 index 0000000..fba5780 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMap.cs @@ -0,0 +1,39 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0290 // net8 - primary CTOR + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TMap + { + public TMap(TType keyType, TType valueType, int count) + { + KeyType = keyType; + ValueType = valueType; + Count = count; + } + + public TType KeyType { get; set; } + + public TType ValueType { get; set; } + + public int Count { get; set; } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMap.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMap.cs.meta new file mode 100644 index 0000000..a8bf785 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMap.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4c32933786e22b34286eb36df8f3c354 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMessage.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMessage.cs new file mode 100644 index 0000000..2e586ea --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMessage.cs @@ -0,0 +1,40 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0290 // net8 - primary CTOR + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TMessage + { + public TMessage(string name, TMessageType type, int seqid) + { + Name = name; + Type = type; + SeqID = seqid; + } + + public string Name { get; set; } + + public TMessageType Type { get; set; } + + // ReSharper disable once InconsistentNaming - do not rename - it used for generation + public int SeqID { get; set; } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMessage.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMessage.cs.meta new file mode 100644 index 0000000..8e33d8a --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMessage.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 930f6d7df6e483743b9814df89e7f4ff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMessageType.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMessageType.cs new file mode 100644 index 0000000..24d663e --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMessageType.cs @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public enum TMessageType + { + Call = 1, + Reply = 2, + Exception = 3, + Oneway = 4 + } +} \ No newline at end of file diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMessageType.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMessageType.cs.meta new file mode 100644 index 0000000..de6bc19 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TMessageType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a12e210a3b515904c9efc20848c86157 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TSet.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TSet.cs new file mode 100644 index 0000000..d29cc0d --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TSet.cs @@ -0,0 +1,41 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0290 // net8 - primary CTOR + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TSet + { + public TSet(TType elementType, int count) + { + ElementType = elementType; + Count = count; + } + + public TSet(TList list) + : this(list.ElementType, list.Count) + { + } + + public TType ElementType { get; set; } + + public int Count { get; set; } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TSet.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TSet.cs.meta new file mode 100644 index 0000000..21ccf25 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TSet.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f793acd60eaa194baa0acc12bd2363c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TStruct.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TStruct.cs new file mode 100644 index 0000000..b2fd000 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TStruct.cs @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0290 // net8 - primary CTOR + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public readonly struct TStruct + { + public TStruct(string name) + { + Name = name; + } + + public string Name { get; } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TStruct.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TStruct.cs.meta new file mode 100644 index 0000000..ab0f07f --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TStruct.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7375aae91c68c944a812e233bdf45f7d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TType.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TType.cs new file mode 100644 index 0000000..2f3037b --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TType.cs @@ -0,0 +1,38 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public enum TType : byte + { + Stop = 0, + Void = 1, + Bool = 2, + Byte = 3, + Double = 4, + I16 = 6, + I32 = 8, + I64 = 10, + String = 11, + Struct = 12, + Map = 13, + Set = 14, + List = 15, + Uuid = 16 + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TType.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TType.cs.meta new file mode 100644 index 0000000..2fa9d09 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Entities/TType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: aca0928aaf4273349b4a3aaab6c86eab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TBase.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TBase.cs new file mode 100644 index 0000000..09bb43f --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TBase.cs @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Threading; +using System.Threading.Tasks; + +#pragma warning disable IDE1006 // some interfaces here are intentionally not I-prefixed + +namespace Thrift.Protocol +{ + public interface TUnionBase + { + Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken = default); + } + + // ReSharper disable once InconsistentNaming + public interface TBase : TUnionBase + { + Task ReadAsync(TProtocol tProtocol, CancellationToken cancellationToken = default); + } + +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TBase.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TBase.cs.meta new file mode 100644 index 0000000..45058d3 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d678ef8837850994788ab62b1041d807 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TBinaryProtocol.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TBinaryProtocol.cs new file mode 100644 index 0000000..44fa9f7 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TBinaryProtocol.cs @@ -0,0 +1,496 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Buffers.Binary; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0290 // net8 - primary CTOR + +namespace Thrift.Protocol +{ + // ReSharper disable once InconsistentNaming + public class TBinaryProtocol : TProtocol + { + protected const uint VersionMask = 0xffff0000; + protected const uint Version1 = 0x80010000; + + protected readonly bool StrictRead; + protected readonly bool StrictWrite; + + // minimize memory allocations by means of an preallocated bytes buffer + // The value of 128 is arbitrarily chosen, the required minimum size must be sizeof(long) + private readonly byte[] PreAllocatedBuffer = new byte[128]; + + public TBinaryProtocol(TTransport trans) + : this(trans, false, true) + { + } + + public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite) + : base(trans) + { + StrictRead = strictRead; + StrictWrite = strictWrite; + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (StrictWrite) + { + var version = Version1 | (uint) message.Type; + await WriteI32Async((int) version, cancellationToken); + await WriteStringAsync(message.Name, cancellationToken); + await WriteI32Async(message.SeqID, cancellationToken); + } + else + { + await WriteStringAsync(message.Name, cancellationToken); + await WriteByteAsync((sbyte) message.Type, cancellationToken); + await WriteI32Async(message.SeqID, cancellationToken); + } + } + + public override Task WriteMessageEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override Task WriteStructEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + await WriteByteAsync((sbyte) field.Type, cancellationToken); + await WriteI16Async(field.ID, cancellationToken); + } + + public override Task WriteFieldEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + await WriteByteAsync((sbyte) TType.Stop, cancellationToken); + } + + public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + PreAllocatedBuffer[0] = (byte)map.KeyType; + PreAllocatedBuffer[1] = (byte)map.ValueType; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 2, cancellationToken); + + await WriteI32Async(map.Count, cancellationToken); + } + + public override Task WriteMapEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + await WriteByteAsync((sbyte) list.ElementType, cancellationToken); + await WriteI32Async(list.Count, cancellationToken); + } + + public override Task WriteListEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + await WriteByteAsync((sbyte) set.ElementType, cancellationToken); + await WriteI32Async(set.Count, cancellationToken); + } + + public override Task WriteSetEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + await WriteByteAsync(b ? (sbyte) 1 : (sbyte) 0, cancellationToken); + } + + public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + PreAllocatedBuffer[0] = (byte)b; + + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + } + public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + BinaryPrimitives.WriteInt16BigEndian(PreAllocatedBuffer, i16); + + await Trans.WriteAsync(PreAllocatedBuffer, 0, 2, cancellationToken); + } + + public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + BinaryPrimitives.WriteInt32BigEndian(PreAllocatedBuffer, i32); + + await Trans.WriteAsync(PreAllocatedBuffer, 0, 4, cancellationToken); + } + + + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + BinaryPrimitives.WriteInt64BigEndian(PreAllocatedBuffer, i64); + + await Trans.WriteAsync(PreAllocatedBuffer, 0, 8, cancellationToken); + } + + public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + await WriteI64Async(BitConverter.DoubleToInt64Bits(d), cancellationToken); + } + + + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + await WriteI32Async(bytes.Length, cancellationToken); + await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); + } + + public override async Task WriteUuidAsync(Guid uuid, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var bytes = uuid.SwapByteOrder().ToByteArray(); + await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); + } + + public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var message = new TMessage(); + var size = await ReadI32Async(cancellationToken); + if (size < 0) + { + var version = (uint) size & VersionMask; + if (version != Version1) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, + $"Bad version in ReadMessageBegin: {version}"); + } + message.Type = (TMessageType) (size & 0x000000ff); + message.Name = await ReadStringAsync(cancellationToken); + message.SeqID = await ReadI32Async(cancellationToken); + } + else + { + if (StrictRead) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, + "Missing version in ReadMessageBegin, old client?"); + } + message.Name = (size > 0) ? await ReadStringBodyAsync(size, cancellationToken) : string.Empty; + message.Type = (TMessageType) await ReadByteAsync(cancellationToken); + message.SeqID = await ReadI32Async(cancellationToken); + } + return message; + } + + public override Task ReadMessageEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + Transport.ResetMessageSizeAndConsumedBytes(); + return Task.CompletedTask; + } + + public override ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return new ValueTask(AnonymousStruct); + } + + public override Task ReadStructEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var type = (TType)await ReadByteAsync(cancellationToken); + if (type == TType.Stop) + { + return StopField; + } + + return new TField { + Type = type, + ID = await ReadI16Async(cancellationToken) + }; + } + + public override Task ReadFieldEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var map = new TMap + { + KeyType = (TType) await ReadByteAsync(cancellationToken), + ValueType = (TType) await ReadByteAsync(cancellationToken), + Count = await ReadI32Async(cancellationToken) + }; + CheckReadBytesAvailable(map); + return map; + } + + public override Task ReadMapEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var list = new TList + { + ElementType = (TType) await ReadByteAsync(cancellationToken), + Count = await ReadI32Async(cancellationToken) + }; + CheckReadBytesAvailable(list); + return list; + } + + public override Task ReadListEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var set = new TSet + { + ElementType = (TType) await ReadByteAsync(cancellationToken), + Count = await ReadI32Async(cancellationToken) + }; + CheckReadBytesAvailable(set); + return set; + } + + public override Task ReadSetEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async ValueTask ReadBoolAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + return await ReadByteAsync(cancellationToken) == 1; + } + + public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + return (sbyte)PreAllocatedBuffer[0]; + } + + public override async ValueTask ReadI16Async(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 2, cancellationToken); + var result = BinaryPrimitives.ReadInt16BigEndian(PreAllocatedBuffer); + return result; + } + + public override async ValueTask ReadI32Async(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 4, cancellationToken); + + var result = BinaryPrimitives.ReadInt32BigEndian(PreAllocatedBuffer); + + return result; + } + + public override async ValueTask ReadI64Async(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 8, cancellationToken); + return BinaryPrimitives.ReadInt64BigEndian(PreAllocatedBuffer); + } + + public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var d = await ReadI64Async(cancellationToken); + return BitConverter.Int64BitsToDouble(d); + } + + public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var size = await ReadI32Async(cancellationToken); + Transport.CheckReadBytesAvailable(size); + var buf = new byte[size]; + await Trans.ReadAllAsync(buf, 0, size, cancellationToken); + return buf; + } + + public override async ValueTask ReadUuidAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + Transport.CheckReadBytesAvailable(16); // = sizeof(uuid) + var buf = new byte[16]; + await Trans.ReadAllAsync(buf, 0, 16, cancellationToken); + return new Guid(buf).SwapByteOrder(); + } + + public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var size = await ReadI32Async(cancellationToken); + return size > 0 ? await ReadStringBodyAsync(size, cancellationToken) : string.Empty; + } + + private async ValueTask ReadStringBodyAsync(int size, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (size <= PreAllocatedBuffer.Length) + { + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, size, cancellationToken); + return Encoding.UTF8.GetString(PreAllocatedBuffer, 0, size); + } + + Transport.CheckReadBytesAvailable(size); + var buf = new byte[size]; + await Trans.ReadAllAsync(buf, 0, size, cancellationToken); + return Encoding.UTF8.GetString(buf, 0, buf.Length); + } + + // Return the minimum number of bytes a type will consume on the wire + public override int GetMinSerializedSize(TType type) + { + switch (type) + { + case TType.Stop: return 0; + case TType.Void: return 0; + case TType.Bool: return sizeof(byte); + case TType.Byte: return sizeof(byte); + case TType.Double: return sizeof(double); + case TType.I16: return sizeof(short); + case TType.I32: return sizeof(int); + case TType.I64: return sizeof(long); + case TType.String: return sizeof(int); // string length + case TType.Struct: return 0; // empty struct + case TType.Map: return sizeof(int); // element count + case TType.Set: return sizeof(int); // element count + case TType.List: return sizeof(int); // element count + case TType.Uuid: return 16; // uuid bytes + default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "unrecognized type code"); + } + } + + public class Factory : TProtocolFactory + { + protected readonly bool StrictRead; + protected readonly bool StrictWrite; + + // emtpy default CTOR required + public Factory() + : this(false, true) + { + } + + public Factory(bool strictRead, bool strictWrite) + { + StrictRead = strictRead; + StrictWrite = strictWrite; + } + + public override TProtocol GetProtocol(TTransport trans) + { + return new TBinaryProtocol(trans, StrictRead, StrictWrite); + } + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TBinaryProtocol.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TBinaryProtocol.cs.meta new file mode 100644 index 0000000..bb1c92f --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TBinaryProtocol.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 560b2c8f00f662f46a9ebd661e8b62bb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TCompactProtocol.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TCompactProtocol.cs new file mode 100644 index 0000000..1fd7e50 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TCompactProtocol.cs @@ -0,0 +1,866 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Buffers; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0301 // net8 - simplified collection init + +namespace Thrift.Protocol +{ + + // ReSharper disable once InconsistentNaming + public class TCompactProtocol : TProtocol + { + private const byte ProtocolId = 0x82; + private const byte Version = 1; + private const byte VersionMask = 0x1f; // 0001 1111 + private const byte TypeMask = 0xE0; // 1110 0000 + private const byte TypeBits = 0x07; // 0000 0111 + private const int TypeShiftAmount = 5; + + private const byte NoTypeOverride = 0xFF; + + // ReSharper disable once InconsistentNaming + private static readonly byte[] TTypeToCompactType = new byte[17]; + private static readonly TType[] CompactTypeToTType = new TType[14]; + + /// + /// Used to keep track of the last field for the current and previous structs, so we can do the delta stuff. + /// + private readonly Stack _lastField = new Stack(15); + + /// + /// If we encounter a boolean field begin, save the TField here so it can have the value incorporated. + /// + private TField? _booleanField; + + /// + /// If we Read a field header, and it's a boolean field, save the boolean value here so that ReadBool can use it. + /// + private bool? _boolValue; + + private short _lastFieldId; + + // minimize memory allocations by means of an preallocated bytes buffer + // The value of 128 is arbitrarily chosen, the required minimum size must be sizeof(long) + private readonly byte[] PreAllocatedBuffer = new byte[128]; + + private struct VarInt + { + public byte[] bytes; + public int count; + } + + // minimize memory allocations by means of an preallocated VarInt buffer + private VarInt PreAllocatedVarInt = new VarInt() + { + bytes = new byte[10], // see Int64ToVarInt() + count = 0 + }; + + + + + public TCompactProtocol(TTransport trans) + : base(trans) + { + TTypeToCompactType[(int)TType.Stop] = Types.Stop; + TTypeToCompactType[(int)TType.Bool] = Types.BooleanTrue; + TTypeToCompactType[(int)TType.Byte] = Types.Byte; + TTypeToCompactType[(int)TType.I16] = Types.I16; + TTypeToCompactType[(int)TType.I32] = Types.I32; + TTypeToCompactType[(int)TType.I64] = Types.I64; + TTypeToCompactType[(int)TType.Double] = Types.Double; + TTypeToCompactType[(int)TType.String] = Types.Binary; + TTypeToCompactType[(int)TType.List] = Types.List; + TTypeToCompactType[(int)TType.Set] = Types.Set; + TTypeToCompactType[(int)TType.Map] = Types.Map; + TTypeToCompactType[(int)TType.Struct] = Types.Struct; + TTypeToCompactType[(int)TType.Uuid] = Types.Uuid; + + CompactTypeToTType[Types.Stop] = TType.Stop; + CompactTypeToTType[Types.BooleanTrue] = TType.Bool; + CompactTypeToTType[Types.BooleanFalse] = TType.Bool; + CompactTypeToTType[Types.Byte] = TType.Byte; + CompactTypeToTType[Types.I16] = TType.I16; + CompactTypeToTType[Types.I32] = TType.I32; + CompactTypeToTType[Types.I64] = TType.I64; + CompactTypeToTType[Types.Double] = TType.Double; + CompactTypeToTType[Types.Binary] = TType.String; + CompactTypeToTType[Types.List] = TType.List; + CompactTypeToTType[Types.Set] = TType.Set; + CompactTypeToTType[Types.Map] = TType.Map; + CompactTypeToTType[Types.Struct] = TType.Struct; + CompactTypeToTType[Types.Uuid] = TType.Uuid; + } + + public void Reset() + { + _lastField.Clear(); + _lastFieldId = 0; + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + PreAllocatedBuffer[0] = ProtocolId; + PreAllocatedBuffer[1] = (byte)((Version & VersionMask) | (((uint)message.Type << TypeShiftAmount) & TypeMask)); + await Trans.WriteAsync(PreAllocatedBuffer, 0, 2, cancellationToken); + + Int32ToVarInt((uint) message.SeqID, ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); + + await WriteStringAsync(message.Name, cancellationToken); + } + + public override Task WriteMessageEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + /// + /// Write a struct begin. This doesn't actually put anything on the wire. We + /// use it as an opportunity to put special placeholder markers on the field + /// stack so we can get the field id deltas correct. + /// + public override Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + _lastField.Push(_lastFieldId); + _lastFieldId = 0; + + return Task.CompletedTask; + } + + public override Task WriteStructEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + _lastFieldId = _lastField.Pop(); + + return Task.CompletedTask; + } + + private async Task WriteFieldBeginInternalAsync(TField field, byte fieldType, CancellationToken cancellationToken) + { + // if there's a exType override passed in, use that. Otherwise ask GetCompactType(). + if (fieldType == NoTypeOverride) + fieldType = GetCompactType(field.Type); + + + // check if we can use delta encoding for the field id + if (field.ID > _lastFieldId) + { + var delta = field.ID - _lastFieldId; + if (delta <= 15) + { + // Write them together + PreAllocatedBuffer[0] = (byte)((delta << 4) | fieldType); + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + _lastFieldId = field.ID; + return; + } + } + + // Write them separate + PreAllocatedBuffer[0] = fieldType; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + await WriteI16Async(field.ID, cancellationToken); + _lastFieldId = field.ID; + } + + public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) + { + if (field.Type == TType.Bool) + { + _booleanField = field; + } + else + { + await WriteFieldBeginInternalAsync(field, NoTypeOverride, cancellationToken); + } + } + + public override Task WriteFieldEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + PreAllocatedBuffer[0] = Types.Stop; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + } + + protected async Task WriteCollectionBeginAsync(TType elemType, int size, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + /* + Abstract method for writing the start of lists and sets. List and sets on + the wire differ only by the exType indicator. + */ + + if (size <= 14) + { + PreAllocatedBuffer[0] = (byte)((size << 4) | GetCompactType(elemType)); + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + } + else + { + PreAllocatedBuffer[0] = (byte)(0xf0 | GetCompactType(elemType)); + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + + Int32ToVarInt((uint) size, ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); + } + } + + public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) + { + await WriteCollectionBeginAsync(list.ElementType, list.Count, cancellationToken); + } + + public override Task WriteListEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + await WriteCollectionBeginAsync(set.ElementType, set.Count, cancellationToken); + } + + public override Task WriteSetEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + /* + Write a boolean value. Potentially, this could be a boolean field, in + which case the field header info isn't written yet. If so, decide what the + right exType header is for the value and then Write the field header. + Otherwise, Write a single byte. + */ + + if (_booleanField != null) + { + // we haven't written the field header yet + var type = b ? Types.BooleanTrue : Types.BooleanFalse; + await WriteFieldBeginInternalAsync(_booleanField.Value, type, cancellationToken); + _booleanField = null; + } + else + { + // we're not part of a field, so just write the value. + PreAllocatedBuffer[0] = b ? Types.BooleanTrue : Types.BooleanFalse; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + } + } + + public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + PreAllocatedBuffer[0] = (byte)b; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + } + + public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + Int32ToVarInt(IntToZigzag(i16), ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); + } + + private static void Int32ToVarInt(uint n, ref VarInt varint) + { + // Write an i32 as a varint. Results in 1 - 5 bytes on the wire. + varint.count = 0; + Debug.Assert(varint.bytes.Length >= 5); + + while (true) + { + if ((n & ~0x7F) == 0) + { + varint.bytes[varint.count++] = (byte)n; + break; + } + + varint.bytes[varint.count++] = (byte)((n & 0x7F) | 0x80); + n >>= 7; + } + } + + public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + Int32ToVarInt(IntToZigzag(i32), ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); + } + + static private void Int64ToVarInt(ulong n, ref VarInt varint) + { + // Write an i64 as a varint. Results in 1-10 bytes on the wire. + varint.count = 0; + Debug.Assert(varint.bytes.Length >= 10); + + while (true) + { + if ((n & ~(ulong)0x7FL) == 0) + { + varint.bytes[varint.count++] = (byte)n; + break; + } + varint.bytes[varint.count++] = (byte)((n & 0x7F) | 0x80); + n >>= 7; + } + } + + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + Int64ToVarInt(LongToZigzag(i64), ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); + } + + public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + BinaryPrimitives.WriteInt64LittleEndian(PreAllocatedBuffer, BitConverter.DoubleToInt64Bits(d)); + await Trans.WriteAsync(PreAllocatedBuffer, 0, 8, cancellationToken); + } + + public override async Task WriteStringAsync(string str, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var buf = ArrayPool.Shared.Rent(Encoding.UTF8.GetByteCount(str)); + try + { + var numberOfBytes = Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0); + + Int32ToVarInt((uint)numberOfBytes, ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); + await Trans.WriteAsync(buf, 0, numberOfBytes, cancellationToken); + } + finally + { + ArrayPool.Shared.Return(buf); + } + } + + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + Int32ToVarInt((uint) bytes.Length, ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); + await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); + } + + public override async Task WriteUuidAsync(Guid uuid, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var bytes = uuid.SwapByteOrder().ToByteArray(); + await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); + } + + public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (map.Count == 0) + { + PreAllocatedBuffer[0] = 0; + await Trans.WriteAsync( PreAllocatedBuffer, 0, 1, cancellationToken); + } + else + { + Int32ToVarInt((uint) map.Count, ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); + + PreAllocatedBuffer[0] = (byte)((GetCompactType(map.KeyType) << 4) | GetCompactType(map.ValueType)); + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + } + } + + public override Task WriteMapEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + var protocolId = (byte) await ReadByteAsync(cancellationToken); + if (protocolId != ProtocolId) + { + throw new TProtocolException($"Expected protocol id {ProtocolId:X} but got {protocolId:X}"); + } + + var versionAndType = (byte) await ReadByteAsync(cancellationToken); + var version = (byte) (versionAndType & VersionMask); + + if (version != Version) + { + throw new TProtocolException($"Expected version {Version} but got {version}"); + } + + var type = (byte) ((versionAndType >> TypeShiftAmount) & TypeBits); + var seqid = (int) await ReadVarInt32Async(cancellationToken); + var messageName = await ReadStringAsync(cancellationToken); + + return new TMessage(messageName, (TMessageType) type, seqid); + } + + public override Task ReadMessageEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + Transport.ResetMessageSizeAndConsumedBytes(); + return Task.CompletedTask; + } + + public override ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + _lastField.Push(_lastFieldId); + _lastFieldId = 0; + + return new ValueTask(AnonymousStruct); + } + + public override Task ReadStructEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + /* + Doesn't actually consume any wire data, just removes the last field for + this struct from the field stack. + */ + + // consume the last field we Read off the wire. + _lastFieldId = _lastField.Pop(); + + return Task.CompletedTask; + } + + public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) + { + // Read a field header off the wire. + var type = (byte) await ReadByteAsync(cancellationToken); + + // if it's a stop, then we can return immediately, as the struct is over. + if (type == Types.Stop) + { + return StopField; + } + + + // mask off the 4 MSB of the exType header. it could contain a field id delta. + var modifier = (short) ((type & 0xf0) >> 4); + var compactType = (byte)(type & 0x0f); + + short fieldId; + if (modifier == 0) + { + fieldId = await ReadI16Async(cancellationToken); + } + else + { + fieldId = (short) (_lastFieldId + modifier); + } + + var ttype = GetTType(compactType); + var field = new TField(string.Empty, ttype, fieldId); + + // if this happens to be a boolean field, the value is encoded in the exType + if( ttype == TType.Bool) + { + _boolValue = (compactType == Types.BooleanTrue); + } + + // push the new field onto the field stack so we can keep the deltas going. + _lastFieldId = field.ID; + return field; + } + + public override Task ReadFieldEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + /* + Read a map header off the wire. If the size is zero, skip Reading the key + and value exType. This means that 0-length maps will yield TMaps without the + "correct" types. + */ + + var size = (int) await ReadVarInt32Async(cancellationToken); + var keyAndValueType = size == 0 ? (byte) 0 : (byte) await ReadByteAsync(cancellationToken); + var map = new TMap(GetTType((byte) (keyAndValueType >> 4)), GetTType((byte) (keyAndValueType & 0xf)), size); + CheckReadBytesAvailable(map); + return map; + } + + public override Task ReadMapEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) + { + /* + Read a set header off the wire. If the set size is 0-14, the size will + be packed into the element exType header. If it's a longer set, the 4 MSB + of the element exType header will be 0xF, and a varint will follow with the + true size. + */ + + return new TSet(await ReadListBeginAsync(cancellationToken)); + } + + public override ValueTask ReadBoolAsync(CancellationToken cancellationToken) + { + /* + Read a boolean off the wire. If this is a boolean field, the value should + already have been Read during ReadFieldBegin, so we'll just consume the + pre-stored value. Otherwise, Read a byte. + */ + + if (_boolValue != null) + { + var result = _boolValue.Value; + _boolValue = null; + return new ValueTask(result); + } + + return InternalCall(); + + async ValueTask InternalCall() + { + var data = await ReadByteAsync(cancellationToken); + return (data == Types.BooleanTrue); + } + } + + + public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) + { + // Read a single byte off the wire. Nothing interesting here. + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + return (sbyte)PreAllocatedBuffer[0]; + } + + public override async ValueTask ReadI16Async(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + return (short) ZigzagToInt(await ReadVarInt32Async(cancellationToken)); + } + + public override async ValueTask ReadI32Async(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + return ZigzagToInt(await ReadVarInt32Async(cancellationToken)); + } + + public override async ValueTask ReadI64Async(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + return ZigzagToLong(await ReadVarInt64Async(cancellationToken)); + } + + public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 8, cancellationToken); + + return BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(PreAllocatedBuffer)); + } + + public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) + { + // read length + var length = (int) await ReadVarInt32Async(cancellationToken); + if (length == 0) + { + return string.Empty; + } + + // read and decode data + if (length < PreAllocatedBuffer.Length) + { + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, length, cancellationToken); + return Encoding.UTF8.GetString(PreAllocatedBuffer, 0, length); + } + + Transport.CheckReadBytesAvailable(length); + + var buf = ArrayPool.Shared.Rent(length); + try + { + await Trans.ReadAllAsync(buf, 0, length, cancellationToken); + return Encoding.UTF8.GetString(buf, 0, length); + } + finally + { + ArrayPool.Shared.Return(buf); + } + } + + public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) + { + // read length + var length = (int) await ReadVarInt32Async(cancellationToken); + if (length == 0) + { + return Array.Empty(); + } + + // read data + Transport.CheckReadBytesAvailable(length); + var buf = new byte[length]; + await Trans.ReadAllAsync(buf, 0, length, cancellationToken); + return buf; + } + + public override async ValueTask ReadUuidAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + Transport.CheckReadBytesAvailable(16); // = sizeof(uuid) + var buf = new byte[16]; + await Trans.ReadAllAsync(buf, 0, 16, cancellationToken); + return new Guid(buf).SwapByteOrder(); + } + + public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + /* + Read a list header off the wire. If the list size is 0-14, the size will + be packed into the element exType header. If it's a longer list, the 4 MSB + of the element exType header will be 0xF, and a varint will follow with the + true size. + */ + + var sizeAndType = (byte) await ReadByteAsync(cancellationToken); + var size = (sizeAndType >> 4) & 0x0f; + if (size == 15) + { + size = (int) await ReadVarInt32Async(cancellationToken); + } + + var type = GetTType(sizeAndType); + var list = new TList(type, size); + CheckReadBytesAvailable(list); + return list; + } + + public override Task ReadListEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override Task ReadSetEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + private static byte GetCompactType(TType ttype) + { + // Given a TType value, find the appropriate TCompactProtocol.Types constant. + return TTypeToCompactType[(int) ttype]; + } + + + private async ValueTask ReadVarInt32Async(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + /* + Read an i32 from the wire as a varint. The MSB of each byte is set + if there is another byte to follow. This can Read up to 5 bytes. + */ + + uint result = 0; + var shift = 0; + + while (true) + { + var b = (byte) await ReadByteAsync(cancellationToken); + result |= (uint) (b & 0x7f) << shift; + if ((b & 0x80) != 0x80) + { + break; + } + shift += 7; + } + + return result; + } + + private async ValueTask ReadVarInt64Async(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + /* + Read an i64 from the wire as a proper varint. The MSB of each byte is set + if there is another byte to follow. This can Read up to 10 bytes. + */ + + var shift = 0; + ulong result = 0; + while (true) + { + var b = (byte) await ReadByteAsync(cancellationToken); + result |= (ulong) (b & 0x7f) << shift; + if ((b & 0x80) != 0x80) + { + break; + } + shift += 7; + } + + return result; + } + + private static int ZigzagToInt(uint n) + { + return (int) (n >> 1) ^ -(int) (n & 1); + } + + private static long ZigzagToLong(ulong n) + { + return (long) (n >> 1) ^ -(long) (n & 1); + } + + private static TType GetTType(byte type) + { + // Given a TCompactProtocol.Types constant, convert it to its corresponding TType value. + return CompactTypeToTType[type & 0x0f]; + } + + private static ulong LongToZigzag(long n) + { + // Convert l into a zigzag long. This allows negative numbers to be represented compactly as a varint + return (ulong) (n << 1) ^ (ulong) (n >> 63); + } + + private static uint IntToZigzag(int n) + { + // Convert n into a zigzag int. This allows negative numbers to be represented compactly as a varint + return (uint) (n << 1) ^ (uint) (n >> 31); + } + + // Return the minimum number of bytes a type will consume on the wire + public override int GetMinSerializedSize(TType type) + { + switch (type) + { + case TType.Stop: return 0; + case TType.Void: return 0; + case TType.Bool: return sizeof(byte); + case TType.Double: return 8; // uses fixedLongToBytes() which always writes 8 bytes + case TType.Byte: return sizeof(byte); + case TType.I16: return sizeof(byte); // zigzag + case TType.I32: return sizeof(byte); // zigzag + case TType.I64: return sizeof(byte); // zigzag + case TType.String: return sizeof(byte); // string length + case TType.Struct: return 0; // empty struct + case TType.Map: return sizeof(byte); // element count + case TType.Set: return sizeof(byte); // element count + case TType.List: return sizeof(byte); // element count + case TType.Uuid: return 16; // uuid bytes + default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "unrecognized type code"); + } + } + + public class Factory : TProtocolFactory + { + public override TProtocol GetProtocol(TTransport trans) + { + return new TCompactProtocol(trans); + } + } + + /// + /// All of the on-wire exType codes. + /// + private static class Types + { + public const byte Stop = 0x00; + public const byte BooleanTrue = 0x01; + public const byte BooleanFalse = 0x02; + public const byte Byte = 0x03; + public const byte I16 = 0x04; + public const byte I32 = 0x05; + public const byte I64 = 0x06; + public const byte Double = 0x07; + public const byte Binary = 0x08; + public const byte List = 0x09; + public const byte Set = 0x0A; + public const byte Map = 0x0B; + public const byte Struct = 0x0C; + public const byte Uuid = 0x0D; + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TCompactProtocol.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TCompactProtocol.cs.meta new file mode 100644 index 0000000..86149de --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TCompactProtocol.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3124fc994ddc723458d1ca617ecfa78f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TJSONProtocol.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TJSONProtocol.cs new file mode 100644 index 0000000..ae37a80 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TJSONProtocol.cs @@ -0,0 +1,1044 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0290 // net8 - primary CTOR +#pragma warning disable IDE0305 // net9 - collection init +#pragma warning disable IDE0300 // net9 - collection init + +namespace Thrift.Protocol +{ + /// + /// JSON protocol implementation for thrift. + /// This is a full-featured protocol supporting Write and Read. + /// Please see the C++ class header for a detailed description of the + /// protocol's wire format. + /// Adapted from the Java version. + /// + // ReSharper disable once InconsistentNaming + public class TJsonProtocol : TProtocol + { + private const long Version = 1; + + // Temporary buffer used by several methods + private readonly byte[] _tempBuffer = new byte[4]; + + // Current context that we are in + protected JSONBaseContext Context; + + // Stack of nested contexts that we may be in + protected Stack ContextStack = new Stack(); + + // Reader that manages a 1-byte buffer + protected LookaheadReader Reader; + + // Default encoding + protected Encoding Utf8Encoding = Encoding.UTF8; + + /// + /// TJsonProtocol Constructor + /// + public TJsonProtocol(TTransport trans) + : base(trans) + { + Context = new JSONBaseContext(this); + Reader = new LookaheadReader(this); + } + + /// + /// Push a new JSON context onto the stack. + /// + protected void PushContext(JSONBaseContext c) + { + ContextStack.Push(Context); + Context = c; + } + + /// + /// Pop the last JSON context off the stack + /// + protected void PopContext() + { + Context = ContextStack.Pop(); + } + + /// + /// Resets the context stack to pristine state. Allows for reusal of the protocol + /// even in cases where the protocol instance was in an undefined state due to + /// dangling/stale/obsolete contexts + /// + private void ResetContext() + { + ContextStack.Clear(); + Context = new JSONBaseContext(this); + } + /// + /// Read a byte that must match b[0]; otherwise an exception is thrown. + /// Marked protected to avoid synthetic accessor in JSONListContext.Read + /// and JSONPairContext.Read + /// + protected async Task ReadJsonSyntaxCharAsync(byte[] bytes, CancellationToken cancellationToken) + { + var ch = await Reader.ReadAsync(cancellationToken); + if (ch != bytes[0]) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, $"Unexpected character: {(char) ch}"); + } + } + + /// + /// Write the bytes in array buf as a JSON characters, escaping as needed + /// + private async Task WriteJsonStringAsync(byte[] bytes, CancellationToken cancellationToken) + { + await Context.WriteConditionalDelimiterAsync(cancellationToken); + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + + var len = bytes.Length; + for (var i = 0; i < len; i++) + { + if ((bytes[i] & 0x00FF) >= 0x30) + { + if (bytes[i] == TJSONProtocolConstants.Backslash[0]) + { + await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken); + await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken); + } + else + { + await Trans.WriteAsync(bytes, i, 1, cancellationToken); + } + } + else + { + _tempBuffer[0] = TJSONProtocolConstants.JsonCharTable[bytes[i]]; + if (_tempBuffer[0] == 1) + { + await Trans.WriteAsync(bytes, i, 1, cancellationToken); + } + else if (_tempBuffer[0] > 1) + { + await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken); + await Trans.WriteAsync(_tempBuffer, 0, 1, cancellationToken); + } + else + { + await Trans.WriteAsync(TJSONProtocolConstants.EscSequences, cancellationToken); + _tempBuffer[0] = TJSONProtocolHelper.ToHexChar((byte) (bytes[i] >> 4)); + _tempBuffer[1] = TJSONProtocolHelper.ToHexChar(bytes[i]); + await Trans.WriteAsync(_tempBuffer, 0, 2, cancellationToken); + } + } + } + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + /// + /// Write out number as a JSON value. If the context dictates so, it will be + /// wrapped in quotes to output as a JSON string. + /// + private async Task WriteJsonIntegerAsync(long num, CancellationToken cancellationToken) + { + await Context.WriteConditionalDelimiterAsync(cancellationToken); + var str = num.ToString(); + + var escapeNum = Context.EscapeNumbers(); + if (escapeNum) + { + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + var bytes = Utf8Encoding.GetBytes(str); + await Trans.WriteAsync(bytes, cancellationToken); + + if (escapeNum) + { + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + } + + /// + /// Write out a double as a JSON value. If it is NaN or infinity or if the + /// context dictates escaping, Write out as JSON string. + /// + private async Task WriteJsonDoubleAsync(double num, CancellationToken cancellationToken) + { + await Context.WriteConditionalDelimiterAsync(cancellationToken); + var str = num.ToString("G17", CultureInfo.InvariantCulture); + var special = false; + + switch (str[0]) + { + case 'N': // NaN + case 'I': // Infinity + special = true; + break; + case '-': + if (str[1] == 'I') + { + // -Infinity + special = true; + } + break; + } + + var escapeNum = special || Context.EscapeNumbers(); + + if (escapeNum) + { + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + await Trans.WriteAsync(Utf8Encoding.GetBytes(str), cancellationToken); + + if (escapeNum) + { + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + } + + /// + /// Write out contents of byte array b as a JSON string with base-64 encoded + /// data + /// + private async Task WriteJsonBase64Async(byte[] bytes, CancellationToken cancellationToken) + { + await Context.WriteConditionalDelimiterAsync(cancellationToken); + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + + var len = bytes.Length; + var off = 0; + + while (len >= 3) + { + // Encode 3 bytes at a time + TBase64Utils.Encode(bytes, off, 3, _tempBuffer, 0); + await Trans.WriteAsync(_tempBuffer, 0, 4, cancellationToken); + off += 3; + len -= 3; + } + + if (len > 0) + { + // Encode remainder + TBase64Utils.Encode(bytes, off, len, _tempBuffer, 0); + await Trans.WriteAsync(_tempBuffer, 0, len + 1, cancellationToken); + } + + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + private async Task WriteJsonObjectStartAsync(CancellationToken cancellationToken) + { + await Context.WriteConditionalDelimiterAsync(cancellationToken); + await Trans.WriteAsync(TJSONProtocolConstants.LeftBrace, cancellationToken); + PushContext(new JSONPairContext(this)); + } + + private async Task WriteJsonObjectEndAsync(CancellationToken cancellationToken) + { + PopContext(); + await Trans.WriteAsync(TJSONProtocolConstants.RightBrace, cancellationToken); + } + + private async Task WriteJsonArrayStartAsync(CancellationToken cancellationToken) + { + await Context.WriteConditionalDelimiterAsync(cancellationToken); + await Trans.WriteAsync(TJSONProtocolConstants.LeftBracket, cancellationToken); + PushContext(new JSONListContext(this)); + } + + private async Task WriteJsonArrayEndAsync(CancellationToken cancellationToken) + { + PopContext(); + await Trans.WriteAsync(TJSONProtocolConstants.RightBracket, cancellationToken); + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + ResetContext(); + await WriteJsonArrayStartAsync(cancellationToken); + await WriteJsonIntegerAsync(Version, cancellationToken); + + var b = Utf8Encoding.GetBytes(message.Name); + await WriteJsonStringAsync(b, cancellationToken); + + await WriteJsonIntegerAsync((long) message.Type, cancellationToken); + await WriteJsonIntegerAsync(message.SeqID, cancellationToken); + } + + public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) + { + await WriteJsonArrayEndAsync(cancellationToken); + } + + public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + { + await WriteJsonObjectStartAsync(cancellationToken); + } + + public override async Task WriteStructEndAsync(CancellationToken cancellationToken) + { + await WriteJsonObjectEndAsync(cancellationToken); + } + + public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(field.ID, cancellationToken); + await WriteJsonObjectStartAsync(cancellationToken); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(field.Type), cancellationToken); + } + + public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) + { + await WriteJsonObjectEndAsync(cancellationToken); + } + + public override Task WriteFieldStopAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) + { + await WriteJsonArrayStartAsync(cancellationToken); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.KeyType), cancellationToken); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.ValueType), cancellationToken); + await WriteJsonIntegerAsync(map.Count, cancellationToken); + await WriteJsonObjectStartAsync(cancellationToken); + } + + public override async Task WriteMapEndAsync(CancellationToken cancellationToken) + { + await WriteJsonObjectEndAsync(cancellationToken); + await WriteJsonArrayEndAsync(cancellationToken); + } + + public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) + { + await WriteJsonArrayStartAsync(cancellationToken); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(list.ElementType), cancellationToken); + await WriteJsonIntegerAsync(list.Count, cancellationToken); + } + + public override async Task WriteListEndAsync(CancellationToken cancellationToken) + { + await WriteJsonArrayEndAsync(cancellationToken); + } + + public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) + { + await WriteJsonArrayStartAsync(cancellationToken); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(set.ElementType), cancellationToken); + await WriteJsonIntegerAsync(set.Count, cancellationToken); + } + + public override async Task WriteSetEndAsync(CancellationToken cancellationToken) + { + await WriteJsonArrayEndAsync(cancellationToken); + } + + public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(b ? 1 : 0, cancellationToken); + } + + public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(b, cancellationToken); + } + + public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(i16, cancellationToken); + } + + public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(i32, cancellationToken); + } + + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(i64, cancellationToken); + } + + public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) + { + await WriteJsonDoubleAsync(d, cancellationToken); + } + + public override async Task WriteStringAsync(string s, CancellationToken cancellationToken) + { + var b = Utf8Encoding.GetBytes(s); + await WriteJsonStringAsync(b, cancellationToken); + } + + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) + { + await WriteJsonBase64Async(bytes, cancellationToken); + } + public override async Task WriteUuidAsync(Guid uuid, CancellationToken cancellationToken = default) + { + await WriteStringAsync(uuid.ToString("D"), cancellationToken); // no curly braces + } + + /// + /// Read in a JSON string, unescaping as appropriate.. Skip Reading from the + /// context if skipContext is true. + /// + private async ValueTask ReadJsonStringAsync(bool skipContext, CancellationToken cancellationToken) + { + using (var buffer = new MemoryStream()) + { + var codeunits = new List(); + + + if (!skipContext) + { + await Context.ReadConditionalDelimiterAsync(cancellationToken); + } + + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); + + while (true) + { + var ch = await Reader.ReadAsync(cancellationToken); + if (ch == TJSONProtocolConstants.Quote[0]) + { + break; + } + + // escaped? + if (ch != TJSONProtocolConstants.EscSequences[0]) + { +#if NET5_0_OR_GREATER + var wbuf = new[] { ch }; + await buffer.WriteAsync(wbuf.AsMemory(0, 1), cancellationToken); +#else + await buffer.WriteAsync(new[] { ch }, 0, 1, cancellationToken); +#endif + continue; + } + + // distinguish between \uXXXX and \? + ch = await Reader.ReadAsync(cancellationToken); + if (ch != TJSONProtocolConstants.EscSequences[1]) // control chars like \n + { + var off = Array.IndexOf(TJSONProtocolConstants.EscapeChars, (char) ch); + if (off == -1) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected control char"); + } + ch = TJSONProtocolConstants.EscapeCharValues[off]; +#if NET5_0_OR_GREATER + var wbuf = new[] { ch }; + await buffer.WriteAsync( wbuf.AsMemory(0, 1), cancellationToken); +#else + await buffer.WriteAsync(new[] { ch }, 0, 1, cancellationToken); +#endif + continue; + } + + // it's \uXXXX + await Trans.ReadAllAsync(_tempBuffer, 0, 4, cancellationToken); + + var wch = (short) ((TJSONProtocolHelper.ToHexVal(_tempBuffer[0]) << 12) + + (TJSONProtocolHelper.ToHexVal(_tempBuffer[1]) << 8) + + (TJSONProtocolHelper.ToHexVal(_tempBuffer[2]) << 4) + + TJSONProtocolHelper.ToHexVal(_tempBuffer[3])); + + if (char.IsHighSurrogate((char) wch)) + { + if (codeunits.Count > 0) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected low surrogate char"); + } + codeunits.Add((char) wch); + } + else if (char.IsLowSurrogate((char) wch)) + { + if (codeunits.Count == 0) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected high surrogate char"); + } + + codeunits.Add((char) wch); + var tmp = Utf8Encoding.GetBytes(codeunits.ToArray()); +#if NET5_0_OR_GREATER + await buffer.WriteAsync(tmp.AsMemory(0, tmp.Length), cancellationToken); +#else + await buffer.WriteAsync(tmp, 0, tmp.Length, cancellationToken); +#endif + codeunits.Clear(); + } + else + { + var tmp = Utf8Encoding.GetBytes(new[] { (char)wch }); +#if NET5_0_OR_GREATER + await buffer.WriteAsync(tmp.AsMemory( 0, tmp.Length), cancellationToken); +#else + await buffer.WriteAsync(tmp, 0, tmp.Length, cancellationToken); +#endif + } + } + + if (codeunits.Count > 0) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected low surrogate char"); + } + + return buffer.ToArray(); + } + } + + /// + /// Read in a sequence of characters that are all valid in JSON numbers. Does + /// not do a complete regex check to validate that this is actually a number. + /// + private async ValueTask ReadJsonNumericCharsAsync(CancellationToken cancellationToken) + { + var strbld = new StringBuilder(); + while (true) + { + //TODO: workaround for primitive types with TJsonProtocol, think - how to rewrite into more easy form without exceptions + try + { + var ch = await Reader.PeekAsync(cancellationToken); + if (!TJSONProtocolHelper.IsJsonNumeric(ch)) + { + break; + } + var c = (char)await Reader.ReadAsync(cancellationToken); + strbld.Append(c); + } + catch (TTransportException) + { + break; + } + } + return strbld.ToString(); + } + + /// + /// Read in a JSON number. If the context dictates, Read in enclosing quotes. + /// + private async ValueTask ReadJsonIntegerAsync(CancellationToken cancellationToken) + { + await Context.ReadConditionalDelimiterAsync(cancellationToken); + if (Context.EscapeNumbers()) + { + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + var str = await ReadJsonNumericCharsAsync(cancellationToken); + if (Context.EscapeNumbers()) + { + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + try + { + return long.Parse(str); + } + catch (FormatException) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Bad data encounted in numeric data"); + } + } + + /// + /// Read in a JSON double value. Throw if the value is not wrapped in quotes + /// when expected or if wrapped in quotes when not expected. + /// + private async ValueTask ReadJsonDoubleAsync(CancellationToken cancellationToken) + { + await Context.ReadConditionalDelimiterAsync(cancellationToken); + if (await Reader.PeekAsync(cancellationToken) == TJSONProtocolConstants.Quote[0]) + { + var arr = await ReadJsonStringAsync(true, cancellationToken); + var dub = double.Parse(Utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture); + + if (!Context.EscapeNumbers() && !double.IsNaN(dub) && !double.IsInfinity(dub)) + { + // Throw exception -- we should not be in a string in this case + throw new TProtocolException(TProtocolException.INVALID_DATA, "Numeric data unexpectedly quoted"); + } + + return dub; + } + + if (Context.EscapeNumbers()) + { + // This will throw - we should have had a quote if escapeNum == true + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + try + { + return double.Parse(await ReadJsonNumericCharsAsync(cancellationToken), CultureInfo.InvariantCulture); + } + catch (FormatException) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Bad data encounted in numeric data"); + } + } + + /// + /// Read in a JSON string containing base-64 encoded data and decode it. + /// + private async ValueTask ReadJsonBase64Async(CancellationToken cancellationToken) + { + var b = await ReadJsonStringAsync(false, cancellationToken); + var len = b.Length; + var off = 0; + var size = 0; + + // reduce len to ignore fill bytes + while ((len > 0) && (b[len - 1] == '=')) + { + --len; + } + + // read & decode full byte triplets = 4 source bytes + while (len > 4) + { + // Decode 4 bytes at a time + TBase64Utils.Decode(b, off, 4, b, size); // NB: decoded in place + off += 4; + len -= 4; + size += 3; + } + + // Don't decode if we hit the end or got a single leftover byte (invalid + // base64 but legal for skip of regular string exType) + if (len > 1) + { + // Decode remainder + TBase64Utils.Decode(b, off, len, b, size); // NB: decoded in place + size += len - 1; + } + + // Sadly we must copy the byte[] (any way around this?) + var result = new byte[size]; + Array.Copy(b, 0, result, 0, size); + return result; + } + + private async Task ReadJsonObjectStartAsync(CancellationToken cancellationToken) + { + await Context.ReadConditionalDelimiterAsync(cancellationToken); + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBrace, cancellationToken); + PushContext(new JSONPairContext(this)); + } + + private async Task ReadJsonObjectEndAsync(CancellationToken cancellationToken) + { + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBrace, cancellationToken); + PopContext(); + } + + private async Task ReadJsonArrayStartAsync(CancellationToken cancellationToken) + { + await Context.ReadConditionalDelimiterAsync(cancellationToken); + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBracket, cancellationToken); + PushContext(new JSONListContext(this)); + } + + private async Task ReadJsonArrayEndAsync(CancellationToken cancellationToken) + { + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBracket, cancellationToken); + PopContext(); + } + + public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) + { + var message = new TMessage(); + + ResetContext(); + await ReadJsonArrayStartAsync(cancellationToken); + if (await ReadJsonIntegerAsync(cancellationToken) != Version) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, "Message contained bad version."); + } + + var buf = await ReadJsonStringAsync(false, cancellationToken); + message.Name = Utf8Encoding.GetString(buf, 0, buf.Length); + message.Type = (TMessageType) await ReadJsonIntegerAsync(cancellationToken); + message.SeqID = (int) await ReadJsonIntegerAsync(cancellationToken); + return message; + } + + public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + await ReadJsonArrayEndAsync(cancellationToken); + Transport.ResetMessageSizeAndConsumedBytes(); + } + + public override async ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) + { + await ReadJsonObjectStartAsync(cancellationToken); + + return AnonymousStruct; + } + + public override async Task ReadStructEndAsync(CancellationToken cancellationToken) + { + await ReadJsonObjectEndAsync(cancellationToken); + } + + public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) + { + var ch = await Reader.PeekAsync(cancellationToken); + if (ch == TJSONProtocolConstants.RightBrace[0]) + { + return StopField; + } + + var field = new TField() + { + ID = (short)await ReadJsonIntegerAsync(cancellationToken) + }; + + await ReadJsonObjectStartAsync(cancellationToken); + field.Type = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); + return field; + } + + public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) + { + await ReadJsonObjectEndAsync(cancellationToken); + } + + public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) + { + var map = new TMap(); + await ReadJsonArrayStartAsync(cancellationToken); + map.KeyType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); + map.ValueType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); + map.Count = (int) await ReadJsonIntegerAsync(cancellationToken); + CheckReadBytesAvailable(map); + await ReadJsonObjectStartAsync(cancellationToken); + return map; + } + + public override async Task ReadMapEndAsync(CancellationToken cancellationToken) + { + await ReadJsonObjectEndAsync(cancellationToken); + await ReadJsonArrayEndAsync(cancellationToken); + } + + public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) + { + var list = new TList(); + await ReadJsonArrayStartAsync(cancellationToken); + list.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); + list.Count = (int) await ReadJsonIntegerAsync(cancellationToken); + CheckReadBytesAvailable(list); + return list; + } + + public override async Task ReadListEndAsync(CancellationToken cancellationToken) + { + await ReadJsonArrayEndAsync(cancellationToken); + } + + public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) + { + var set = new TSet(); + await ReadJsonArrayStartAsync(cancellationToken); + set.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); + set.Count = (int) await ReadJsonIntegerAsync(cancellationToken); + CheckReadBytesAvailable(set); + return set; + } + + public override async Task ReadSetEndAsync(CancellationToken cancellationToken) + { + await ReadJsonArrayEndAsync(cancellationToken); + } + + public override async ValueTask ReadBoolAsync(CancellationToken cancellationToken) + { + return await ReadJsonIntegerAsync(cancellationToken) != 0; + } + + public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) + { + return (sbyte) await ReadJsonIntegerAsync(cancellationToken); + } + + public override async ValueTask ReadI16Async(CancellationToken cancellationToken) + { + return (short) await ReadJsonIntegerAsync(cancellationToken); + } + + public override async ValueTask ReadI32Async(CancellationToken cancellationToken) + { + return (int) await ReadJsonIntegerAsync(cancellationToken); + } + + public override async ValueTask ReadI64Async(CancellationToken cancellationToken) + { + return await ReadJsonIntegerAsync(cancellationToken); + } + + public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) + { + return await ReadJsonDoubleAsync(cancellationToken); + } + + public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) + { + var buf = await ReadJsonStringAsync(false, cancellationToken); + return Utf8Encoding.GetString(buf, 0, buf.Length); + } + + public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) + { + return await ReadJsonBase64Async(cancellationToken); + } + + public override async ValueTask ReadUuidAsync(CancellationToken cancellationToken = default) + { + return new Guid( await ReadStringAsync(cancellationToken)); + } + + // Return the minimum number of bytes a type will consume on the wire + public override int GetMinSerializedSize(TType type) + { + switch (type) + { + case TType.Stop: return 0; + case TType.Void: return 0; + case TType.Bool: return 1; // written as int + case TType.Byte: return 1; + case TType.Double: return 1; + case TType.I16: return 1; + case TType.I32: return 1; + case TType.I64: return 1; + case TType.String: return 2; // empty string + case TType.Struct: return 2; // empty struct + case TType.Map: return 2; // empty map + case TType.Set: return 2; // empty set + case TType.List: return 2; // empty list + case TType.Uuid: return 36; // "E236974D-F0B0-4E05-8F29-0B455D41B1A1" + default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "unrecognized type code"); + } + } + + /// + /// Factory for JSON protocol objects + /// + public class Factory : TProtocolFactory + { + public override TProtocol GetProtocol(TTransport trans) + { + return new TJsonProtocol(trans); + } + } + + /// + /// Base class for tracking JSON contexts that may require + /// inserting/Reading additional JSON syntax characters + /// This base context does nothing. + /// + protected class JSONBaseContext + { + protected TJsonProtocol Proto; + + public JSONBaseContext(TJsonProtocol proto) + { + Proto = proto; + } + + public virtual Task WriteConditionalDelimiterAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public virtual Task ReadConditionalDelimiterAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public virtual bool EscapeNumbers() + { + return false; + } + } + + /// + /// Context for JSON lists. Will insert/Read commas before each item except + /// for the first one + /// + protected class JSONListContext : JSONBaseContext + { + private bool _first = true; + + public JSONListContext(TJsonProtocol protocol) + : base(protocol) + { + } + + public override async Task WriteConditionalDelimiterAsync(CancellationToken cancellationToken) + { + if (_first) + { + _first = false; + } + else + { + await Proto.Trans.WriteAsync(TJSONProtocolConstants.Comma, cancellationToken); + } + } + + public override async Task ReadConditionalDelimiterAsync(CancellationToken cancellationToken) + { + if (_first) + { + _first = false; + } + else + { + await Proto.ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Comma, cancellationToken); + } + } + } + + /// + /// Context for JSON records. Will insert/Read colons before the value portion + /// of each record pair, and commas before each key except the first. In + /// addition, will indicate that numbers in the key position need to be + /// escaped in quotes (since JSON keys must be strings). + /// + // ReSharper disable once InconsistentNaming + protected class JSONPairContext : JSONBaseContext + { + private bool _colon = true; + + private bool _first = true; + + public JSONPairContext(TJsonProtocol proto) + : base(proto) + { + } + + public override async Task WriteConditionalDelimiterAsync(CancellationToken cancellationToken) + { + if (_first) + { + _first = false; + _colon = true; + } + else + { + await Proto.Trans.WriteAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken); + _colon = !_colon; + } + } + + public override async Task ReadConditionalDelimiterAsync(CancellationToken cancellationToken) + { + if (_first) + { + _first = false; + _colon = true; + } + else + { + await Proto.ReadJsonSyntaxCharAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken); + _colon = !_colon; + } + } + + public override bool EscapeNumbers() + { + return _colon; + } + } + + /// + /// Holds up to one byte from the transport + /// + protected class LookaheadReader + { + private readonly byte[] _data = new byte[1]; + + private bool _hasData; + protected TJsonProtocol Proto; + + public LookaheadReader(TJsonProtocol proto) + { + Proto = proto; + } + + /// + /// Return and consume the next byte to be Read, either taking it from the + /// data buffer if present or getting it from the transport otherwise. + /// + public async ValueTask ReadAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (_hasData) + { + _hasData = false; + } + else + { + // find more easy way to avoid exception on reading primitive types + await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken); + } + return _data[0]; + } + + /// + /// Return the next byte to be Read without consuming, filling the data + /// buffer if it has not been filled alReady. + /// + public async ValueTask PeekAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (!_hasData) + { + // find more easy way to avoid exception on reading primitive types + await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken); + _hasData = true; + } + return _data[0]; + } + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TJSONProtocol.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TJSONProtocol.cs.meta new file mode 100644 index 0000000..ead48c9 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TJSONProtocol.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2852a1ad0426ea54aa516b762a3ce775 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TMultiplexedProtocol.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TMultiplexedProtocol.cs new file mode 100644 index 0000000..510dc28 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TMultiplexedProtocol.cs @@ -0,0 +1,94 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0290 // net8 - primary CTOR + +namespace Thrift.Protocol +{ + /** + * TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift + * client to communicate with a multiplexing Thrift server, by prepending the service name + * to the function name during function calls. + * + * NOTE: THIS IS NOT TO BE USED BY SERVERS. + * On the server, use TMultiplexedProcessor to handle requests from a multiplexing client. + * + * This example uses a single socket transport to invoke two services: + * + * TSocketTransport transport = new TSocketTransport("localhost", 9090); + * transport.open(); + * + * TBinaryProtocol protocol = new TBinaryProtocol(transport); + * + * TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator"); + * Calculator.Client service = new Calculator.Client(mp); + * + * TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport"); + * WeatherReport.Client service2 = new WeatherReport.Client(mp2); + * + * System.out.println(service.add(2,2)); + * System.out.println(service2.getTemperature()); + * + */ + + //TODO: implementation of TProtocol + + // ReSharper disable once InconsistentNaming + public class TMultiplexedProtocol : TProtocolDecorator + { + /** Used to delimit the service name from the function name */ + public const string Separator = ":"; + + private readonly string _serviceName; + + /** + * Wrap the specified protocol, allowing it to be used to communicate with a + * multiplexing server. The serviceName is required as it is + * prepended to the message header so that the multiplexing server can broker + * the function call to the proper service. + * + * Args: + * protocol Your communication protocol of choice, e.g. TBinaryProtocol + * serviceName The service name of the service communicating via this protocol. + */ + + public TMultiplexedProtocol(TProtocol protocol, string serviceName) + : base(protocol) + { + _serviceName = serviceName; + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + switch (message.Type) + { + case TMessageType.Call: + case TMessageType.Oneway: + await base.WriteMessageBeginAsync(new TMessage($"{_serviceName}{Separator}{message.Name}", message.Type, message.SeqID), cancellationToken); + break; + default: + await base.WriteMessageBeginAsync(message, cancellationToken); + break; + } + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TMultiplexedProtocol.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TMultiplexedProtocol.cs.meta new file mode 100644 index 0000000..32b2743 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TMultiplexedProtocol.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 785a0b3fdff50d5489cdd7626de12986 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocol.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocol.cs new file mode 100644 index 0000000..f2bec60 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocol.cs @@ -0,0 +1,199 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; +using Thrift.Transport; + +namespace Thrift.Protocol +{ + // ReSharper disable once InconsistentNaming + public abstract class TProtocol : IDisposable + { + private bool _isDisposed; + protected int RecursionDepth; + + protected TTransport Trans; + + protected static readonly TStruct AnonymousStruct = new TStruct(string.Empty); + protected static readonly TField StopField = new TField() { Type = TType.Stop }; + + + protected TProtocol(TTransport trans) + { + Trans = trans; + RecursionLimit = trans.Configuration.RecursionLimit; + RecursionDepth = 0; + } + + public TTransport Transport => Trans; + + protected int RecursionLimit { get; set; } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public void IncrementRecursionDepth() + { + if (RecursionDepth < RecursionLimit) + { + ++RecursionDepth; + } + else + { + throw new TProtocolException(TProtocolException.DEPTH_LIMIT, "Depth limit exceeded"); + } + } + + public void DecrementRecursionDepth() + { + --RecursionDepth; + } + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + (Trans as IDisposable)?.Dispose(); + } + } + _isDisposed = true; + } + + + protected void CheckReadBytesAvailable(TSet set) + { + Transport.CheckReadBytesAvailable(set.Count * GetMinSerializedSize(set.ElementType)); + } + + protected void CheckReadBytesAvailable(TList list) + { + Transport.CheckReadBytesAvailable(list.Count * GetMinSerializedSize(list.ElementType)); + } + + protected void CheckReadBytesAvailable(TMap map) + { + var elmSize = GetMinSerializedSize(map.KeyType) + GetMinSerializedSize(map.ValueType); + Transport.CheckReadBytesAvailable(map.Count * elmSize); + } + + // Returns the minimum amount of bytes needed to store the smallest possible instance of TType. + public abstract int GetMinSerializedSize(TType type); + + + public abstract Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken = default); + + public abstract Task WriteMessageEndAsync(CancellationToken cancellationToken = default); + + public abstract Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken = default); + + public abstract Task WriteStructEndAsync(CancellationToken cancellationToken = default); + + public abstract Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken = default); + + public abstract Task WriteFieldEndAsync(CancellationToken cancellationToken = default); + + public abstract Task WriteFieldStopAsync(CancellationToken cancellationToken = default); + + public abstract Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken = default); + + public abstract Task WriteMapEndAsync(CancellationToken cancellationToken = default); + + public abstract Task WriteListBeginAsync(TList list, CancellationToken cancellationToken = default); + + public abstract Task WriteListEndAsync(CancellationToken cancellationToken = default); + + public abstract Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken = default); + + public abstract Task WriteSetEndAsync(CancellationToken cancellationToken = default); + + public abstract Task WriteBoolAsync(bool b, CancellationToken cancellationToken = default); + + public abstract Task WriteByteAsync(sbyte b, CancellationToken cancellationToken = default); + + public abstract Task WriteI16Async(short i16, CancellationToken cancellationToken = default); + + public abstract Task WriteI32Async(int i32, CancellationToken cancellationToken = default); + + public abstract Task WriteI64Async(long i64, CancellationToken cancellationToken = default); + + public abstract Task WriteDoubleAsync(double d, CancellationToken cancellationToken = default); + + public virtual async Task WriteStringAsync(string s, CancellationToken cancellationToken = default) + { + var bytes = Encoding.UTF8.GetBytes(s); + await WriteBinaryAsync(bytes, cancellationToken); + } + + public abstract Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken = default); + public abstract Task WriteUuidAsync(Guid uuid, CancellationToken cancellationToken = default); + + public abstract ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken = default); + + public abstract Task ReadMessageEndAsync(CancellationToken cancellationToken = default); + + public abstract ValueTask ReadStructBeginAsync(CancellationToken cancellationToken = default); + + public abstract Task ReadStructEndAsync(CancellationToken cancellationToken = default); + + public abstract ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken = default); + + public abstract Task ReadFieldEndAsync(CancellationToken cancellationToken = default); + + public abstract ValueTask ReadMapBeginAsync(CancellationToken cancellationToken = default); + + public abstract Task ReadMapEndAsync(CancellationToken cancellationToken = default); + + public abstract ValueTask ReadListBeginAsync(CancellationToken cancellationToken = default); + + public abstract Task ReadListEndAsync(CancellationToken cancellationToken = default); + + public abstract ValueTask ReadSetBeginAsync(CancellationToken cancellationToken = default); + + public abstract Task ReadSetEndAsync(CancellationToken cancellationToken = default); + + public abstract ValueTask ReadBoolAsync(CancellationToken cancellationToken = default); + + public abstract ValueTask ReadByteAsync(CancellationToken cancellationToken = default); + + public abstract ValueTask ReadI16Async(CancellationToken cancellationToken = default); + + public abstract ValueTask ReadI32Async(CancellationToken cancellationToken = default); + + public abstract ValueTask ReadI64Async(CancellationToken cancellationToken = default); + + public abstract ValueTask ReadDoubleAsync(CancellationToken cancellationToken = default); + + public virtual async ValueTask ReadStringAsync(CancellationToken cancellationToken = default) + { + var buf = await ReadBinaryAsync(cancellationToken); + return Encoding.UTF8.GetString(buf, 0, buf.Length); + } + + public abstract ValueTask ReadBinaryAsync(CancellationToken cancellationToken = default); + + public abstract ValueTask ReadUuidAsync(CancellationToken cancellationToken = default); + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocol.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocol.cs.meta new file mode 100644 index 0000000..2c9aed4 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocol.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 707e55b50657bac48b6aa280c626c7aa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolDecorator.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolDecorator.cs new file mode 100644 index 0000000..8e7fb94 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolDecorator.cs @@ -0,0 +1,267 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; + +namespace Thrift.Protocol +{ + // ReSharper disable once InconsistentNaming + /// + /// TProtocolDecorator forwards all requests to an enclosed TProtocol instance, + /// providing a way to author concise concrete decorator subclasses.While it has + /// no abstract methods, it is marked abstract as a reminder that by itself, + /// it does not modify the behaviour of the enclosed TProtocol. + /// + public abstract class TProtocolDecorator : TProtocol + { + private readonly TProtocol _wrappedProtocol; + + protected TProtocolDecorator(TProtocol protocol) + : base(protocol.Transport) + { + _wrappedProtocol = protocol ?? throw new ArgumentNullException(nameof(protocol)); + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteMessageBeginAsync(message, cancellationToken); + } + + public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteMessageEndAsync(cancellationToken); + } + + public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteStructBeginAsync(@struct, cancellationToken); + } + + public override async Task WriteStructEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteStructEndAsync(cancellationToken); + } + + public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteFieldBeginAsync(field, cancellationToken); + } + + public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteFieldEndAsync(cancellationToken); + } + + public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteFieldStopAsync(cancellationToken); + } + + public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteMapBeginAsync(map, cancellationToken); + } + + public override async Task WriteMapEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteMapEndAsync(cancellationToken); + } + + public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteListBeginAsync(list, cancellationToken); + } + + public override async Task WriteListEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteListEndAsync(cancellationToken); + } + + public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteSetBeginAsync(set, cancellationToken); + } + + public override async Task WriteSetEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteSetEndAsync(cancellationToken); + } + + public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteBoolAsync(b, cancellationToken); + } + + public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteByteAsync(b, cancellationToken); + } + + public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteI16Async(i16, cancellationToken); + } + + public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteI32Async(i32, cancellationToken); + } + + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteI64Async(i64, cancellationToken); + } + + public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteDoubleAsync(d, cancellationToken); + } + + public override async Task WriteStringAsync(string s, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteStringAsync(s, cancellationToken); + } + + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteBinaryAsync(bytes, cancellationToken); + } + + public override async Task WriteUuidAsync(Guid uuid, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteUuidAsync(uuid, cancellationToken); + } + + public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadMessageBeginAsync(cancellationToken); + } + + public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + await _wrappedProtocol.ReadMessageEndAsync(cancellationToken); + Transport.ResetMessageSizeAndConsumedBytes(); + } + + public override async ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadStructBeginAsync(cancellationToken); + } + + public override async Task ReadStructEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadStructEndAsync(cancellationToken); + } + + public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadFieldBeginAsync(cancellationToken); + } + + public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadFieldEndAsync(cancellationToken); + } + + public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadMapBeginAsync(cancellationToken); + } + + public override async Task ReadMapEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadMapEndAsync(cancellationToken); + } + + public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadListBeginAsync(cancellationToken); + } + + public override async Task ReadListEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadListEndAsync(cancellationToken); + } + + public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadSetBeginAsync(cancellationToken); + } + + public override async Task ReadSetEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadSetEndAsync(cancellationToken); + } + + public override async ValueTask ReadBoolAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadBoolAsync(cancellationToken); + } + + public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadByteAsync(cancellationToken); + } + + public override async ValueTask ReadI16Async(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadI16Async(cancellationToken); + } + + public override async ValueTask ReadI32Async(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadI32Async(cancellationToken); + } + + public override async ValueTask ReadI64Async(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadI64Async(cancellationToken); + } + + public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadDoubleAsync(cancellationToken); + } + + public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadStringAsync(cancellationToken); + } + + public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadBinaryAsync(cancellationToken); + } + + public override async ValueTask ReadUuidAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadUuidAsync(cancellationToken); + } + + // Returns the minimum amount of bytes needed to store the smallest possible instance of TType. + public override int GetMinSerializedSize(TType type) + { + return _wrappedProtocol.GetMinSerializedSize(type); + } + + + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolDecorator.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolDecorator.cs.meta new file mode 100644 index 0000000..b80abd3 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolDecorator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 19b5bca1a81ff0e4d950ab9a26a08350 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolException.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolException.cs new file mode 100644 index 0000000..328babd --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolException.cs @@ -0,0 +1,62 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// ReSharper disable InconsistentNaming +using System; + +namespace Thrift.Protocol +{ + public class TProtocolException : TException + { + // do not rename public constants - they used in generated files + public const int UNKNOWN = 0; + public const int INVALID_DATA = 1; + public const int NEGATIVE_SIZE = 2; + public const int SIZE_LIMIT = 3; + public const int BAD_VERSION = 4; + public const int NOT_IMPLEMENTED = 5; + public const int DEPTH_LIMIT = 6; + + protected int Type = UNKNOWN; + + public TProtocolException() + { + } + + public TProtocolException(int type, Exception inner = null) + : base(string.Empty, inner) + { + Type = type; + } + + public TProtocolException(int type, string message, Exception inner = null) + : base(message, inner) + { + Type = type; + } + + public TProtocolException(string message, Exception inner = null) + : base(message, inner) + { + } + + public int GetExceptionType() + { + return Type; + } + } +} \ No newline at end of file diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolException.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolException.cs.meta new file mode 100644 index 0000000..6bde13e --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4ba605f7d63e1314f9b930e4b8a2c7be +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolFactory.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolFactory.cs new file mode 100644 index 0000000..31b0514 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolFactory.cs @@ -0,0 +1,27 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using Thrift.Transport; + +namespace Thrift.Protocol +{ + // ReSharper disable once InconsistentNaming + public abstract class TProtocolFactory + { + public abstract TProtocol GetProtocol(TTransport trans); + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolFactory.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolFactory.cs.meta new file mode 100644 index 0000000..1496444 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/TProtocolFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bc1306af0fbb4444aabfb648f3361e7e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/ToString.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/ToString.cs new file mode 100644 index 0000000..9a94c08 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/ToString.cs @@ -0,0 +1,87 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using Thrift.Protocol; + +namespace Thrift.Protocol +{ + + + public static class ToStringExtensions + { + public static void ToString(this object self, StringBuilder sb, bool first = true) + { + if (!first) + sb.Append(", "); + + bool first_child = true; + if (self is string str) // string is IEnumerable + { + sb.Append('"'); + sb.Append(str); + sb.Append('"'); + } + else if (self is IDictionary dict) + { + sb.Append("{ "); + foreach (DictionaryEntry pair in dict) + { + if (first_child) + first_child = false; + else + sb.Append(','); + + sb.Append("{ "); + pair.Key.ToString(sb); + sb.Append(", "); + pair.Value.ToString(sb); + sb.Append('}'); + } + sb.Append('}'); + } + else if (self is IEnumerable enumerable) + { + sb.Append("{ "); + foreach (var elm in enumerable) + { + elm.ToString(sb, first_child); + first_child = false; + } + sb.Append('}'); + } + else if (self is TBase tbase) + { + sb.Append(tbase.ToString()); + } + else if (self is double dbVal) + { + sb.Append(dbVal.ToString(CultureInfo.InvariantCulture)); + } + else + { + sb.Append(self != null ? self.ToString() : ""); + } + } + } + + +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/ToString.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/ToString.cs.meta new file mode 100644 index 0000000..dc0097f --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/ToString.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2074e4c9459760546bd43505c9481d62 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities.meta new file mode 100644 index 0000000..be447e2 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bb04768de16698c41a44db64dc06a464 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TBase64Utils.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TBase64Utils.cs new file mode 100644 index 0000000..15ef04f --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TBase64Utils.cs @@ -0,0 +1,107 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0300 // net8 - simplified collection init +#pragma warning disable IDE0028 // net8 - simplified collection init +#pragma warning disable CA1510 // net8 - use ThrowIfNull +#pragma warning disable CA1513 // net8 - use ThrowIfNull + +namespace Thrift.Protocol.Utilities +{ + // ReSharper disable once InconsistentNaming + internal static class TBase64Utils + { + //TODO: Constants + //TODO: Check for args + //TODO: Unitests + + internal const string EncodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + private static readonly int[] DecodeTable = + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + internal static void Encode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) + { + if (src == null) + { + throw new ArgumentNullException(nameof(src)); + } + + dst[dstOff] = (byte) EncodeTable[(src[srcOff] >> 2) & 0x3F]; + + if (len == 3) + { + dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; + dst[dstOff + 2] = (byte) EncodeTable[((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)]; + dst[dstOff + 3] = (byte) EncodeTable[src[srcOff + 2] & 0x3F]; + } + else if (len == 2) + { + dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; + dst[dstOff + 2] = (byte) EncodeTable[(src[srcOff + 1] << 2) & 0x3C]; + } + else + { + // len == 1 + dst[dstOff + 1] = (byte) EncodeTable[(src[srcOff] << 4) & 0x30]; + } + } + + internal static void Decode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) + { + if (src == null) + { + throw new ArgumentNullException(nameof(src)); + } + + dst[dstOff] = (byte) ((DecodeTable[src[srcOff] & 0x0FF] << 2) | (DecodeTable[src[srcOff + 1] & 0x0FF] >> 4)); + + if (len > 2) + { + dst[dstOff + 1] = + (byte) + (((DecodeTable[src[srcOff + 1] & 0x0FF] << 4) & 0xF0) | (DecodeTable[src[srcOff + 2] & 0x0FF] >> 2)); + if (len > 3) + { + dst[dstOff + 2] = + (byte) + (((DecodeTable[src[srcOff + 2] & 0x0FF] << 6) & 0xC0) | DecodeTable[src[srcOff + 3] & 0x0FF]); + } + } + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TBase64Utils.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TBase64Utils.cs.meta new file mode 100644 index 0000000..911c06e --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TBase64Utils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 761fd254a87199345ac100ae7ad63f88 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TGuidExtensions.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TGuidExtensions.cs new file mode 100644 index 0000000..ecc0263 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TGuidExtensions.cs @@ -0,0 +1,80 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace Thrift.Protocol.Utilities +{ + public static class TGuidExtensions + { + public static Guid SwapByteOrder(this Guid self) + { + var bytes = self.ToByteArray(); + + // already network order on BigEndian machines + if (BitConverter.IsLittleEndian) + { + SwapBytes(ref bytes[0], ref bytes[3]); + SwapBytes(ref bytes[1], ref bytes[2]); + SwapBytes(ref bytes[4], ref bytes[5]); + SwapBytes(ref bytes[6], ref bytes[7]); + } + + return new Guid(bytes); + } + + private static void SwapBytes(ref byte one, ref byte two) + { + (two, one) = (one, two); + } + + #region SelfTest +#if DEBUG + static private readonly Guid TEST_GUID = new Guid("{00112233-4455-6677-8899-aabbccddeeff}"); + + static TGuidExtensions() + { + SelfTest(); + } + + private static void SelfTest() + { + // host to network + var guid = TEST_GUID; + guid = guid.SwapByteOrder(); + + // validate network order + var bytes = guid.ToByteArray(); + for (var i = 0; i < 10; ++i) + { + var expected = i * 0x11; + Debug.Assert( bytes[i] == expected); + } + + // network to host and final validation + guid = guid.SwapByteOrder(); + Debug.Assert(guid.Equals(TEST_GUID)); + } + +#endif + #endregion + + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TGuidExtensions.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TGuidExtensions.cs.meta new file mode 100644 index 0000000..4d161fb --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TGuidExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a7f1fdb7231fce94086107b61128e0b7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TJsonProtocolConstants.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TJsonProtocolConstants.cs new file mode 100644 index 0000000..6e248db --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TJsonProtocolConstants.cs @@ -0,0 +1,65 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0300 // net8 - simplified collection init + +namespace Thrift.Protocol.Utilities +{ + // ReSharper disable once InconsistentNaming + public static class TJSONProtocolConstants + { + //TODO Check for performance for reusing ImmutableArray from System.Collections.Immutable (https://blogs.msdn.microsoft.com/dotnet/2013/06/24/please-welcome-immutablearrayt/) + // can be possible to get better performance and also better GC + + public static readonly byte[] Comma = {(byte) ','}; + public static readonly byte[] Colon = {(byte) ':'}; + public static readonly byte[] LeftBrace = {(byte) '{'}; + public static readonly byte[] RightBrace = {(byte) '}'}; + public static readonly byte[] LeftBracket = {(byte) '['}; + public static readonly byte[] RightBracket = {(byte) ']'}; + public static readonly byte[] Quote = {(byte) '"'}; + public static readonly byte[] Backslash = {(byte) '\\'}; + + public static readonly byte[] JsonCharTable = + { + 0, 0, 0, 0, 0, 0, 0, 0, (byte) 'b', (byte) 't', (byte) 'n', 0, (byte) 'f', (byte) 'r', 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, (byte) '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + + public static readonly char[] EscapeChars = "\"\\/bfnrt".ToCharArray(); + public static readonly byte[] EscapeCharValues = {(byte) '"', (byte) '\\', (byte) '/', (byte) '\b', (byte) '\f', (byte) '\n', (byte) '\r', (byte) '\t'}; + public static readonly byte[] EscSequences = {(byte) '\\', (byte) 'u', (byte) '0', (byte) '0'}; + + public static class TypeNames + { + public static readonly byte[] NameBool = { (byte)'t', (byte)'f' }; + public static readonly byte[] NameByte = { (byte)'i', (byte)'8' }; + public static readonly byte[] NameI16 = { (byte)'i', (byte)'1', (byte)'6' }; + public static readonly byte[] NameI32 = { (byte)'i', (byte)'3', (byte)'2' }; + public static readonly byte[] NameI64 = { (byte)'i', (byte)'6', (byte)'4' }; + public static readonly byte[] NameDouble = { (byte)'d', (byte)'b', (byte)'l' }; + public static readonly byte[] NameStruct = { (byte)'r', (byte)'e', (byte)'c' }; + public static readonly byte[] NameString = { (byte)'s', (byte)'t', (byte)'r' }; + public static readonly byte[] NameMap = { (byte)'m', (byte)'a', (byte)'p' }; + public static readonly byte[] NameList = { (byte)'l', (byte)'s', (byte)'t' }; + public static readonly byte[] NameSet = { (byte)'s', (byte)'e', (byte)'t' }; + public static readonly byte[] NameUuid = { (byte)'u', (byte)'i', (byte)'d' }; + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TJsonProtocolConstants.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TJsonProtocolConstants.cs.meta new file mode 100644 index 0000000..a942398 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TJsonProtocolConstants.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e217a11c484220b4aaf3b2b92127067c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TJsonProtocolHelper.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TJsonProtocolHelper.cs new file mode 100644 index 0000000..67c7bc0 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TJsonProtocolHelper.cs @@ -0,0 +1,181 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using Thrift.Protocol.Entities; + +namespace Thrift.Protocol.Utilities +{ + // ReSharper disable once InconsistentNaming + public static class TJSONProtocolHelper + { + public static byte[] GetTypeNameForTypeId(TType typeId) + { + switch (typeId) + { + case TType.Bool: + return TJSONProtocolConstants.TypeNames.NameBool; + case TType.Byte: + return TJSONProtocolConstants.TypeNames.NameByte; + case TType.I16: + return TJSONProtocolConstants.TypeNames.NameI16; + case TType.I32: + return TJSONProtocolConstants.TypeNames.NameI32; + case TType.I64: + return TJSONProtocolConstants.TypeNames.NameI64; + case TType.Double: + return TJSONProtocolConstants.TypeNames.NameDouble; + case TType.String: + return TJSONProtocolConstants.TypeNames.NameString; + case TType.Struct: + return TJSONProtocolConstants.TypeNames.NameStruct; + case TType.Map: + return TJSONProtocolConstants.TypeNames.NameMap; + case TType.Set: + return TJSONProtocolConstants.TypeNames.NameSet; + case TType.List: + return TJSONProtocolConstants.TypeNames.NameList; + case TType.Uuid: + return TJSONProtocolConstants.TypeNames.NameUuid; + default: + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType"); + } + } + + public static TType GetTypeIdForTypeName(byte[] name) + { + var result = TType.Stop; + if (name.Length > 1) + { + switch (name[0]) + { + case (byte) 'd': + result = TType.Double; + break; + case (byte) 'i': + switch (name[1]) + { + case (byte) '8': + result = TType.Byte; + break; + case (byte) '1': + result = TType.I16; + break; + case (byte) '3': + result = TType.I32; + break; + case (byte) '6': + result = TType.I64; + break; + } + break; + case (byte) 'l': + result = TType.List; + break; + case (byte) 'm': + result = TType.Map; + break; + case (byte) 'r': + result = TType.Struct; + break; + case (byte) 's': + if (name[1] == (byte) 't') + { + result = TType.String; + } + else if (name[1] == (byte) 'e') + { + result = TType.Set; + } + break; + case (byte) 't': + result = TType.Bool; + break; + case (byte)'u': + result = TType.Uuid; + break; + } + } + if (result == TType.Stop) + { + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType"); + } + return result; + } + + /// + /// Return true if the given byte could be a valid part of a JSON number. + /// + public static bool IsJsonNumeric(byte b) + { + switch (b) + { + case (byte)'+': + case (byte)'-': + case (byte)'.': + case (byte)'0': + case (byte)'1': + case (byte)'2': + case (byte)'3': + case (byte)'4': + case (byte)'5': + case (byte)'6': + case (byte)'7': + case (byte)'8': + case (byte)'9': + case (byte)'E': + case (byte)'e': + return true; + default: + return false; + } + } + + /// + /// Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its + /// corresponding hex value + /// + public static byte ToHexVal(byte ch) + { + if (ch >= '0' && ch <= '9') + { + return (byte)((char)ch - '0'); + } + + if (ch >= 'a' && ch <= 'f') + { + ch += 10; + return (byte)((char)ch - 'a'); + } + + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected hex character"); + } + + /// + /// Convert a byte containing a hex value to its corresponding hex character + /// + public static byte ToHexChar(byte val) + { + val &= 0x0F; + if (val < 10) + { + return (byte)((char)val + '0'); + } + val -= 10; + return (byte)((char)val + 'a'); + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TJsonProtocolHelper.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TJsonProtocolHelper.cs.meta new file mode 100644 index 0000000..a89f76b --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TJsonProtocolHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c0b7b8082d4f82543b7d7e4ec25a8596 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TProtocolUtil.cs b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TProtocolUtil.cs new file mode 100644 index 0000000..3c8b37a --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TProtocolUtil.cs @@ -0,0 +1,110 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; + +namespace Thrift.Protocol.Utilities +{ + // ReSharper disable once InconsistentNaming + public static class TProtocolUtil + { + public static async Task SkipAsync(TProtocol protocol, TType type, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + protocol.IncrementRecursionDepth(); + try + { + switch (type) + { + case TType.Bool: + await protocol.ReadBoolAsync(cancellationToken); + break; + case TType.Byte: + await protocol.ReadByteAsync(cancellationToken); + break; + case TType.I16: + await protocol.ReadI16Async(cancellationToken); + break; + case TType.I32: + await protocol.ReadI32Async(cancellationToken); + break; + case TType.I64: + await protocol.ReadI64Async(cancellationToken); + break; + case TType.Double: + await protocol.ReadDoubleAsync(cancellationToken); + break; + case TType.String: + // Don't try to decode the string, just skip it. + await protocol.ReadBinaryAsync(cancellationToken); + break; + case TType.Uuid: + await protocol.ReadUuidAsync(cancellationToken); + break; + case TType.Struct: + await protocol.ReadStructBeginAsync(cancellationToken); + while (true) + { + var field = await protocol.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + await SkipAsync(protocol, field.Type, cancellationToken); + await protocol.ReadFieldEndAsync(cancellationToken); + } + await protocol.ReadStructEndAsync(cancellationToken); + break; + case TType.Map: + var map = await protocol.ReadMapBeginAsync(cancellationToken); + for (var i = 0; i < map.Count; i++) + { + await SkipAsync(protocol, map.KeyType, cancellationToken); + await SkipAsync(protocol, map.ValueType, cancellationToken); + } + await protocol.ReadMapEndAsync(cancellationToken); + break; + case TType.Set: + var set = await protocol.ReadSetBeginAsync(cancellationToken); + for (var i = 0; i < set.Count; i++) + { + await SkipAsync(protocol, set.ElementType, cancellationToken); + } + await protocol.ReadSetEndAsync(cancellationToken); + break; + case TType.List: + var list = await protocol.ReadListBeginAsync(cancellationToken); + for (var i = 0; i < list.Count; i++) + { + await SkipAsync(protocol, list.ElementType, cancellationToken); + } + await protocol.ReadListEndAsync(cancellationToken); + break; + default: + throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d")); + } + } + finally + { + protocol.DecrementRecursionDepth(); + } + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TProtocolUtil.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TProtocolUtil.cs.meta new file mode 100644 index 0000000..5dc1a17 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Protocol/Utilities/TProtocolUtil.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: da904c2c7f62df841acde0448f0b0a6f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/TApplicationException.cs b/Packages/com.bywaystudios.thrift/Runtime/TApplicationException.cs new file mode 100644 index 0000000..514db9a --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/TApplicationException.cs @@ -0,0 +1,147 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; + +namespace Thrift +{ + // ReSharper disable once InconsistentNaming + public class TApplicationException : TException + { + public enum ExceptionType + { + Unknown, + UnknownMethod, + InvalidMessageType, + WrongMethodName, + BadSequenceId, + MissingResult, + InternalError, + ProtocolError, + InvalidTransform, + InvalidProtocol, + UnsupportedClientType + } + + private const int MessageTypeFieldId = 1; + private const int ExTypeFieldId = 2; + + public ExceptionType Type { get; private set; } + + public TApplicationException() + { + } + + public TApplicationException(ExceptionType type) + { + Type = type; + } + + public TApplicationException(ExceptionType type, string message) + : base(message, null) // TApplicationException is serializable, but we never serialize InnerException + { + Type = type; + } + + public static async ValueTask ReadAsync(TProtocol inputProtocol, CancellationToken cancellationToken) + { + string message = null; + var type = ExceptionType.Unknown; + + await inputProtocol.ReadStructBeginAsync(cancellationToken); + while (true) + { + var field = await inputProtocol.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case MessageTypeFieldId: + if (field.Type == TType.String) + { + message = await inputProtocol.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken); + } + break; + case ExTypeFieldId: + if (field.Type == TType.I32) + { + type = (ExceptionType) await inputProtocol.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken); + break; + } + + await inputProtocol.ReadFieldEndAsync(cancellationToken); + } + + await inputProtocol.ReadStructEndAsync(cancellationToken); + + return new TApplicationException(type, message); + } + + public async Task WriteAsync(TProtocol outputProtocol, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + const string messageTypeFieldName = "message"; + const string exTypeFieldName = "exType"; + const string structApplicationExceptionName = "TApplicationException"; + + var struc = new TStruct(structApplicationExceptionName); + var field = new TField(); + + await outputProtocol.WriteStructBeginAsync(struc, cancellationToken); + + if (!string.IsNullOrEmpty(Message)) + { + field.Name = messageTypeFieldName; + field.Type = TType.String; + field.ID = MessageTypeFieldId; + await outputProtocol.WriteFieldBeginAsync(field, cancellationToken); + await outputProtocol.WriteStringAsync(Message, cancellationToken); + await outputProtocol.WriteFieldEndAsync(cancellationToken); + } + + field.Name = exTypeFieldName; + field.Type = TType.I32; + field.ID = ExTypeFieldId; + + await outputProtocol.WriteFieldBeginAsync(field, cancellationToken); + await outputProtocol.WriteI32Async((int) Type, cancellationToken); + await outputProtocol.WriteFieldEndAsync(cancellationToken); + await outputProtocol.WriteFieldStopAsync(cancellationToken); + await outputProtocol.WriteStructEndAsync(cancellationToken); + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/TApplicationException.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/TApplicationException.cs.meta new file mode 100644 index 0000000..203e5fa --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/TApplicationException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f86d77c239225104cab74e32b14c5d93 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/TBaseClient.cs b/Packages/com.bywaystudios.thrift/Runtime/TBaseClient.cs new file mode 100644 index 0000000..aefb54d --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/TBaseClient.cs @@ -0,0 +1,91 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol; + +namespace Thrift +{ + // ReSharper disable once InconsistentNaming + /// + /// TBaseClient. + /// Base client for generated clients. + /// Do not change this class without checking generated code (namings, etc.) + /// + public abstract class TBaseClient + { + private readonly TProtocol _inputProtocol; + private readonly TProtocol _outputProtocol; + private bool _isDisposed; + private int _seqId; + public readonly Guid ClientId = Guid.NewGuid(); + + protected TBaseClient(TProtocol inputProtocol, TProtocol outputProtocol) + { + _inputProtocol = inputProtocol ?? throw new ArgumentNullException(nameof(inputProtocol)); + _outputProtocol = outputProtocol ?? throw new ArgumentNullException(nameof(outputProtocol)); + } + + public TProtocol InputProtocol => _inputProtocol; + + public TProtocol OutputProtocol => _outputProtocol; + + public int SeqId + { + get { return ++_seqId; } + } + + public virtual async Task OpenTransportAsync() + { + await OpenTransportAsync(CancellationToken.None); + } + + public virtual async Task OpenTransportAsync(CancellationToken cancellationToken) + { + if (!_inputProtocol.Transport.IsOpen) + { + await _inputProtocol.Transport.OpenAsync(cancellationToken); + } + + if (!_outputProtocol.Transport.IsOpen) + { + await _outputProtocol.Transport.OpenAsync(cancellationToken); + } + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _inputProtocol?.Dispose(); + _outputProtocol?.Dispose(); + } + } + + _isDisposed = true; + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/TBaseClient.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/TBaseClient.cs.meta new file mode 100644 index 0000000..d5bee34 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/TBaseClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af1fb0222ec8a574aa069e3d3c4a7c94 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/TConfiguration.cs b/Packages/com.bywaystudios.thrift/Runtime/TConfiguration.cs new file mode 100644 index 0000000..eff78e9 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/TConfiguration.cs @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Thrift +{ + public class TConfiguration + { + public const int DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024; + public const int DEFAULT_MAX_FRAME_SIZE = 16384000; // this value is used consistently across all Thrift libraries + public const int DEFAULT_RECURSION_DEPTH = 64; + + public int MaxMessageSize { get; set; } = DEFAULT_MAX_MESSAGE_SIZE; + public int MaxFrameSize { get; set; } = DEFAULT_MAX_FRAME_SIZE; + public int RecursionLimit { get; set; } = DEFAULT_RECURSION_DEPTH; + + // TODO(JensG): add connection and i/o timeouts + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/TConfiguration.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/TConfiguration.cs.meta new file mode 100644 index 0000000..596abff --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/TConfiguration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 25f18e47ae18a504e9bd1b18dd0bac49 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/TException.cs b/Packages/com.bywaystudios.thrift/Runtime/TException.cs new file mode 100644 index 0000000..43e7054 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/TException.cs @@ -0,0 +1,34 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; + +namespace Thrift +{ + // ReSharper disable once InconsistentNaming + public class TException : Exception + { + public TException() + { + } + + public TException(string message, Exception inner) + : base(message, inner) + { + } + } +} \ No newline at end of file diff --git a/Packages/com.bywaystudios.thrift/Runtime/TException.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/TException.cs.meta new file mode 100644 index 0000000..58a123b --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/TException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4c31d338acd518d47894f98047ffe9ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Thrift.asmdef b/Packages/com.bywaystudios.thrift/Runtime/Thrift.asmdef new file mode 100644 index 0000000..cd01282 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Thrift.asmdef @@ -0,0 +1,14 @@ +{ + "name": "Thrift", + "rootNamespace": "", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Packages/com.bywaystudios.thrift/Runtime/Thrift.asmdef.meta b/Packages/com.bywaystudios.thrift/Runtime/Thrift.asmdef.meta new file mode 100644 index 0000000..c21e95c --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Thrift.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 80bc5989de867864f925938fc1ceb864 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport.meta new file mode 100644 index 0000000..f6bffef --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0de584fe90b6ad447a3e305ab93ec9c3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client.meta new file mode 100644 index 0000000..42ae486 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5b44f0b64f17bfb45ae3deb0647b1078 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/THttpTransport.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/THttpTransport.cs new file mode 100644 index 0000000..4467681 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/THttpTransport.cs @@ -0,0 +1,301 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; + +#pragma warning disable IDE0079 // unneeded suppression -> all except net8 +#pragma warning disable IDE0301 // simplify collection init -> net8 only + +namespace Thrift.Transport.Client +{ + // ReSharper disable once InconsistentNaming + public class THttpTransport : TEndpointTransport + { + private readonly X509Certificate[] _certificates; + private readonly Uri _uri; + + private int _connectTimeout = 30000; // Timeouts in milliseconds + private HttpClient _httpClient; + private Stream _inputStream; + private MemoryStream _outputStream = new MemoryStream(); + private bool _isDisposed; + + public THttpTransport(Uri uri, TConfiguration config, IDictionary customRequestHeaders = null, string userAgent = null) + : this(uri, config, Enumerable.Empty(), customRequestHeaders, userAgent) + { + } + + public THttpTransport(Uri uri, TConfiguration config, IEnumerable certificates, + IDictionary customRequestHeaders, string userAgent = null) + : base(config) + { + _uri = uri; + _certificates = (certificates ?? Enumerable.Empty()).ToArray(); + + if (!string.IsNullOrEmpty(userAgent)) + UserAgent = userAgent; + + // due to current bug with performance of Dispose in netcore https://github.com/dotnet/corefx/issues/8809 + // this can be switched to default way (create client->use->dispose per flush) later + _httpClient = CreateClient(customRequestHeaders); + ConfigureClient(_httpClient); + } + + /// + /// Constructor that takes a HttpClient instance to support using IHttpClientFactory. + /// + /// As the HttpMessageHandler of the client must be configured at the time of creation, it + /// is assumed that the consumer has already added any certificates and configured decompression methods. The + /// consumer can use the CreateHttpClientHandler method to get a handler with these set. + /// Client configured with the desired message handler, user agent, and URI if not + /// specified in the uri parameter. A default user agent will be used if not set. + /// Thrift configuration object + /// Optional URI to use for requests, if not specified the base address of httpClient + /// is used. + public THttpTransport(HttpClient httpClient, TConfiguration config, Uri uri = null) + : base(config) + { + _httpClient = httpClient; + + _uri = uri ?? httpClient.BaseAddress; + httpClient.BaseAddress = _uri; + + var userAgent = _httpClient.DefaultRequestHeaders.UserAgent.ToString(); + if (!string.IsNullOrEmpty(userAgent)) + UserAgent = userAgent; + + ConfigureClient(_httpClient); + } + + // According to RFC 2616 section 3.8, the "User-Agent" header may not carry a version number + public readonly string UserAgent = "Thrift netstd THttpClient"; + + public int ConnectTimeout + { + set + { + _connectTimeout = value; + if(_httpClient != null) + _httpClient.Timeout = TimeSpan.FromMilliseconds(_connectTimeout); + } + get + { + if (_httpClient == null) + return _connectTimeout; + return (int)_httpClient.Timeout.TotalMilliseconds; + } + } + + public override bool IsOpen => true; + + public HttpRequestHeaders RequestHeaders => _httpClient.DefaultRequestHeaders; + + public MediaTypeHeaderValue ContentType { get; set; } + + public override Task OpenAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override void Close() + { + if (_inputStream != null) + { + _inputStream.Dispose(); + _inputStream = null; + } + + if (_outputStream != null) + { + _outputStream.Dispose(); + _outputStream = null; + } + + if (_httpClient != null) + { + _httpClient.Dispose(); + _httpClient = null; + } + } + + public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (_inputStream == null) + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No request has been sent"); + + CheckReadBytesAvailable(length); + + try + { +#if NET5_0_OR_GREATER + var ret = await _inputStream.ReadAsync(new Memory(buffer, offset, length), cancellationToken); +#else + var ret = await _inputStream.ReadAsync(buffer, offset, length, cancellationToken); +#endif + if (ret == -1) + { + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "No more data available"); + } + + CountConsumedMessageBytes(ret); + return ret; + } + catch (IOException iox) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString(), iox); + } + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + +#if NET5_0_OR_GREATER + await _outputStream.WriteAsync(buffer.AsMemory(offset, length), cancellationToken); +#else + await _outputStream.WriteAsync(buffer, offset, length, cancellationToken); +#endif + } + + /// + /// Get a client handler configured with recommended properties to use with the HttpClient constructor + /// and an IHttpClientFactory. + /// + /// An optional array of client certificates to associate with the handler. + /// + /// A client handler with deflate and gZip compression-decompression algorithms and any client + /// certificates passed in via certificates. + /// + public virtual HttpClientHandler CreateHttpClientHandler(X509Certificate[] certificates = null) + { + var handler = new HttpClientHandler(); + if (certificates != null) + handler.ClientCertificates.AddRange(certificates); + handler.AutomaticDecompression = System.Net.DecompressionMethods.Deflate | System.Net.DecompressionMethods.GZip; + return handler; + } + + private HttpClient CreateClient(IDictionary customRequestHeaders) + { + var handler = CreateHttpClientHandler(_certificates); + var httpClient = new HttpClient(handler); + + + if (customRequestHeaders != null) + { + foreach (var item in customRequestHeaders) + { + httpClient.DefaultRequestHeaders.Add(item.Key, item.Value); + } + } + + return httpClient; + } + + private void ConfigureClient(HttpClient httpClient) + { + if (_connectTimeout > 0) + { + httpClient.Timeout = TimeSpan.FromMilliseconds(_connectTimeout); + } + + httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); + + // Clear any user agent values to avoid drift with the field value + httpClient.DefaultRequestHeaders.UserAgent.Clear(); + httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd(UserAgent); + + httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate")); + httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip")); + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + try + { + _outputStream.Seek(0, SeekOrigin.Begin); + + using (var contentStream = new StreamContent(_outputStream)) + { + contentStream.Headers.ContentType = ContentType ?? new MediaTypeHeaderValue(@"application/x-thrift"); + + var response = (await _httpClient.PostAsync(_uri, contentStream, cancellationToken)).EnsureSuccessStatusCode(); + + _inputStream?.Dispose(); +#if NET5_0_OR_GREATER + _inputStream = await response.Content.ReadAsStreamAsync(cancellationToken); +#else + _inputStream = await response.Content.ReadAsStreamAsync(); +#endif + if (_inputStream.CanSeek) + { + _inputStream.Seek(0, SeekOrigin.Begin); + } + } + } + catch (IOException iox) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString(), iox); + } + catch (HttpRequestException wx) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, + "Couldn't connect to server: " + wx, wx); + } + catch (OperationCanceledException ocx) + { + throw new TTransportException(TTransportException.ExceptionType.Interrupted, ocx.Message, ocx); + } + catch (Exception ex) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, ex.Message, ex); + } + finally + { + _outputStream = new MemoryStream(); + ResetMessageSizeAndConsumedBytes(); + } + } + + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _inputStream?.Dispose(); + _outputStream?.Dispose(); + _httpClient?.Dispose(); + } + } + _isDisposed = true; + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/THttpTransport.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/THttpTransport.cs.meta new file mode 100644 index 0000000..fcbf4f5 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/THttpTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ffdc5327b1fab754789b71906c403f6a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TMemoryBufferTransport.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TMemoryBufferTransport.cs new file mode 100644 index 0000000..4701378 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TMemoryBufferTransport.cs @@ -0,0 +1,178 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + + +namespace Thrift.Transport.Client +{ + // ReSharper disable once InconsistentNaming + public class TMemoryBufferTransport : TEndpointTransport + { + private bool IsDisposed; + private byte[] Bytes; + private int _bytesUsed; + + public TMemoryBufferTransport(TConfiguration config, int initialCapacity = 2048) + : base(config) + { + Bytes = new byte[initialCapacity]; + } + + public TMemoryBufferTransport(byte[] buf, TConfiguration config) + :base(config) + { + Bytes = (byte[])buf.Clone(); + _bytesUsed = Bytes.Length; + UpdateKnownMessageSize(_bytesUsed); + } + + public int Position { get; set; } + + public int Capacity + { + get + { + Debug.Assert(_bytesUsed <= Bytes.Length); + return Bytes.Length; + } + set + { + Array.Resize(ref Bytes, value); + _bytesUsed = value; + } + } + + public int Length + { + get { + Debug.Assert(_bytesUsed <= Bytes.Length); + return _bytesUsed; + } + set { + if ((Bytes.Length < value) || (Bytes.Length > (10 * value))) + Array.Resize(ref Bytes, Math.Max(2048, (int)(value * 1.25))); + _bytesUsed = value; + } + } + + public void SetLength(int value) + { + Length = value; + Position = Math.Min(Position, value); + } + + public override bool IsOpen => true; + + public override Task OpenAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override void Close() + { + /* do nothing */ + } + + public void Seek(int delta, SeekOrigin origin) + { + int newPos; + switch (origin) + { + case SeekOrigin.Begin: + newPos = delta; + break; + case SeekOrigin.Current: + newPos = Position + delta; + break; + case SeekOrigin.End: + newPos = _bytesUsed + delta; + break; + default: + throw new ArgumentException("Unrecognized value",nameof(origin)); + } + + if ((0 > newPos) || (newPos > _bytesUsed)) + throw new ArgumentException("Cannot seek outside of the valid range",nameof(origin)); + Position = newPos; + + ResetMessageSizeAndConsumedBytes(); + CountConsumedMessageBytes(Position); + } + + public override ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + var count = Math.Min(Length - Position, length); + Buffer.BlockCopy(Bytes, Position, buffer, offset, count); + Position += count; + CountConsumedMessageBytes(count); + return new ValueTask(count); + } + + public override Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) + { + return WriteAsync(buffer, 0, buffer.Length, cancellationToken); + } + + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + var free = Length - Position; + Length = Length + count - free; + Buffer.BlockCopy(buffer, offset, Bytes, Position, count); + Position += count; + return Task.CompletedTask; + } + + public override Task FlushAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + ResetMessageSizeAndConsumedBytes(); + return Task.CompletedTask; + } + + public byte[] GetBuffer() + { + var retval = new byte[Length]; + Buffer.BlockCopy(Bytes, 0, retval, 0, Length); + return retval; + } + + internal bool TryGetBuffer(out ArraySegment bufSegment) + { + bufSegment = new ArraySegment(Bytes, 0, _bytesUsed); + return true; + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!IsDisposed) + { + if (disposing) + { + // nothing to do + } + } + IsDisposed = true; + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TMemoryBufferTransport.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TMemoryBufferTransport.cs.meta new file mode 100644 index 0000000..e675f16 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TMemoryBufferTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7c87ebc03dc66ae47be0456d1e90e133 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TNamedPipeTransport.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TNamedPipeTransport.cs new file mode 100644 index 0000000..3ed1b6c --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TNamedPipeTransport.cs @@ -0,0 +1,133 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.IO.Pipes; +using System.Security.Principal; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport.Client +{ + // ReSharper disable once InconsistentNaming + public class TNamedPipeTransport : TEndpointTransport + { + private NamedPipeClientStream PipeStream; + private readonly int ConnectTimeout; + private const int DEFAULT_CONNECT_TIMEOUT = 60 * 1000; // Timeout.Infinite is not a good default + + public TNamedPipeTransport(string pipe, TConfiguration config, int timeout = DEFAULT_CONNECT_TIMEOUT) + : this(".", pipe, config, timeout) + { + } + + public TNamedPipeTransport(string server, string pipe, TConfiguration config, int timeout = DEFAULT_CONNECT_TIMEOUT) + : base(config) + { + var serverName = string.IsNullOrWhiteSpace(server) ? server : "."; + ConnectTimeout = (timeout > 0) ? timeout : DEFAULT_CONNECT_TIMEOUT; + + PipeStream = new NamedPipeClientStream(serverName, pipe, PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.Anonymous); + } + + public override bool IsOpen => PipeStream != null && PipeStream.IsConnected; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen); + } + + await PipeStream.ConnectAsync( ConnectTimeout, cancellationToken); + ResetMessageSizeAndConsumedBytes(); + } + + public override void Close() + { + if (PipeStream != null) + { + if (PipeStream.IsConnected) + PipeStream.Close(); + PipeStream.Dispose(); + PipeStream = null; + } + } + + public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + if (PipeStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + CheckReadBytesAvailable(length); +#if NET5_0_OR_GREATER + var numRead = await PipeStream.ReadAsync(new Memory(buffer, offset, length), cancellationToken); +#else + var numRead = await PipeStream.ReadAsync(buffer, offset, length, cancellationToken); +#endif + CountConsumedMessageBytes(numRead); + return numRead; + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + if (PipeStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + // if necessary, send the data in chunks + // there's a system limit around 0x10000 bytes that we hit otherwise + // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section." + var nBytes = Math.Min(15 * 4096, length); // 16 would exceed the limit + while (nBytes > 0) + { +#if NET5_0_OR_GREATER + await PipeStream.WriteAsync(buffer.AsMemory(offset, nBytes), cancellationToken); +#else + await PipeStream.WriteAsync(buffer, offset, nBytes, cancellationToken); +#endif + offset += nBytes; + length -= nBytes; + nBytes = Math.Min(nBytes, length); + } + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + await PipeStream.FlushAsync(cancellationToken); + ResetMessageSizeAndConsumedBytes(); + } + + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (PipeStream != null) + { + if (PipeStream.IsConnected) + PipeStream.Close(); + PipeStream.Dispose(); + PipeStream = null; + } + } + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TNamedPipeTransport.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TNamedPipeTransport.cs.meta new file mode 100644 index 0000000..b09e8cd --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TNamedPipeTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d5fcf3d3e1ec0e94abe92fa217bc88df +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TSocketTransport.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TSocketTransport.cs new file mode 100644 index 0000000..f3e87d4 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TSocketTransport.cs @@ -0,0 +1,229 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport.Client +{ + // ReSharper disable once InconsistentNaming + public class TSocketTransport : TStreamTransport + { + private bool _isDisposed; + + + public TSocketTransport(TcpClient client, TConfiguration config) + : base(config) + { + TcpClient = client ?? throw new ArgumentNullException(nameof(client)); + SetInputOutputStream(); + } + + /// + /// The constructor for a TSocketTransport which takes an IPAddress object. + /// + /// The IP address. + /// The TcpClient port number. + /// The . + /// The TcpClient send timeout. + /// + /// The TcpClient is not connected automatically. You are required to use . + /// + public TSocketTransport(IPAddress host, int port, TConfiguration config, int timeout = 0) + : base(config) + { + Host = host; + Port = port; + + TcpClient = new TcpClient(); + TcpClient.ReceiveTimeout = TcpClient.SendTimeout = timeout; + TcpClient.Client.NoDelay = true; + + SetInputOutputStream(); + } + + /// + /// The constructor for a TSocketTransport which takes either a host name, e.g. 'host.example.com' and port number. + /// If host is not found using Dns.GetHostEntry(host) an exception will be thrown. + /// + /// The host name. + /// The TcpClient port number. + /// The . + /// The TcpClient send timeout. + /// + /// + /// The TcpClient is connected automatically. + /// + public TSocketTransport(string host, int port, TConfiguration config, int timeout = 0) + : base(config) + { + try + { + var entry = Dns.GetHostEntry(host); + if (entry.AddressList.Length == 0) + throw new TTransportException(TTransportException.ExceptionType.Unknown, "unable to resolve host name"); + + Host = entry.AddressList[0]; + Port = port; + + TcpClient = new TcpClient(host, port); + TcpClient.ReceiveTimeout = TcpClient.SendTimeout = timeout; + TcpClient.Client.NoDelay = true; + + SetInputOutputStream(); + } + catch (SocketException e) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, e.Message, e); + } + } + + /// + /// The constructor for a TSocketTransport which takes either a host name, e.g. 'host.example.com' or and IP address string, e.g '123.456.789' and port number. + /// If hostNameOrIpAddress represents a valid IP address this will be used directly. + /// If hostNameOrIpAddress does not represent a valid IP address an IP address will be retrieved using Dns.GetHostEntry(hostNameOrIpAddress). + /// If that fails an exception will be thrown. + /// + /// The host name or IP address. + /// The TcpClient port number. + /// If true attempt to connect the TcpClient. + /// The . + /// The TcpClient send timeout. + /// + /// + /// The TcpClient is connected dependent on the value of ./>. + /// + public TSocketTransport(string hostNameOrIpAddress, int port, bool connectClient, TConfiguration config, int timeout = 0) + : base(config) + { + try + { + if (!IPAddress.TryParse(hostNameOrIpAddress, out var address)) + { + var entry = Dns.GetHostEntry(hostNameOrIpAddress); + + if (entry.AddressList.Length == 0) + throw new TTransportException(TTransportException.ExceptionType.Unknown, "unable to resolve host name"); + + address = entry.AddressList[0]; + } + + Host = address; + Port = port; + + TcpClient = new TcpClient(); + TcpClient.ReceiveTimeout = TcpClient.SendTimeout = timeout; + TcpClient.Client.NoDelay = true; + + if (connectClient) + { + TcpClient.Connect(Host, Port); + } + + SetInputOutputStream(); + } + catch (SocketException e) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, e.Message, e); + } + } + + private void SetInputOutputStream() + { + if (IsOpen) + { + InputStream = TcpClient.GetStream(); + OutputStream = TcpClient.GetStream(); + } + } + + public TcpClient TcpClient { get; private set; } + public IPAddress Host { get; } + public int Port { get; } + + public int Timeout + { + set + { + if (TcpClient != null) + { + TcpClient.ReceiveTimeout = TcpClient.SendTimeout = value; + } + } + } + + public override bool IsOpen + { + get + { + return (TcpClient != null) && TcpClient.Connected; + } + } + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); + } + + if (Port <= 0) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); + } + + if (TcpClient == null) + { + throw new InvalidOperationException("Invalid or not initialized tcp client"); + } + + await TcpClient.ConnectAsync(Host, Port); + SetInputOutputStream(); + } + + public override void Close() + { + base.Close(); + + if (TcpClient != null) + { + TcpClient.Dispose(); + TcpClient = null; + } + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + TcpClient?.Dispose(); + + base.Dispose(disposing); + } + } + _isDisposed = true; + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TSocketTransport.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TSocketTransport.cs.meta new file mode 100644 index 0000000..7571e36 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TSocketTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a03affec5f36f2e468e27282faeb048a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TStreamTransport.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TStreamTransport.cs new file mode 100644 index 0000000..a195001 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TStreamTransport.cs @@ -0,0 +1,146 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Drawing; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport.Client +{ + // ReSharper disable once InconsistentNaming + public class TStreamTransport : TEndpointTransport + { + private bool _isDisposed; + + protected TStreamTransport(TConfiguration config) + :base(config) + { + } + + public TStreamTransport(Stream inputStream, Stream outputStream, TConfiguration config) + : base(config) + { + InputStream = inputStream; + OutputStream = outputStream; + } + + protected Stream OutputStream { get; set; } + + private Stream _InputStream = null; + protected Stream InputStream { + get => _InputStream; + set { + _InputStream = value; + ResetMessageSizeAndConsumedBytes(-1); // full reset to configured maximum + UpdateKnownMessageSize(-1); // adjust to real stream size + } + } + + public override void UpdateKnownMessageSize(long size) + { + long adjusted = 0; + + if (InputStream != null) + { + adjusted = MaxMessageSize; + if (size > 0) + adjusted = Math.Min(adjusted, size); + if( InputStream.CanSeek) + adjusted = Math.Min(adjusted, InputStream.Length); + } + + base.UpdateKnownMessageSize(adjusted); + } + + + public override bool IsOpen => true; + + public override Task OpenAsync(CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; + } + + public override void Close() + { + if (InputStream != null) + { + InputStream.Dispose(); + InputStream = null; + } + + if (OutputStream != null) + { + OutputStream.Dispose(); + OutputStream = null; + } + } + + public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + if (InputStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, + "Cannot read from null inputstream"); + } + +#if NET5_0_OR_GREATER + return await InputStream.ReadAsync(new Memory(buffer, offset, length), cancellationToken); +#else + return await InputStream.ReadAsync(buffer, offset, length, cancellationToken); +#endif + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + if (OutputStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, + "Cannot write to null outputstream"); + } + +#if NET5_0_OR_GREATER + await OutputStream.WriteAsync(buffer.AsMemory(offset, length), cancellationToken); +#else + await OutputStream.WriteAsync(buffer, offset, length, cancellationToken); +#endif + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + await OutputStream.FlushAsync(cancellationToken); + ResetMessageSizeAndConsumedBytes(); + } + + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + InputStream?.Dispose(); + OutputStream?.Dispose(); + } + } + _isDisposed = true; + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TStreamTransport.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TStreamTransport.cs.meta new file mode 100644 index 0000000..415d09f --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TStreamTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e145ef5b9c3663143b84e9befefe3a6c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TTlsSocketTransport.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TTlsSocketTransport.cs new file mode 100644 index 0000000..df18124 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TTlsSocketTransport.cs @@ -0,0 +1,292 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Diagnostics; +using System.Net; +using System.Net.Security; +using System.Net.Sockets; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0028 // net8 - simplified collection init + +namespace Thrift.Transport.Client +{ + //TODO: check for correct work + + // ReSharper disable once InconsistentNaming + public class TTlsSocketTransport : TStreamTransport + { + private readonly X509Certificate2 _certificate; + private readonly RemoteCertificateValidationCallback _certValidator; + private readonly IPAddress _host; + private readonly bool _isServer; + private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback; + private readonly int _port; + private readonly SslProtocols _sslProtocols; + private readonly string _targetHost; + private TcpClient _client; + private SslStream _secureStream; + private int _timeout; + + #if NET7_0_OR_GREATER + public const SslProtocols DefaultSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13; + #else + public const SslProtocols DefaultSslProtocols = SslProtocols.Tls12; + #endif + + + + public TTlsSocketTransport(TcpClient client, TConfiguration config, + X509Certificate2 certificate, bool isServer = false, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = DefaultSslProtocols) + : base(config) + { + _client = client; + _certificate = certificate; + _certValidator = certValidator; + _localCertificateSelectionCallback = localCertificateSelectionCallback; + _sslProtocols = sslProtocols; + _isServer = isServer; + + if (isServer && certificate == null) + { + throw new ArgumentException("TTlsSocketTransport needs certificate to be used for server", + nameof(certificate)); + } + + if (IsOpen) + { + InputStream = client.GetStream(); + OutputStream = client.GetStream(); + } + } + + #if NET9_0_OR_GREATER + [Obsolete("SYSLIB0057: X509Certificate2 and X509Certificate constructors for binary and file content are obsolete")] + #pragma warning disable SYSLIB0057 + #endif + public TTlsSocketTransport(IPAddress host, int port, TConfiguration config, + string certificatePath, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = DefaultSslProtocols) + : this(host, port, config, 0, + new X509Certificate2(certificatePath), + certValidator, + localCertificateSelectionCallback, + sslProtocols) + { + } + #pragma warning restore SYSLIB0057 + + public TTlsSocketTransport(IPAddress host, int port, TConfiguration config, + X509Certificate2 certificate = null, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = DefaultSslProtocols) + : this(host, port, config, 0, + certificate, + certValidator, + localCertificateSelectionCallback, + sslProtocols) + { + } + + public TTlsSocketTransport(IPAddress host, int port, TConfiguration config, int timeout, + X509Certificate2 certificate, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = DefaultSslProtocols) + : base(config) + { + _host = host; + _port = port; + _timeout = timeout; + _certificate = certificate; + _certValidator = certValidator; + _localCertificateSelectionCallback = localCertificateSelectionCallback; + _sslProtocols = sslProtocols; + + InitSocket(); + } + + public TTlsSocketTransport(string host, int port, TConfiguration config, int timeout, + X509Certificate2 certificate, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = DefaultSslProtocols) + : base(config) + { + try + { + _targetHost = host; + + var entry = Dns.GetHostEntry(host); + if (entry.AddressList.Length == 0) + throw new TTransportException(TTransportException.ExceptionType.Unknown, "unable to resolve host name"); + + _host = entry.AddressList[0]; + _port = port; + _timeout = timeout; + _certificate = certificate; + _certValidator = certValidator; + _localCertificateSelectionCallback = localCertificateSelectionCallback; + _sslProtocols = sslProtocols; + + InitSocket(); + } + catch (SocketException e) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, e.Message, e); + } + } + + public int Timeout + { + set { _client.ReceiveTimeout = _client.SendTimeout = _timeout = value; } + } + + public TcpClient TcpClient => _client; + + public IPAddress Host => _host; + + public int Port => _port; + + public override bool IsOpen + { + get + { + if (_client == null) + { + return false; + } + + return _client.Connected; + } + } + + private void InitSocket() + { + _client = new TcpClient(); + _client.ReceiveTimeout = _client.SendTimeout = _timeout; + _client.Client.NoDelay = true; + } + + private bool DefaultCertificateValidator(object sender, X509Certificate certificate, X509Chain chain, + SslPolicyErrors sslValidationErrors) + { + return sslValidationErrors == SslPolicyErrors.None; + } + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); + } + + if (_host == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); + } + + if (_port <= 0) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); + } + + if (_client == null) + { + InitSocket(); + } + + if (_client != null) + { + await _client.ConnectAsync(_host, _port); + await SetupTlsAsync(); + } + } + + public async Task SetupTlsAsync() + { + var validator = _certValidator ?? DefaultCertificateValidator; + + if (_localCertificateSelectionCallback != null) + { + _secureStream = new SslStream(_client.GetStream(), false, validator, _localCertificateSelectionCallback); + } + else + { + _secureStream = new SslStream(_client.GetStream(), false, validator); + } + + try + { + if (_isServer) + { + // Server authentication + await + _secureStream.AuthenticateAsServerAsync(_certificate, _certValidator != null, _sslProtocols, + true); + } + else + { + // Client authentication + var certs = _certificate != null + ? new X509CertificateCollection { _certificate } + : new X509CertificateCollection(); + + var targetHost = _targetHost ?? _host.ToString(); + await _secureStream.AuthenticateAsClientAsync(targetHost, certs, _sslProtocols, true); + } + } + catch (Exception) + { + Close(); + throw; + } + + InputStream = _secureStream; + OutputStream = _secureStream; + } + + public override void Close() + { + base.Close(); + if (_client != null) + { + _client.Dispose(); + _client = null; + } + + if (_secureStream != null) + { + _secureStream.Dispose(); + _secureStream = null; + } + } + + + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TTlsSocketTransport.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TTlsSocketTransport.cs.meta new file mode 100644 index 0000000..40bff05 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Client/TTlsSocketTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 87695db59ada9b24ca9532c22d4e7430 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered.meta new file mode 100644 index 0000000..16de76c --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 825788dd34aebb141a8af1211bf684f7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TBufferedTransport.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TBufferedTransport.cs new file mode 100644 index 0000000..977dcbf --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TBufferedTransport.cs @@ -0,0 +1,211 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport +{ + // ReSharper disable once InconsistentNaming + public class TBufferedTransport : TLayeredTransport + { + private readonly int DesiredBufferSize; + private readonly Client.TMemoryBufferTransport ReadBuffer; + private readonly Client.TMemoryBufferTransport WriteBuffer; + private bool IsDisposed; + + public class Factory : TTransportFactory + { + public override TTransport GetTransport(TTransport trans) + { + return new TBufferedTransport(trans); + } + } + + //TODO: should support only specified input transport? + public TBufferedTransport(TTransport transport, int bufSize = 1024) + : base(transport) + { + if (bufSize <= 0) + { + throw new ArgumentOutOfRangeException(nameof(bufSize), "Buffer size must be a positive number."); + } + + DesiredBufferSize = bufSize; + + WriteBuffer = new Client.TMemoryBufferTransport(InnerTransport.Configuration, bufSize); + ReadBuffer = new Client.TMemoryBufferTransport(InnerTransport.Configuration, bufSize); + + Debug.Assert(DesiredBufferSize == ReadBuffer.Capacity); + Debug.Assert(DesiredBufferSize == WriteBuffer.Capacity); + } + + public TTransport UnderlyingTransport + { + get + { + CheckNotDisposed(); + + return InnerTransport; + } + } + + public override bool IsOpen => !IsDisposed && InnerTransport.IsOpen; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + CheckNotDisposed(); + + await InnerTransport.OpenAsync(cancellationToken); + } + + public override void Close() + { + CheckNotDisposed(); + + InnerTransport.Close(); + } + + public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + CheckNotDisposed(); + ValidateBufferArgs(buffer, offset, length); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + + // do we have something buffered? + var count = ReadBuffer.Length - ReadBuffer.Position; + if (count > 0) + { + return await ReadBuffer.ReadAsync(buffer, offset, length, cancellationToken); + } + + // does the request even fit into the buffer? + // Note we test for >= instead of > to avoid nonsense buffering + if (length >= ReadBuffer.Capacity) + { + return await InnerTransport.ReadAsync(buffer, offset, length, cancellationToken); + } + + // buffer a new chunk of bytes from the underlying transport + ReadBuffer.Length = ReadBuffer.Capacity; + ReadBuffer.TryGetBuffer(out ArraySegment bufSegment); + ReadBuffer.Length = await InnerTransport.ReadAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); + ReadBuffer.Position = 0; + + // deliver the bytes + return await ReadBuffer.ReadAsync(buffer, offset, length, cancellationToken); + } + + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + CheckNotDisposed(); + ValidateBufferArgs(buffer, offset, length); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + // enough space left in buffer? + var free = WriteBuffer.Capacity - WriteBuffer.Length; + if (length > free) + { + WriteBuffer.TryGetBuffer(out ArraySegment bufSegment); + await InnerTransport.WriteAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); + WriteBuffer.SetLength(0); + } + + // do the data even fit into the buffer? + // Note we test for < instead of <= to avoid nonsense buffering + if (length < WriteBuffer.Capacity) + { + await WriteBuffer.WriteAsync(buffer, offset, length, cancellationToken); + return; + } + + // write thru + await InnerTransport.WriteAsync(buffer, offset, length, cancellationToken); + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + CheckNotDisposed(); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + if (WriteBuffer.Length > 0) + { + WriteBuffer.TryGetBuffer(out ArraySegment bufSegment); + await InnerTransport.WriteAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); + WriteBuffer.SetLength(0); + } + + await InnerTransport.FlushAsync(cancellationToken); + } + + public override void CheckReadBytesAvailable(long numBytes) + { + var buffered = ReadBuffer.Length - ReadBuffer.Position; + if (buffered < numBytes) + { + numBytes -= buffered; + InnerTransport.CheckReadBytesAvailable(numBytes); + } + } + + public override void ResetMessageSizeAndConsumedBytes(long newSize = -1) + { + base.ResetMessageSizeAndConsumedBytes(newSize); + ReadBuffer.ResetMessageSizeAndConsumedBytes(newSize); + } + + private void CheckNotDisposed() + { + if (IsDisposed) + { + throw new ObjectDisposedException(nameof(InnerTransport)); + } + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!IsDisposed) + { + if (disposing) + { + ReadBuffer?.Dispose(); + WriteBuffer?.Dispose(); + InnerTransport?.Dispose(); + } + } + IsDisposed = true; + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TBufferedTransport.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TBufferedTransport.cs.meta new file mode 100644 index 0000000..e95f921 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TBufferedTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d92fa7b7befab22429bc60d6d107d6dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TFramedTransport.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TFramedTransport.cs new file mode 100644 index 0000000..faa3fa6 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TFramedTransport.cs @@ -0,0 +1,200 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Buffers.Binary; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable CA1510 // net8 - use ThrowIfNull +#pragma warning disable CA1513 // net8 - use ThrowIfNull + +namespace Thrift.Transport +{ + // ReSharper disable once InconsistentNaming + public class TFramedTransport : TLayeredTransport + { + private const int HeaderSize = 4; + private readonly byte[] HeaderBuf = new byte[HeaderSize]; + private readonly Client.TMemoryBufferTransport ReadBuffer; + private readonly Client.TMemoryBufferTransport WriteBuffer; + + private bool IsDisposed; + + public class Factory : TTransportFactory + { + public override TTransport GetTransport(TTransport trans) + { + return new TFramedTransport(trans); + } + } + + public TFramedTransport(TTransport transport) + : base(transport) + { + ReadBuffer = new Client.TMemoryBufferTransport(Configuration); + WriteBuffer = new Client.TMemoryBufferTransport(Configuration); + InitWriteBuffer(); + } + + public override bool IsOpen => !IsDisposed && InnerTransport.IsOpen; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + CheckNotDisposed(); + + await InnerTransport.OpenAsync(cancellationToken); + } + + public override void Close() + { + CheckNotDisposed(); + + InnerTransport.Close(); + } + + public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + CheckNotDisposed(); + ValidateBufferArgs(buffer, offset, length); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + // Read another frame of data if we run out of bytes + if (ReadBuffer.Position >= ReadBuffer.Length) + { + await ReadFrameAsync(cancellationToken); + } + + return await ReadBuffer.ReadAsync(buffer, offset, length, cancellationToken); + } + + private async ValueTask ReadFrameAsync(CancellationToken cancellationToken) + { + UpdateKnownMessageSize(-1); + await InnerTransport.ReadAllAsync(HeaderBuf, 0, HeaderSize, cancellationToken); + int size = BinaryPrimitives.ReadInt32BigEndian(HeaderBuf); + + if ((0 > size) || (size > Configuration.MaxFrameSize)) // size must be in the range 0 to allowed max + throw new TTransportException(TTransportException.ExceptionType.Unknown, $"Maximum frame size exceeded ({size} bytes)"); + UpdateKnownMessageSize(size + HeaderSize); + + ReadBuffer.SetLength(size); + ReadBuffer.Seek(0, SeekOrigin.Begin); + + ReadBuffer.TryGetBuffer(out ArraySegment bufSegment); + await InnerTransport.ReadAllAsync(bufSegment.Array, 0, size, cancellationToken); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + CheckNotDisposed(); + ValidateBufferArgs(buffer, offset, length); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + if (WriteBuffer.Length > (int.MaxValue - length)) + { + await FlushAsync(cancellationToken); + } + + await WriteBuffer.WriteAsync(buffer, offset, length, cancellationToken); + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + CheckNotDisposed(); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + WriteBuffer.TryGetBuffer(out ArraySegment bufSegment); + + int dataLen = bufSegment.Count - HeaderSize; + if (dataLen < 0) + { + throw new InvalidOperationException(); // logic error actually + } + + // Inject message header into the reserved buffer space + BinaryPrimitives.WriteInt32BigEndian(bufSegment.Array, dataLen); + + // Send the entire message at once + await InnerTransport.WriteAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); + + InitWriteBuffer(); + + await InnerTransport.FlushAsync(cancellationToken); + } + + private void InitWriteBuffer() + { + // Reserve space for message header to be put right before sending it out + WriteBuffer.SetLength(HeaderSize); + WriteBuffer.Seek(0, SeekOrigin.End); + } + + public override void CheckReadBytesAvailable(long numBytes) + { + var buffered = ReadBuffer.Length - ReadBuffer.Position; + if (buffered < numBytes) + { + numBytes -= buffered; + InnerTransport.CheckReadBytesAvailable(numBytes); + } + } + + private void CheckNotDisposed() + { + if (IsDisposed) + { + throw new ObjectDisposedException(this.GetType().Name); + } + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!IsDisposed) + { + if (disposing) + { + ReadBuffer?.Dispose(); + WriteBuffer?.Dispose(); + InnerTransport?.Dispose(); + } + } + IsDisposed = true; + } + + public override void ResetMessageSizeAndConsumedBytes(long newSize = -1) + { + base.ResetMessageSizeAndConsumedBytes(newSize); + ReadBuffer.ResetMessageSizeAndConsumedBytes(newSize); + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TFramedTransport.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TFramedTransport.cs.meta new file mode 100644 index 0000000..3187cf3 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TFramedTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0812fa4415186fa458b001a437836b07 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TLayeredTransport.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TLayeredTransport.cs new file mode 100644 index 0000000..f9a4ce4 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TLayeredTransport.cs @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable IDE0290 // net8 - primary CTOR + +namespace Thrift.Transport +{ + public abstract class TLayeredTransport : TTransport + { + public readonly TTransport InnerTransport; + + public override TConfiguration Configuration { get => InnerTransport.Configuration; } + + public TLayeredTransport(TTransport transport) + { + InnerTransport = transport ?? throw new ArgumentNullException(nameof(transport)); + } + + public override void UpdateKnownMessageSize(long size) + { + InnerTransport.UpdateKnownMessageSize(size); + } + + public override void CheckReadBytesAvailable(long numBytes) + { + InnerTransport.CheckReadBytesAvailable(numBytes); + } + + public override void ResetMessageSizeAndConsumedBytes(long newSize = -1) + { + InnerTransport.ResetMessageSizeAndConsumedBytes(newSize); + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TLayeredTransport.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TLayeredTransport.cs.meta new file mode 100644 index 0000000..206c583 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/Layered/TLayeredTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc408d6d74391774fa67e1874cff1ad3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/TEndpointTransport.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/TEndpointTransport.cs new file mode 100644 index 0000000..27fb48d --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/TEndpointTransport.cs @@ -0,0 +1,104 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace Thrift.Transport +{ + + abstract public class TEndpointTransport : TTransport + { + protected long MaxMessageSize { get => Configuration.MaxMessageSize; } + protected long KnownMessageSize { get; private set; } + protected long RemainingMessageSize { get; private set; } + + private readonly TConfiguration _configuration; + public override TConfiguration Configuration { get => _configuration; } + + public TEndpointTransport( TConfiguration config) + { + _configuration = config ?? new TConfiguration(); + Debug.Assert(Configuration != null); + + ResetMessageSizeAndConsumedBytes(); + } + + /// + /// Resets RemainingMessageSize to the configured maximum + /// + public override void ResetMessageSizeAndConsumedBytes(long newSize = -1) + { + // full reset + if (newSize < 0) + { + KnownMessageSize = MaxMessageSize; + RemainingMessageSize = MaxMessageSize; + return; + } + + // update only: message size can shrink, but not grow + Debug.Assert(KnownMessageSize <= MaxMessageSize); + if (newSize > KnownMessageSize) + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "MaxMessageSize reached"); + + KnownMessageSize = newSize; + RemainingMessageSize = newSize; + } + + /// + /// Updates RemainingMessageSize to reflect then known real message size (e.g. framed transport). + /// Will throw if we already consumed too many bytes or if the new size is larger than allowed. + /// + /// + public override void UpdateKnownMessageSize(long size) + { + var consumed = KnownMessageSize - RemainingMessageSize; + ResetMessageSizeAndConsumedBytes(size); + CountConsumedMessageBytes(consumed); + } + + /// + /// Throws if there are not enough bytes in the input stream to satisfy a read of numBytes bytes of data + /// + /// + public override void CheckReadBytesAvailable(long numBytes) + { + if ((RemainingMessageSize < numBytes) || (numBytes < 0)) + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "MaxMessageSize reached"); + } + + /// + /// Consumes numBytes from the RemainingMessageSize. + /// + /// + protected void CountConsumedMessageBytes(long numBytes) + { + if (RemainingMessageSize >= numBytes) + { + RemainingMessageSize -= numBytes; + } + else + { + RemainingMessageSize = 0; + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "MaxMessageSize reached"); + } + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/TEndpointTransport.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/TEndpointTransport.cs.meta new file mode 100644 index 0000000..9197adf --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/TEndpointTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b3057f0c3ff0ec442b1162cc8ef0055d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransport.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransport.cs new file mode 100644 index 0000000..77ef281 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransport.cs @@ -0,0 +1,174 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +#pragma warning disable IDE0079 // net20 - unneeded suppression +#pragma warning disable CA1510 // net8 - use ThrowIfNull +#pragma warning disable CA1513 // net8 - use ThrowIfNull + +namespace Thrift.Transport +{ + //TODO: think about client info + // ReSharper disable once InconsistentNaming + public abstract class TTransport : IDisposable + { + //TODO: think how to avoid peek byte + private readonly byte[] _peekBuffer = new byte[1]; + private bool _hasPeekByte; + + public abstract bool IsOpen { get; } + public abstract TConfiguration Configuration { get; } + public abstract void UpdateKnownMessageSize(long size); + public abstract void CheckReadBytesAvailable(long numBytes); + public abstract void ResetMessageSizeAndConsumedBytes(long newSize = -1); + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public async ValueTask PeekAsync(CancellationToken cancellationToken) + { + //If we already have a byte read but not consumed, do nothing. + if (_hasPeekByte) + { + return true; + } + + //If transport closed we can't peek. + if (!IsOpen) + { + return false; + } + + //Try to read one byte. If succeeds we will need to store it for the next read. + try + { + var bytes = await ReadAsync(_peekBuffer, 0, 1, cancellationToken); + if (bytes == 0) + { + return false; + } + } + catch (IOException) + { + return false; + } + + _hasPeekByte = true; + return true; + } + + + public abstract Task OpenAsync(CancellationToken cancellationToken = default); + + public abstract void Close(); + + protected static void ValidateBufferArgs(byte[] buffer, int offset, int length) + { + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + +#if DEBUG // let it fail with OutOfRange in RELEASE mode + if (offset < 0) + { + throw new ArgumentOutOfRangeException(nameof(offset), "Buffer offset must be >= 0"); + } + + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length), "Buffer length must be >= 0"); + } + + if (offset + length > buffer.Length) + { + throw new ArgumentOutOfRangeException(nameof(buffer), "Not enough data"); + } +#endif + } + + + public abstract ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); + + public virtual async ValueTask ReadAllAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + ValidateBufferArgs(buffer, offset, length); + if (length <= 0) + return 0; + + // If we previously peeked a byte, we need to use that first. + var totalBytes = 0; + if (_hasPeekByte) + { + buffer[offset++] = _peekBuffer[0]; + _hasPeekByte = false; + if (1 == length) + { + return 1; // we're done + } + ++totalBytes; + } + + var remaining = length - totalBytes; + Debug.Assert(remaining > 0); // any other possible cases should have been handled already + while (true) + { + var numBytes = await ReadAsync(buffer, offset, remaining, cancellationToken); + totalBytes += numBytes; + if (totalBytes >= length) + { + return totalBytes; // we're done + } + + if (numBytes <= 0) + { + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, + "Cannot read, Remote side has closed"); + } + + remaining -= numBytes; + offset += numBytes; + } + } + + public virtual async Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) + { + await WriteAsync(buffer, 0, buffer.Length, CancellationToken.None); + } + + public virtual async Task WriteAsync(byte[] buffer, int offset, int length) + { + await WriteAsync(buffer, offset, length, CancellationToken.None); + } + + public abstract Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); + + + public abstract Task FlushAsync(CancellationToken cancellationToken); + + protected abstract void Dispose(bool disposing); + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransport.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransport.cs.meta new file mode 100644 index 0000000..055e92e --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransport.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f958cc470d8907f4ba2de25376b7a1ea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransportException.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransportException.cs new file mode 100644 index 0000000..760a178 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransportException.cs @@ -0,0 +1,60 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; + +namespace Thrift.Transport +{ + // ReSharper disable once InconsistentNaming + public class TTransportException : TException + { + public enum ExceptionType + { + Unknown, + NotOpen, + AlreadyOpen, + TimedOut, + EndOfFile, + Interrupted + } + + public ExceptionType ExType { get; private set; } + + public TTransportException() + { + } + + public TTransportException(ExceptionType exType, Exception inner = null) + : base(string.Empty, inner) + { + ExType = exType; + } + + public TTransportException(ExceptionType exType, string message, Exception inner = null) + : base(message, inner) + { + ExType = exType; + } + + public TTransportException(string message, Exception inner = null) + : base(message, inner) + { + } + + public ExceptionType Type => ExType; + } +} \ No newline at end of file diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransportException.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransportException.cs.meta new file mode 100644 index 0000000..0493fad --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransportException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bf3f37d29b264014c903e1a4dffd1ed5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransportFactory.cs b/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransportFactory.cs new file mode 100644 index 0000000..5f604f1 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransportFactory.cs @@ -0,0 +1,35 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +namespace Thrift.Transport +{ + /// + /// From Mark Slee & Aditya Agarwal of Facebook: + /// Factory class used to create wrapped instance of Transports. + /// This is used primarily in servers, which get Transports from + /// a ServerTransport and then may want to mutate them (i.e. create + /// a BufferedTransport from the underlying base transport) + /// + // ReSharper disable once InconsistentNaming + public class TTransportFactory + { + public virtual TTransport GetTransport(TTransport trans) + { + return trans; + } + } +} diff --git a/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransportFactory.cs.meta b/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransportFactory.cs.meta new file mode 100644 index 0000000..03a01db --- /dev/null +++ b/Packages/com.bywaystudios.thrift/Runtime/Transport/TTransportFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 87f32f9dccc6ac9479c8ddc5cd902666 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.thrift/package.json b/Packages/com.bywaystudios.thrift/package.json new file mode 100644 index 0000000..372f850 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/package.json @@ -0,0 +1,11 @@ +{ + "name": "com.bywaystudios.thrift", + "displayName": "Thrift", + "version": "0.22.0-exp.1", + "description": "Package to Import Apache Thrift", + "repository": { + "url": "git@gitea.bywaystudios.com:wangshiyao/ThriftPackage.git", + "type": "git", + "revision": null + } +} diff --git a/Packages/com.bywaystudios.thrift/package.json.meta b/Packages/com.bywaystudios.thrift/package.json.meta new file mode 100644 index 0000000..4bfa541 --- /dev/null +++ b/Packages/com.bywaystudios.thrift/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f1ece8aa29c7c6944a4184fda86cf77f +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/.attestation.p7m b/Packages/com.unity.nuget.newtonsoft-json/.attestation.p7m new file mode 100644 index 0000000..13c5d77 Binary files /dev/null and b/Packages/com.unity.nuget.newtonsoft-json/.attestation.p7m differ diff --git a/Packages/com.unity.nuget.newtonsoft-json/.signature b/Packages/com.unity.nuget.newtonsoft-json/.signature new file mode 100644 index 0000000..174c70b --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/.signature @@ -0,0 +1 @@ +{"timestamp":1682613715,"signature":"ASVE5AxdkAkRhzuFeuvYGTMbcEQhLN0o4WEFhmFe20wZQkm4/TYBU/HMJl5nJeHY9em7sF30LUVued47FllfrgENx9qEcdgxJgxcnT6a98pUGwNvX6u0fLArs6tPH/mjCVaaoQY5VUFVchAsj9aVow9stjyCmPmRiezHT43nZaf0uCa6unqRSu8YILUzOZt3Ln0XlfYmf0UAaVFtkndv3J+QFOcmZv9lupbRKTTjryGzgEo9cogRa07kDTeLx0XDQ6rda8abtlqVdtXvbKDjS19q0XOWRCWM0bmyCCr5HEsZSJzhBDm2jHT/lo6vhtDZbj4GzM5CtfRVIO6RDTfZ8CnzM4Xk1L7GXqE4gKPl6SjhZvrerg8ClfBm0bw8Kx3llzczk+PGQYWq62xXI3lj3cWCeSl3z0fgIUdEMrGW+XqxXhNsHh2pCGENqA0zWtP8fYu0UqCRX5KJahlrPcWlDtBW3HN8NuJmF0mvclkONx7+Hk68w5BNM8GT5iH2CrbW","publicKey":"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQm9qQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FZOEFNSUlCaWdLQ0FZRUFzdUhXYUhsZ0I1cVF4ZEJjTlJKSAordHR4SmoxcVY1NTdvMlZaRE1XaXhYRVBkRTBEMVFkT1JIRXNSS1RscmplUXlERU83ZlNQS0ZwZ1A3MU5TTnJCCkFHM2NFSU45aHNQVDhOVmllZmdWem5QTkVMenFkVmdEbFhpb2VpUnV6OERKWFgvblpmU1JWKytwbk9ySTRibG4KS0twelJlNW14OTc1SjhxZ1FvRktKT0NNRlpHdkJMR2MxSzZZaEIzOHJFODZCZzgzbUovWjBEYkVmQjBxZm13cgo2ZDVFUXFsd0E5Y3JZT1YyV1VpWXprSnBLNmJZNzRZNmM1TmpBcEFKeGNiaTFOaDlRVEhUcU44N0ZtMDF0R1ZwCjVNd1pXSWZuYVRUemEvTGZLelR5U0pka0tldEZMVGdkYXpMYlpzUEE2aHBSK0FJRTJhc0tLTi84UUk1N3UzU2cKL2xyMnZKS1IvU2l5eEN1Q20vQWJkYnJMbXk0WjlSdm1jMGdpclA4T0lLQWxBRWZ2TzV5Z2hSKy8vd1RpTFlzUQp1SllDM0V2UE16ZGdKUzdGR2FscnFLZzlPTCsxVzROY05yNWdveVdSUUJ0cktKaWlTZEJVWmVxb0RvSUY5NHpCCndGbzJJT1JFdXFqcU51M3diMWZIM3p1dGdtalFra3IxVjJhd3hmcExLWlROQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg"} \ No newline at end of file diff --git a/Packages/com.unity.nuget.newtonsoft-json/CHANGELOG.md b/Packages/com.unity.nuget.newtonsoft-json/CHANGELOG.md new file mode 100644 index 0000000..fd48a85 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/CHANGELOG.md @@ -0,0 +1,130 @@ +# Changelog + +All notable changes to this package will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [3.2.1] - 2023-04-27 + +* Fixed Newtonsoft DLL when compiling with netstandard 2.0. + +## [3.2.0] - 2023-04-19 + +* Fixed Newtonsoft DLL public key token so it properly supports assembly strong name. +* Support Newtonsoft's `JsonSelectSettings.RegexMatchTimeout`. + +## [3.1.0] - 2023-02-28 + +* Updated AOT and Editor DLLs to corresponds to Newtonsoft.Json version 13.0.2 + +## [3.0.2] - 2022-03-29 + +* Removed test code from package. + +## [3.0.1] - 2022-02-21 + +* Updated license file + +## [3.0.0] - 2022-01-27 + +* Updated Documentation + +## [3.0.0-preview.1] - 2022-01-25 + +* Updated AOT and Editor DLLs to corresponds to Newtonsoft.Json version 13.0.1 +* Removed deprecated Portable DLL +* Updated README +* Updated Documentation + +## [2.0.2] - 2020-10-04 + +* Updated README +* Added package signature for validation + +## [2.0.1-preview.1] - 2020-11-14 + +* Updated README and Internal Fixtures + +## [2.0.0] - 2020-04-20 + +### This is the release of *Unity Package Nuget.NewtonsoftJson* v2.0.0. + +* Updated dll to AOT compatible version to allow for IL2CPP compilation platform targets +* Added dll to Portable compatible version to allow for additional platform targets +* Updated associated Package Documents + +## [2.0.0-preview] - 2019-11-14 + +### This is the preview of *Unity Package Nuget.NewtonsoftJson* v2.0.0-preview. + +* Changed dll to AOT compatible version to allow for IL2CPP compilation platform targets + +## [1.1.2] - 2019-10-31 + +### This is the release of *Unity Package Nuget.NewtonsoftJson* v1.1.2. + +* Fixed tests for 2018.4. + +## [1.1.1] - 2019-10-30 + +### This is the release of *Unity Package Nuget.NewtonsoftJson* v1.1.1. + +* Added some sanity tests to catch issues in the CI. + +## [1.1.0] - 2019-10-29 + +### This is the release of *Unity Package Nuget.NewtonsoftJson* v1.1.0. + +* Use .net standard 2.0 version of the dll. +* Renamed the dll to match the assembly name. Users will need to update their assembly references. + +## [1.1.0-preview.1] - 2019-08-09 + +### This is the first preview of *Unity Package Nuget.Newtonsoft.Json* version 1.1.0. + +* Updated to bug fix release 12.0.2 of Newtonsoft Json. +* Updated package description. + +## [1.0.1-preview.2] - 2019-10-02 + +### This is the second preview release of *Unity Package Nuget.NewtonsoftJson* v1.0.1. + +* Use .net standard 2.0 version of the dll. + +## [1.0.1-preview.1] - 2019-08-13 + +### This is the first preview release of *Unity Package Nuget.Newtonsoft.Json* v1.0.1. + +* Renamed the dll to match the assembly name. Users will need to update their assembly references. + +## [1.0.0] - 2019-08-08 + +### This is the first release of *Unity Package Nuget.Newtonsoft.Json*. + +* No notable changes from the previous preview release. + +## [1.0.0-preview.4] - 2019-08-06 + +### This is the fourth preview release of *Unity Package Nuget.Newtonsoft.Json*. + +* Remove the unused asmdef file and make it such that the dll needs to be explicitly included. + +## [1.0.0-preview.3] - 2019-07-03 + +### This is the third preview release of *Unity Package Nuget.Newtonsoft.Json*. + +* Update the documentation for the package and the package description to state that this package is for internal Unity + use __only__. + +## [1.0.0-preview.2] - 2019-06-21 + +### This is the second preview release of *Unity Package Nuget.NewtonsoftJson*. + +* The name of the package has been changed to avoid a naming issue with npm. + +## [1.0.0-preview.1] - 2019-06-21 + +### This is the first preview release of *Unity Package Nuget.NewtonsoftJson*. + +* This is the first preview of a the custom Unity package for NewtonsoftJson. Please report any bugs. diff --git a/Packages/com.unity.nuget.newtonsoft-json/CHANGELOG.md.meta b/Packages/com.unity.nuget.newtonsoft-json/CHANGELOG.md.meta new file mode 100644 index 0000000..f64aa98 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/CHANGELOG.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 16f24f695cc06684991baf4b1bc6ad22 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/Documentation~/index.md b/Packages/com.unity.nuget.newtonsoft-json/Documentation~/index.md new file mode 100644 index 0000000..9720308 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Documentation~/index.md @@ -0,0 +1,21 @@ +# Newtonsoft Json Unity Package + +This is a Unity package for Newtonsoft Json and corresponds to Newtonsoft.Json version 13.0.2. + +Documentation for this Package is provided as links to the Json.NET Documentation. + +## Json.NET is a popular JSON framework for .NET + +### Documentation + +* [Json.NET Main Page](https://www.newtonsoft.com/json) +* [Json.NET Documentation](https://www.newtonsoft.com/json/help/html/Introduction.htm) +* [Json.NET Source Code](https://github.com/JamesNK/Newtonsoft.Json) + +### Use Cases + +- Flexible JSON serializer for converting between .NET objects and JSON +- LINQ to JSON for manually reading and writing JSON +- Write indented, easy-to-read JSON +- Convert JSON to and from XML +- Supports .NET Standard 2.0, .NET 2, .NET 3.5, .NET 4, .NET 4.5, Silverlight, Windows Phone and Windows 8 Store diff --git a/Packages/com.unity.nuget.newtonsoft-json/LICENSE.md b/Packages/com.unity.nuget.newtonsoft-json/LICENSE.md new file mode 100644 index 0000000..f1e628e --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/LICENSE.md @@ -0,0 +1,5 @@ +Nuget.Newtonsoft.Json copyright © 2022 Unity Technologies ApS + +Licensed under the Unity Companion License for Unity-dependent projects--see [Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). + +Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the license for details on these and other terms and conditions. diff --git a/Packages/com.unity.nuget.newtonsoft-json/LICENSE.md.meta b/Packages/com.unity.nuget.newtonsoft-json/LICENSE.md.meta new file mode 100644 index 0000000..df9df66 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/LICENSE.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 24efe08f95549ab4699df4c1b55703e5 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/README.md b/Packages/com.unity.nuget.newtonsoft-json/README.md new file mode 100644 index 0000000..acb2a0b --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/README.md @@ -0,0 +1,8 @@ +This package wraps the Json.NET DLLs. + +# Newtonsoft.JSON +Unity Package for [Newtonsoft's JSON library] (https://www.newtonsoft.com/json) + +This package includes the DLL version of JSON.Net Version: 13.0.1. It also has the AOT DLL for additional Platform Compatibility. + +This package is intended to be inherited as a dependency, and should not be directly installed, by end users. diff --git a/Packages/com.unity.nuget.newtonsoft-json/README.md.meta b/Packages/com.unity.nuget.newtonsoft-json/README.md.meta new file mode 100644 index 0000000..011fcb3 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 51bd45ca4f0f28342a12f4b0c80e9f4f +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/Runtime.meta b/Packages/com.unity.nuget.newtonsoft-json/Runtime.meta new file mode 100644 index 0000000..4f65c4f --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: de1c7164adaf49d47b5de31c140713c9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT.meta b/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT.meta new file mode 100644 index 0000000..f9dba64 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 14f21d7a1e53a8c4e87b25526a7eb63c +folderAsset: yes +timeCreated: 1466788345 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.dll b/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.dll new file mode 100644 index 0000000..d9a10ce Binary files /dev/null and b/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.dll differ diff --git a/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.dll.meta b/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.dll.meta new file mode 100644 index 0000000..f82f2cc --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.dll.meta @@ -0,0 +1,129 @@ +fileFormatVersion: 2 +guid: 6c694cfdc33ae264fb33e0cd1c7e25cf +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 1 + Exclude Linux: 0 + Exclude Linux64: 0 + Exclude LinuxUniversal: 0 + Exclude OSXUniversal: 0 + Exclude WebGL: 0 + Exclude Win: 0 + Exclude Win64: 0 + Exclude WindowsStoreApps: 0 + Exclude iOS: 0 + Exclude tvOS: 0 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 1 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 1 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: LinuxUniversal + second: + enabled: 1 + settings: {} + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + WebGL: WebGL + second: + enabled: 1 + settings: {} + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 1 + settings: + CPU: AnyCPU + DontProcess: false + PlaceholderPath: + SDK: AnySDK + ScriptingBackend: AnyScriptingBackend + - first: + iPhone: iOS + second: + enabled: 1 + settings: + AddToEmbeddedBinaries: false + CompileFlags: + FrameworkDependencies: + - first: + tvOS: tvOS + second: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.pdb.meta b/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.pdb.meta new file mode 100644 index 0000000..2ce9637 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.pdb.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 1396f5bdc432cd247ac75b97a31e4d1a +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.xml b/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.xml new file mode 100644 index 0000000..19b2923 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.xml @@ -0,0 +1,11347 @@ + + + + Newtonsoft.Json + + + + + Represents a BSON Oid (object id). + + + + + Gets or sets the value of the Oid. + + The value of the Oid. + + + + Initializes a new instance of the class. + + The Oid value. + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized BSON data. + + + + + Gets or sets a value indicating whether binary data reading should be compatible with incorrect Json.NET 3.5 written binary. + + + true if binary data reading will be compatible with incorrect Json.NET 3.5 written binary; otherwise, false. + + + + + Gets or sets a value indicating whether the root object will be read as a JSON array. + + + true if the root object will be read as a JSON array; otherwise, false. + + + + + Gets or sets the used when reading values from BSON. + + The used when reading values from BSON. + + + + Initializes a new instance of the class. + + The containing the BSON data to read. + + + + Initializes a new instance of the class. + + The containing the BSON data to read. + + + + Initializes a new instance of the class. + + The containing the BSON data to read. + if set to true the root object will be read as a JSON array. + The used when reading values from BSON. + + + + Initializes a new instance of the class. + + The containing the BSON data to read. + if set to true the root object will be read as a JSON array. + The used when reading values from BSON. + + + + Reads the next JSON token from the underlying . + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Changes the reader's state to . + If is set to true, the underlying is also closed. + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating BSON data. + + + + + Gets or sets the used when writing values to BSON. + When set to no conversion will occur. + + The used when writing values to BSON. + + + + Initializes a new instance of the class. + + The to write to. + + + + Initializes a new instance of the class. + + The to write to. + + + + Flushes whatever is in the buffer to the underlying and also flushes the underlying stream. + + + + + Writes the end. + + The token. + + + + Writes a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes raw JSON. + + The raw JSON to write. + + + + Writes raw JSON where a value is expected and updates the writer's state. + + The raw JSON to write. + + + + Writes the beginning of a JSON array. + + + + + Writes the beginning of a JSON object. + + + + + Writes the property name of a name/value pair on a JSON object. + + The name of the property. + + + + Closes this writer. + If is set to true, the underlying is also closed. + If is set to true, the JSON is auto-completed. + + + + + Writes a value. + An error will raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a [] value. + + The [] value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a [] value that represents a BSON object id. + + The Object ID value to write. + + + + Writes a BSON regex. + + The regex pattern. + The regex options. + + + + Specifies how constructors are used when initializing objects during deserialization by the . + + + + + First attempt to use the public default constructor, then fall back to a single parameterized constructor, then to the non-public default constructor. + + + + + Json.NET will use a non-public default constructor before falling back to a parameterized constructor. + + + + + Converts a binary value to and from a base 64 string value. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a to and from JSON and BSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Creates a custom object. + + The object type to convert. + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Creates an object which will then be populated by the serializer. + + Type of the object. + The created object. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Gets a value indicating whether this can write JSON. + + + true if this can write JSON; otherwise, false. + + + + + Converts a to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Converts a to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Provides a base class for converting a to and from JSON. + + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a F# discriminated union type to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts an Entity Framework to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts an to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Gets a value indicating whether this can write JSON. + + + true if this can write JSON; otherwise, false. + + + + + Converts a to and from the ISO 8601 date format (e.g. "2008-04-12T12:53Z"). + + + + + Gets or sets the date time styles used when converting a date to and from JSON. + + The date time styles used when converting a date to and from JSON. + + + + Gets or sets the date time format used when converting a date to and from JSON. + + The date time format used when converting a date to and from JSON. + + + + Gets or sets the culture used when converting a date to and from JSON. + + The culture used when converting a date to and from JSON. + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Converts a to and from a JavaScript Date constructor (e.g. new Date(52231943)). + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing property value of the JSON that is being converted. + The calling serializer. + The object value. + + + + Converts a to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a to and from JSON and BSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts an to and from its name string value. + + + + + Gets or sets a value indicating whether the written enum text should be camel case. + The default value is false. + + true if the written enum text will be camel case; otherwise, false. + + + + Gets or sets the naming strategy used to resolve how enum text is written. + + The naming strategy used to resolve how enum text is written. + + + + Gets or sets a value indicating whether integer values are allowed when serializing and deserializing. + The default value is true. + + true if integers are allowed when serializing and deserializing; otherwise, false. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + true if the written enum text will be camel case; otherwise, false. + + + + Initializes a new instance of the class. + + The naming strategy used to resolve how enum text is written. + true if integers are allowed when serializing and deserializing; otherwise, false. + + + + Initializes a new instance of the class. + + The of the used to write enum text. + + + + Initializes a new instance of the class. + + The of the used to write enum text. + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + When non-null, there must be a constructor defined in the that exactly matches the number, + order, and type of these parameters. + + + + + Initializes a new instance of the class. + + The of the used to write enum text. + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + When non-null, there must be a constructor defined in the that exactly matches the number, + order, and type of these parameters. + + true if integers are allowed when serializing and deserializing; otherwise, false. + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a to and from Unix epoch time + + + + + Gets or sets a value indicating whether the dates before Unix epoch + should converted to and from JSON. + + + true to allow converting dates before Unix epoch to and from JSON; + false to throw an exception when a date being converted to or from JSON + occurred before Unix epoch. The default value is false. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + true to allow converting dates before Unix epoch to and from JSON; + false to throw an exception when a date being converted to or from JSON + occurred before Unix epoch. The default value is false. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing property value of the JSON that is being converted. + The calling serializer. + The object value. + + + + Converts a to and from a string (e.g. "1.2.3.4"). + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing property value of the JSON that is being converted. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts XML to and from JSON. + + + + + Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produced multiple root elements. + + The name of the deserialized root element. + + + + Gets or sets a value to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + true if the array attribute is written to the XML; otherwise, false. + + + + Gets or sets a value indicating whether to write the root JSON object. + + true if the JSON root object is omitted; otherwise, false. + + + + Gets or sets a value indicating whether to encode special characters when converting JSON to XML. + If true, special characters like ':', '@', '?', '#' and '$' in JSON property names aren't used to specify + XML namespaces, attributes or processing directives. Instead special characters are encoded and written + as part of the XML element name. + + true if special characters are encoded; otherwise, false. + + + + Writes the JSON representation of the object. + + The to write to. + The calling serializer. + The value. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Checks if the is a namespace attribute. + + Attribute name to test. + The attribute name prefix if it has one, otherwise an empty string. + true if attribute name is for a namespace attribute, otherwise false. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Specifies how dates are formatted when writing JSON text. + + + + + Dates are written in the ISO 8601 format, e.g. "2012-03-21T05:40Z". + + + + + Dates are written in the Microsoft JSON format, e.g. "\/Date(1198908717056)\/". + + + + + Specifies how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON text. + + + + + Date formatted strings are not parsed to a date type and are read as strings. + + + + + Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to . + + + + + Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to . + + + + + Specifies how to treat the time value when converting between string and . + + + + + Treat as local time. If the object represents a Coordinated Universal Time (UTC), it is converted to the local time. + + + + + Treat as a UTC. If the object represents a local time, it is converted to a UTC. + + + + + Treat as a local time if a is being converted to a string. + If a string is being converted to , convert to a local time if a time zone is specified. + + + + + Time zone information should be preserved when converting. + + + + + The default JSON name table implementation. + + + + + Initializes a new instance of the class. + + + + + Gets a string containing the same characters as the specified range of characters in the given array. + + The character array containing the name to find. + The zero-based index into the array specifying the first character of the name. + The number of characters in the name. + A string containing the same characters as the specified range of characters in the given array. + + + + Adds the specified string into name table. + + The string to add. + This method is not thread-safe. + The resolved string. + + + + Specifies default value handling options for the . + + + + + + + + + Include members where the member value is the same as the member's default value when serializing objects. + Included members are written to JSON. Has no effect when deserializing. + + + + + Ignore members where the member value is the same as the member's default value when serializing objects + so that it is not written to JSON. + This option will ignore all default values (e.g. null for objects and nullable types; 0 for integers, + decimals and floating point numbers; and false for booleans). The default value ignored can be changed by + placing the on the property. + + + + + Members with a default value but no JSON will be set to their default value when deserializing. + + + + + Ignore members where the member value is the same as the member's default value when serializing objects + and set members to their default value when deserializing. + + + + + Specifies float format handling options when writing special floating point numbers, e.g. , + and with . + + + + + Write special floating point values as strings in JSON, e.g. "NaN", "Infinity", "-Infinity". + + + + + Write special floating point values as symbols in JSON, e.g. NaN, Infinity, -Infinity. + Note that this will produce non-valid JSON. + + + + + Write special floating point values as the property's default value in JSON, e.g. 0.0 for a property, null for a of property. + + + + + Specifies how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. + + + + + Floating point numbers are parsed to . + + + + + Floating point numbers are parsed to . + + + + + Specifies formatting options for the . + + + + + No special formatting is applied. This is the default. + + + + + Causes child objects to be indented according to the and settings. + + + + + Provides an interface for using pooled arrays. + + The array type content. + + + + Rent an array from the pool. This array must be returned when it is no longer needed. + + The minimum required length of the array. The returned array may be longer. + The rented array from the pool. This array must be returned when it is no longer needed. + + + + Return an array to the pool. + + The array that is being returned. + + + + Provides an interface to enable a class to return line and position information. + + + + + Gets a value indicating whether the class can return line information. + + + true if and can be provided; otherwise, false. + + + + + Gets the current line number. + + The current line number or 0 if no line information is available (for example, when returns false). + + + + Gets the current line position. + + The current line position or 0 if no line information is available (for example, when returns false). + + + + Instructs the how to serialize the collection. + + + + + Gets or sets a value indicating whether null items are allowed in the collection. + + true if null items are allowed in the collection; otherwise, false. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with a flag indicating whether the array can contain null items. + + A flag indicating whether the array can contain null items. + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + Instructs the to use the specified constructor when deserializing that object. + + + + + Instructs the how to serialize the object. + + + + + Gets or sets the id. + + The id. + + + + Gets or sets the title. + + The title. + + + + Gets or sets the description. + + The description. + + + + Gets or sets the collection's items converter. + + The collection's items converter. + + + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + When non-null, there must be a constructor defined in the that exactly matches the number, + order, and type of these parameters. + + + + [JsonContainer(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })] + + + + + + Gets or sets the of the . + + The of the . + + + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + When non-null, there must be a constructor defined in the that exactly matches the number, + order, and type of these parameters. + + + + [JsonContainer(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })] + + + + + + Gets or sets a value that indicates whether to preserve object references. + + + true to keep object reference; otherwise, false. The default is false. + + + + + Gets or sets a value that indicates whether to preserve collection's items references. + + + true to keep collection's items object references; otherwise, false. The default is false. + + + + + Gets or sets the reference loop handling used when serializing the collection's items. + + The reference loop handling. + + + + Gets or sets the type name handling used when serializing the collection's items. + + The type name handling. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + Provides methods for converting between .NET types and JSON types. + + + + + + + + Gets or sets a function that creates default . + Default settings are automatically used by serialization methods on , + and and on . + To serialize without using any default settings create a with + . + + + + + Represents JavaScript's boolean value true as a string. This field is read-only. + + + + + Represents JavaScript's boolean value false as a string. This field is read-only. + + + + + Represents JavaScript's null as a string. This field is read-only. + + + + + Represents JavaScript's undefined as a string. This field is read-only. + + + + + Represents JavaScript's positive infinity as a string. This field is read-only. + + + + + Represents JavaScript's negative infinity as a string. This field is read-only. + + + + + Represents JavaScript's NaN as a string. This field is read-only. + + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation using the specified. + + The value to convert. + The format the date will be converted to. + The time zone handling when the date is converted to a string. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation using the specified. + + The value to convert. + The format the date will be converted to. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + The string delimiter character. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + The string delimiter character. + The string escape handling. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Serializes the specified object to a JSON string. + + The object to serialize. + A JSON string representation of the object. + + + + Serializes the specified object to a JSON string using formatting. + + The object to serialize. + Indicates how the output should be formatted. + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using a collection of . + + The object to serialize. + A collection of converters used while serializing. + A JSON string representation of the object. + + + + Serializes the specified object to a JSON string using formatting and a collection of . + + The object to serialize. + Indicates how the output should be formatted. + A collection of converters used while serializing. + A JSON string representation of the object. + + + + Serializes the specified object to a JSON string using . + + The object to serialize. + The used to serialize the object. + If this is null, default serialization settings will be used. + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using a type, formatting and . + + The object to serialize. + The used to serialize the object. + If this is null, default serialization settings will be used. + + The type of the value being serialized. + This parameter is used when is to write out the type name if the type of the value does not match. + Specifying the type is optional. + + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using formatting and . + + The object to serialize. + Indicates how the output should be formatted. + The used to serialize the object. + If this is null, default serialization settings will be used. + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using a type, formatting and . + + The object to serialize. + Indicates how the output should be formatted. + The used to serialize the object. + If this is null, default serialization settings will be used. + + The type of the value being serialized. + This parameter is used when is to write out the type name if the type of the value does not match. + Specifying the type is optional. + + + A JSON string representation of the object. + + + + + Deserializes the JSON to a .NET object. + + The JSON to deserialize. + The deserialized object from the JSON string. + + + + Deserializes the JSON to a .NET object using . + + The JSON to deserialize. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type. + + The JSON to deserialize. + The of object being deserialized. + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type. + + The type of the object to deserialize to. + The JSON to deserialize. + The deserialized object from the JSON string. + + + + Deserializes the JSON to the given anonymous type. + + + The anonymous type to deserialize to. This can't be specified + traditionally and must be inferred from the anonymous type passed + as a parameter. + + The JSON to deserialize. + The anonymous type object. + The deserialized anonymous type from the JSON string. + + + + Deserializes the JSON to the given anonymous type using . + + + The anonymous type to deserialize to. This can't be specified + traditionally and must be inferred from the anonymous type passed + as a parameter. + + The JSON to deserialize. + The anonymous type object. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + The deserialized anonymous type from the JSON string. + + + + Deserializes the JSON to the specified .NET type using a collection of . + + The type of the object to deserialize to. + The JSON to deserialize. + Converters to use while deserializing. + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type using . + + The type of the object to deserialize to. + The object to deserialize. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type using a collection of . + + The JSON to deserialize. + The type of the object to deserialize. + Converters to use while deserializing. + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type using . + + The JSON to deserialize. + The type of the object to deserialize to. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + The deserialized object from the JSON string. + + + + Populates the object with values from the JSON string. + + The JSON to populate values from. + The target object to populate values onto. + + + + Populates the object with values from the JSON string using . + + The JSON to populate values from. + The target object to populate values onto. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + + + + Serializes the to a JSON string. + + The node to serialize. + A JSON string of the . + + + + Serializes the to a JSON string using formatting. + + The node to serialize. + Indicates how the output should be formatted. + A JSON string of the . + + + + Serializes the to a JSON string using formatting and omits the root object if is true. + + The node to serialize. + Indicates how the output should be formatted. + Omits writing the root object. + A JSON string of the . + + + + Deserializes the from a JSON string. + + The JSON string. + The deserialized . + + + + Deserializes the from a JSON string nested in a root element specified by . + + The JSON string. + The name of the root element to append when deserializing. + The deserialized . + + + + Deserializes the from a JSON string nested in a root element specified by + and writes a Json.NET array attribute for collections. + + The JSON string. + The name of the root element to append when deserializing. + + A value to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + The deserialized . + + + + Deserializes the from a JSON string nested in a root element specified by , + writes a Json.NET array attribute for collections, and encodes special characters. + + The JSON string. + The name of the root element to append when deserializing. + + A value to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + + A value to indicate whether to encode special characters when converting JSON to XML. + If true, special characters like ':', '@', '?', '#' and '$' in JSON property names aren't used to specify + XML namespaces, attributes or processing directives. Instead special characters are encoded and written + as part of the XML element name. + + The deserialized . + + + + Serializes the to a JSON string. + + The node to convert to JSON. + A JSON string of the . + + + + Serializes the to a JSON string using formatting. + + The node to convert to JSON. + Indicates how the output should be formatted. + A JSON string of the . + + + + Serializes the to a JSON string using formatting and omits the root object if is true. + + The node to serialize. + Indicates how the output should be formatted. + Omits writing the root object. + A JSON string of the . + + + + Deserializes the from a JSON string. + + The JSON string. + The deserialized . + + + + Deserializes the from a JSON string nested in a root element specified by . + + The JSON string. + The name of the root element to append when deserializing. + The deserialized . + + + + Deserializes the from a JSON string nested in a root element specified by + and writes a Json.NET array attribute for collections. + + The JSON string. + The name of the root element to append when deserializing. + + A value to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + The deserialized . + + + + Deserializes the from a JSON string nested in a root element specified by , + writes a Json.NET array attribute for collections, and encodes special characters. + + The JSON string. + The name of the root element to append when deserializing. + + A value to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + + A value to indicate whether to encode special characters when converting JSON to XML. + If true, special characters like ':', '@', '?', '#' and '$' in JSON property names aren't used to specify + XML namespaces, attributes or processing directives. Instead special characters are encoded and written + as part of the XML element name. + + The deserialized . + + + + Converts an object to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Gets a value indicating whether this can read JSON. + + true if this can read JSON; otherwise, false. + + + + Gets a value indicating whether this can write JSON. + + true if this can write JSON; otherwise, false. + + + + Converts an object to and from JSON. + + The object type to convert. + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. If there is no existing value then null will be used. + The existing value has a value. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Instructs the to use the specified when serializing the member or class. + + + + + Gets the of the . + + The of the . + + + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + + + + + Initializes a new instance of the class. + + Type of the . + + + + Initializes a new instance of the class. + + Type of the . + Parameter list to use when constructing the . Can be null. + + + + Represents a collection of . + + + + + Instructs the how to serialize the collection. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + The exception thrown when an error occurs during JSON serialization or deserialization. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Instructs the to deserialize properties with no matching class member into the specified collection + and write values during serialization. + + + + + Gets or sets a value that indicates whether to write extension data when serializing the object. + + + true to write extension data when serializing the object; otherwise, false. The default is true. + + + + + Gets or sets a value that indicates whether to read extension data when deserializing the object. + + + true to read extension data when deserializing the object; otherwise, false. The default is true. + + + + + Initializes a new instance of the class. + + + + + Instructs the not to serialize the public field or public read/write property value. + + + + + Base class for a table of atomized string objects. + + + + + Gets a string containing the same characters as the specified range of characters in the given array. + + The character array containing the name to find. + The zero-based index into the array specifying the first character of the name. + The number of characters in the name. + A string containing the same characters as the specified range of characters in the given array. + + + + Instructs the how to serialize the object. + + + + + Gets or sets the member serialization. + + The member serialization. + + + + Gets or sets the missing member handling used when deserializing this object. + + The missing member handling. + + + + Gets or sets how the object's properties with null values are handled during serialization and deserialization. + + How the object's properties with null values are handled during serialization and deserialization. + + + + Gets or sets a value that indicates whether the object's properties are required. + + + A value indicating whether the object's properties are required. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified member serialization. + + The member serialization. + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + Instructs the to always serialize the member with the specified name. + + + + + Gets or sets the type used when serializing the property's collection items. + + The collection's items type. + + + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + When non-null, there must be a constructor defined in the that exactly matches the number, + order, and type of these parameters. + + + + [JsonProperty(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })] + + + + + + Gets or sets the of the . + + The of the . + + + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + When non-null, there must be a constructor defined in the that exactly matches the number, + order, and type of these parameters. + + + + [JsonProperty(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })] + + + + + + Gets or sets the null value handling used when serializing this property. + + The null value handling. + + + + Gets or sets the default value handling used when serializing this property. + + The default value handling. + + + + Gets or sets the reference loop handling used when serializing this property. + + The reference loop handling. + + + + Gets or sets the object creation handling used when deserializing this property. + + The object creation handling. + + + + Gets or sets the type name handling used when serializing this property. + + The type name handling. + + + + Gets or sets whether this property's value is serialized as a reference. + + Whether this property's value is serialized as a reference. + + + + Gets or sets the order of serialization of a member. + + The numeric order of serialization. + + + + Gets or sets a value indicating whether this property is required. + + + A value indicating whether this property is required. + + + + + Gets or sets the name of the property. + + The name of the property. + + + + Gets or sets the reference loop handling used when serializing the property's collection items. + + The collection's items reference loop handling. + + + + Gets or sets the type name handling used when serializing the property's collection items. + + The collection's items type name handling. + + + + Gets or sets whether this property's collection items are serialized as a reference. + + Whether this property's collection items are serialized as a reference. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified name. + + Name of the property. + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized JSON data. + + + + + Asynchronously reads the next JSON token from the source. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns true if the next token was read successfully; false if there are no more tokens to read. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously skips the children of the current token. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a []. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the []. This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Specifies the state of the reader. + + + + + A read method has not been called. + + + + + The end of the file has been reached successfully. + + + + + Reader is at a property. + + + + + Reader is at the start of an object. + + + + + Reader is in an object. + + + + + Reader is at the start of an array. + + + + + Reader is in an array. + + + + + The method has been called. + + + + + Reader has just read a value. + + + + + Reader is at the start of a constructor. + + + + + Reader is in a constructor. + + + + + An error occurred that prevents the read operation from continuing. + + + + + The end of the file has been reached successfully. + + + + + Gets the current reader state. + + The current reader state. + + + + Gets or sets a value indicating whether the source should be closed when this reader is closed. + + + true to close the source when this reader is closed; otherwise false. The default is true. + + + + + Gets or sets a value indicating whether multiple pieces of JSON content can + be read from a continuous stream without erroring. + + + true to support reading multiple pieces of JSON content; otherwise false. + The default is false. + + + + + Gets the quotation mark character used to enclose the value of a string. + + + + + Gets or sets how time zones are handled when reading JSON. + + + + + Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON. + + + + + Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. + + + + + Gets or sets how custom date formatted strings are parsed when reading JSON. + + + + + Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a . + A null value means there is no maximum. + The default value is 64. + + + + + Gets the type of the current JSON token. + + + + + Gets the text value of the current JSON token. + + + + + Gets the .NET type for the current JSON token. + + + + + Gets the depth of the current token in the JSON document. + + The depth of the current token in the JSON document. + + + + Gets the path of the current JSON token. + + + + + Gets or sets the culture used when reading JSON. Defaults to . + + + + + Initializes a new instance of the class. + + + + + Reads the next JSON token from the source. + + true if the next token was read successfully; false if there are no more tokens to read. + + + + Reads the next JSON token from the source as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a []. + + A [] or null if the next JSON token is null. This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a of . + + A of . This method will return null at the end of an array. + + + + Skips the children of the current token. + + + + + Sets the current token. + + The new token. + + + + Sets the current token and value. + + The new token. + The value. + + + + Sets the current token and value. + + The new token. + The value. + A flag indicating whether the position index inside an array should be updated. + + + + Sets the state based on current token type. + + + + + Releases unmanaged and - optionally - managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + Changes the reader's state to . + If is set to true, the source is also closed. + + + + + The exception thrown when an error occurs while reading JSON text. + + + + + Gets the line number indicating where the error occurred. + + The line number indicating where the error occurred. + + + + Gets the line position indicating where the error occurred. + + The line position indicating where the error occurred. + + + + Gets the path to the JSON where the error occurred. + + The path to the JSON where the error occurred. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Initializes a new instance of the class + with a specified error message, JSON path, line number, line position, and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The path to the JSON where the error occurred. + The line number indicating where the error occurred. + The line position indicating where the error occurred. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Instructs the to always serialize the member, and to require that the member has a value. + + + + + The exception thrown when an error occurs during JSON serialization or deserialization. + + + + + Gets the line number indicating where the error occurred. + + The line number indicating where the error occurred. + + + + Gets the line position indicating where the error occurred. + + The line position indicating where the error occurred. + + + + Gets the path to the JSON where the error occurred. + + The path to the JSON where the error occurred. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Initializes a new instance of the class + with a specified error message, JSON path, line number, line position, and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The path to the JSON where the error occurred. + The line number indicating where the error occurred. + The line position indicating where the error occurred. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Serializes and deserializes objects into and from the JSON format. + The enables you to control how objects are encoded into JSON. + + + + + Occurs when the errors during serialization and deserialization. + + + + + Gets or sets the used by the serializer when resolving references. + + + + + Gets or sets the used by the serializer when resolving type names. + + + + + Gets or sets the used by the serializer when resolving type names. + + + + + Gets or sets the used by the serializer when writing trace messages. + + The trace writer. + + + + Gets or sets the equality comparer used by the serializer when comparing references. + + The equality comparer. + + + + Gets or sets how type name writing and reading is handled by the serializer. + The default value is . + + + should be used with caution when your application deserializes JSON from an external source. + Incoming types should be validated with a custom + when deserializing with a value other than . + + + + + Gets or sets how a type name assembly is written and resolved by the serializer. + The default value is . + + The type name assembly format. + + + + Gets or sets how a type name assembly is written and resolved by the serializer. + The default value is . + + The type name assembly format. + + + + Gets or sets how object references are preserved by the serializer. + The default value is . + + + + + Gets or sets how reference loops (e.g. a class referencing itself) is handled. + The default value is . + + + + + Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization. + The default value is . + + + + + Gets or sets how null values are handled during serialization and deserialization. + The default value is . + + + + + Gets or sets how default values are handled during serialization and deserialization. + The default value is . + + + + + Gets or sets how objects are created during deserialization. + The default value is . + + The object creation handling. + + + + Gets or sets how constructors are used during deserialization. + The default value is . + + The constructor handling. + + + + Gets or sets how metadata properties are used during deserialization. + The default value is . + + The metadata properties handling. + + + + Gets a collection that will be used during serialization. + + Collection that will be used during serialization. + + + + Gets or sets the contract resolver used by the serializer when + serializing .NET objects to JSON and vice versa. + + + + + Gets or sets the used by the serializer when invoking serialization callback methods. + + The context. + + + + Indicates how JSON text output is formatted. + The default value is . + + + + + Gets or sets how dates are written to JSON text. + The default value is . + + + + + Gets or sets how time zones are handled during serialization and deserialization. + The default value is . + + + + + Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON. + The default value is . + + + + + Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. + The default value is . + + + + + Gets or sets how special floating point numbers, e.g. , + and , + are written as JSON text. + The default value is . + + + + + Gets or sets how strings are escaped when writing JSON text. + The default value is . + + + + + Gets or sets how and values are formatted when writing JSON text, + and the expected date format when reading JSON text. + The default value is "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK". + + + + + Gets or sets the culture used when reading JSON. + The default value is . + + + + + Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a . + A null value means there is no maximum. + The default value is 64. + + + + + Gets a value indicating whether there will be a check for additional JSON content after deserializing an object. + The default value is false. + + + true if there will be a check for additional JSON content after deserializing an object; otherwise, false. + + + + + Initializes a new instance of the class. + + + + + Creates a new instance. + The will not use default settings + from . + + + A new instance. + The will not use default settings + from . + + + + + Creates a new instance using the specified . + The will not use default settings + from . + + The settings to be applied to the . + + A new instance using the specified . + The will not use default settings + from . + + + + + Creates a new instance. + The will use default settings + from . + + + A new instance. + The will use default settings + from . + + + + + Creates a new instance using the specified . + The will use default settings + from as well as the specified . + + The settings to be applied to the . + + A new instance using the specified . + The will use default settings + from as well as the specified . + + + + + Populates the JSON values onto the target object. + + The that contains the JSON structure to read values from. + The target object to populate values onto. + + + + Populates the JSON values onto the target object. + + The that contains the JSON structure to read values from. + The target object to populate values onto. + + + + Deserializes the JSON structure contained by the specified . + + The that contains the JSON structure to deserialize. + The being deserialized. + + + + Deserializes the JSON structure contained by the specified + into an instance of the specified type. + + The containing the object. + The of object being deserialized. + The instance of being deserialized. + + + + Deserializes the JSON structure contained by the specified + into an instance of the specified type. + + The containing the object. + The type of the object to deserialize. + The instance of being deserialized. + + + + Deserializes the JSON structure contained by the specified + into an instance of the specified type. + + The containing the object. + The of object being deserialized. + The instance of being deserialized. + + + + Serializes the specified and writes the JSON structure + using the specified . + + The used to write the JSON structure. + The to serialize. + + + + Serializes the specified and writes the JSON structure + using the specified . + + The used to write the JSON structure. + The to serialize. + + The type of the value being serialized. + This parameter is used when is to write out the type name if the type of the value does not match. + Specifying the type is optional. + + + + + Serializes the specified and writes the JSON structure + using the specified . + + The used to write the JSON structure. + The to serialize. + + The type of the value being serialized. + This parameter is used when is Auto to write out the type name if the type of the value does not match. + Specifying the type is optional. + + + + + Serializes the specified and writes the JSON structure + using the specified . + + The used to write the JSON structure. + The to serialize. + + + + Specifies the settings on a object. + + + + + Gets or sets how reference loops (e.g. a class referencing itself) are handled. + The default value is . + + Reference loop handling. + + + + Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization. + The default value is . + + Missing member handling. + + + + Gets or sets how objects are created during deserialization. + The default value is . + + The object creation handling. + + + + Gets or sets how null values are handled during serialization and deserialization. + The default value is . + + Null value handling. + + + + Gets or sets how default values are handled during serialization and deserialization. + The default value is . + + The default value handling. + + + + Gets or sets a collection that will be used during serialization. + + The converters. + + + + Gets or sets how object references are preserved by the serializer. + The default value is . + + The preserve references handling. + + + + Gets or sets how type name writing and reading is handled by the serializer. + The default value is . + + + should be used with caution when your application deserializes JSON from an external source. + Incoming types should be validated with a custom + when deserializing with a value other than . + + The type name handling. + + + + Gets or sets how metadata properties are used during deserialization. + The default value is . + + The metadata properties handling. + + + + Gets or sets how a type name assembly is written and resolved by the serializer. + The default value is . + + The type name assembly format. + + + + Gets or sets how a type name assembly is written and resolved by the serializer. + The default value is . + + The type name assembly format. + + + + Gets or sets how constructors are used during deserialization. + The default value is . + + The constructor handling. + + + + Gets or sets the contract resolver used by the serializer when + serializing .NET objects to JSON and vice versa. + + The contract resolver. + + + + Gets or sets the equality comparer used by the serializer when comparing references. + + The equality comparer. + + + + Gets or sets the used by the serializer when resolving references. + + The reference resolver. + + + + Gets or sets a function that creates the used by the serializer when resolving references. + + A function that creates the used by the serializer when resolving references. + + + + Gets or sets the used by the serializer when writing trace messages. + + The trace writer. + + + + Gets or sets the used by the serializer when resolving type names. + + The binder. + + + + Gets or sets the used by the serializer when resolving type names. + + The binder. + + + + Gets or sets the error handler called during serialization and deserialization. + + The error handler called during serialization and deserialization. + + + + Gets or sets the used by the serializer when invoking serialization callback methods. + + The context. + + + + Gets or sets how and values are formatted when writing JSON text, + and the expected date format when reading JSON text. + The default value is "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK". + + + + + Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a . + A null value means there is no maximum. + The default value is 64. + + + + + Indicates how JSON text output is formatted. + The default value is . + + + + + Gets or sets how dates are written to JSON text. + The default value is . + + + + + Gets or sets how time zones are handled during serialization and deserialization. + The default value is . + + + + + Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON. + The default value is . + + + + + Gets or sets how special floating point numbers, e.g. , + and , + are written as JSON. + The default value is . + + + + + Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. + The default value is . + + + + + Gets or sets how strings are escaped when writing JSON text. + The default value is . + + + + + Gets or sets the culture used when reading JSON. + The default value is . + + + + + Gets a value indicating whether there will be a check for additional content after deserializing an object. + The default value is false. + + + true if there will be a check for additional content after deserializing an object; otherwise, false. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + using values copied from the passed in . + + + + + Represents a reader that provides fast, non-cached, forward-only access to JSON text data. + + + + + Asynchronously reads the next JSON token from the source. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns true if the next token was read successfully; false if there are no more tokens to read. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a []. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the []. This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Initializes a new instance of the class with the specified . + + The containing the JSON data to read. + + + + Gets or sets the reader's property name table. + + + + + Gets or sets the reader's character buffer pool. + + + + + Reads the next JSON token from the underlying . + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a []. + + A [] or null if the next JSON token is null. This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Changes the reader's state to . + If is set to true, the underlying is also closed. + + + + + Gets a value indicating whether the class can return line information. + + + true if and can be provided; otherwise, false. + + + + + Gets the current line number. + + + The current line number or 0 if no line information is available (for example, returns false). + + + + + Gets the current line position. + + + The current line position or 0 if no line information is available (for example, returns false). + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data. + + + + + Asynchronously flushes whatever is in the buffer to the destination and also flushes the destination. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the JSON value delimiter. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the specified end token. + + The end token to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously closes this writer. + If is set to true, the destination is also closed. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the end of the current JSON object or array. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes indent characters. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes an indent space. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes raw JSON without changing the writer's state. + + The raw JSON to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a null value. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the property name of a name/value pair of a JSON object. + + The name of the property. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the property name of a name/value pair of a JSON object. + + The name of the property. + A flag to indicate whether the text should be escaped when it is written as a JSON property name. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the beginning of a JSON array. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the beginning of a JSON object. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the start of a constructor with the given name. + + The name of the constructor. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes an undefined value. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the given white space. + + The string of white space characters. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a [] value. + + The [] value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a comment /*...*/ containing the specified text. + + Text to place inside the comment. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the end of an array. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the end of a constructor. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the end of a JSON object. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes raw JSON where a value is expected and updates the writer's state. + + The raw JSON to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Gets or sets the writer's character array pool. + + + + + Gets or sets how many s to write for each level in the hierarchy when is set to . + + + + + Gets or sets which character to use to quote attribute values. + + + + + Gets or sets which character to use for indenting when is set to . + + + + + Gets or sets a value indicating whether object names will be surrounded with quotes. + + + + + Initializes a new instance of the class using the specified . + + The to write to. + + + + Flushes whatever is in the buffer to the underlying and also flushes the underlying . + + + + + Closes this writer. + If is set to true, the underlying is also closed. + If is set to true, the JSON is auto-completed. + + + + + Writes the beginning of a JSON object. + + + + + Writes the beginning of a JSON array. + + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes the specified end token. + + The end token to write. + + + + Writes the property name of a name/value pair on a JSON object. + + The name of the property. + + + + Writes the property name of a name/value pair on a JSON object. + + The name of the property. + A flag to indicate whether the text should be escaped when it is written as a JSON property name. + + + + Writes indent characters. + + + + + Writes the JSON value delimiter. + + + + + Writes an indent space. + + + + + Writes a value. + An error will raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes raw JSON. + + The raw JSON to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a value. + + The value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a [] value. + + The [] value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes the given white space. + + The string of white space characters. + + + + Specifies the type of JSON token. + + + + + This is returned by the if a read method has not been called. + + + + + An object start token. + + + + + An array start token. + + + + + A constructor start token. + + + + + An object property name. + + + + + A comment. + + + + + Raw JSON. + + + + + An integer. + + + + + A float. + + + + + A string. + + + + + A boolean. + + + + + A null token. + + + + + An undefined token. + + + + + An object end token. + + + + + An array end token. + + + + + A constructor end token. + + + + + A Date. + + + + + Byte data. + + + + + + Represents a reader that provides validation. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Sets an event handler for receiving schema validation errors. + + + + + Gets the text value of the current JSON token. + + + + + + Gets the depth of the current token in the JSON document. + + The depth of the current token in the JSON document. + + + + Gets the path of the current JSON token. + + + + + Gets the quotation mark character used to enclose the value of a string. + + + + + + Gets the type of the current JSON token. + + + + + + Gets the .NET type for the current JSON token. + + + + + + Initializes a new instance of the class that + validates the content returned from the given . + + The to read from while validating. + + + + Gets or sets the schema. + + The schema. + + + + Gets the used to construct this . + + The specified in the constructor. + + + + Changes the reader's state to . + If is set to true, the underlying is also closed. + + + + + Reads the next JSON token from the underlying as a of . + + A of . + + + + Reads the next JSON token from the underlying as a []. + + + A [] or null if the next JSON token is null. + + + + + Reads the next JSON token from the underlying as a of . + + A of . + + + + Reads the next JSON token from the underlying as a of . + + A of . + + + + Reads the next JSON token from the underlying as a of . + + A of . + + + + Reads the next JSON token from the underlying as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . + + + + Reads the next JSON token from the underlying . + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data. + + + + + Asynchronously closes this writer. + If is set to true, the destination is also closed. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously flushes whatever is in the buffer to the destination and also flushes the destination. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the specified end token. + + The end token to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes indent characters. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the JSON value delimiter. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes an indent space. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes raw JSON without changing the writer's state. + + The raw JSON to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the end of the current JSON object or array. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the end of an array. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the end of a constructor. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the end of a JSON object. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a null value. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the property name of a name/value pair of a JSON object. + + The name of the property. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the property name of a name/value pair of a JSON object. + + The name of the property. + A flag to indicate whether the text should be escaped when it is written as a JSON property name. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the beginning of a JSON array. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a comment /*...*/ containing the specified text. + + Text to place inside the comment. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes raw JSON where a value is expected and updates the writer's state. + + The raw JSON to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the start of a constructor with the given name. + + The name of the constructor. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the beginning of a JSON object. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the current token. + + The to read the token from. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the current token. + + The to read the token from. + A flag indicating whether the current token's children should be written. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the token and its value. + + The to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the token and its value. + + The to write. + + The value to write. + A value is only required for tokens that have an associated value, e.g. the property name for . + null can be passed to the method for tokens that don't have a value, e.g. . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a [] value. + + The [] value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes an undefined value. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the given white space. + + The string of white space characters. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously ets the state of the . + + The being written. + The value being written. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Gets or sets a value indicating whether the destination should be closed when this writer is closed. + + + true to close the destination when this writer is closed; otherwise false. The default is true. + + + + + Gets or sets a value indicating whether the JSON should be auto-completed when this writer is closed. + + + true to auto-complete the JSON when this writer is closed; otherwise false. The default is true. + + + + + Gets the top. + + The top. + + + + Gets the state of the writer. + + + + + Gets the path of the writer. + + + + + Gets or sets a value indicating how JSON text output should be formatted. + + + + + Gets or sets how dates are written to JSON text. + + + + + Gets or sets how time zones are handled when writing JSON text. + + + + + Gets or sets how strings are escaped when writing JSON text. + + + + + Gets or sets how special floating point numbers, e.g. , + and , + are written to JSON text. + + + + + Gets or sets how and values are formatted when writing JSON text. + + + + + Gets or sets the culture used when writing JSON. Defaults to . + + + + + Initializes a new instance of the class. + + + + + Flushes whatever is in the buffer to the destination and also flushes the destination. + + + + + Closes this writer. + If is set to true, the destination is also closed. + If is set to true, the JSON is auto-completed. + + + + + Writes the beginning of a JSON object. + + + + + Writes the end of a JSON object. + + + + + Writes the beginning of a JSON array. + + + + + Writes the end of an array. + + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes the end constructor. + + + + + Writes the property name of a name/value pair of a JSON object. + + The name of the property. + + + + Writes the property name of a name/value pair of a JSON object. + + The name of the property. + A flag to indicate whether the text should be escaped when it is written as a JSON property name. + + + + Writes the end of the current JSON object or array. + + + + + Writes the current token and its children. + + The to read the token from. + + + + Writes the current token. + + The to read the token from. + A flag indicating whether the current token's children should be written. + + + + Writes the token and its value. + + The to write. + + The value to write. + A value is only required for tokens that have an associated value, e.g. the property name for . + null can be passed to the method for tokens that don't have a value, e.g. . + + + + + Writes the token. + + The to write. + + + + Writes the specified end token. + + The end token to write. + + + + Writes indent characters. + + + + + Writes the JSON value delimiter. + + + + + Writes an indent space. + + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes raw JSON without changing the writer's state. + + The raw JSON to write. + + + + Writes raw JSON where a value is expected and updates the writer's state. + + The raw JSON to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a [] value. + + The [] value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + An error will raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes the given white space. + + The string of white space characters. + + + + Releases unmanaged and - optionally - managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + Sets the state of the . + + The being written. + The value being written. + + + + The exception thrown when an error occurs while writing JSON text. + + + + + Gets the path to the JSON where the error occurred. + + The path to the JSON where the error occurred. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Initializes a new instance of the class + with a specified error message, JSON path and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The path to the JSON where the error occurred. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Specifies how JSON comments are handled when loading JSON. + + + + + Ignore comments. + + + + + Load comments as a with type . + + + + + Specifies how duplicate property names are handled when loading JSON. + + + + + Replace the existing value when there is a duplicate property. The value of the last property in the JSON object will be used. + + + + + Ignore the new value when there is a duplicate property. The value of the first property in the JSON object will be used. + + + + + Throw a when a duplicate property is encountered. + + + + + Contains the LINQ to JSON extension methods. + + + + + Returns a collection of tokens that contains the ancestors of every token in the source collection. + + The type of the objects in source, constrained to . + An of that contains the source collection. + An of that contains the ancestors of every token in the source collection. + + + + Returns a collection of tokens that contains every token in the source collection, and the ancestors of every token in the source collection. + + The type of the objects in source, constrained to . + An of that contains the source collection. + An of that contains every token in the source collection, the ancestors of every token in the source collection. + + + + Returns a collection of tokens that contains the descendants of every token in the source collection. + + The type of the objects in source, constrained to . + An of that contains the source collection. + An of that contains the descendants of every token in the source collection. + + + + Returns a collection of tokens that contains every token in the source collection, and the descendants of every token in the source collection. + + The type of the objects in source, constrained to . + An of that contains the source collection. + An of that contains every token in the source collection, and the descendants of every token in the source collection. + + + + Returns a collection of child properties of every object in the source collection. + + An of that contains the source collection. + An of that contains the properties of every object in the source collection. + + + + Returns a collection of child values of every object in the source collection with the given key. + + An of that contains the source collection. + The token key. + An of that contains the values of every token in the source collection with the given key. + + + + Returns a collection of child values of every object in the source collection. + + An of that contains the source collection. + An of that contains the values of every token in the source collection. + + + + Returns a collection of converted child values of every object in the source collection with the given key. + + The type to convert the values to. + An of that contains the source collection. + The token key. + An that contains the converted values of every token in the source collection with the given key. + + + + Returns a collection of converted child values of every object in the source collection. + + The type to convert the values to. + An of that contains the source collection. + An that contains the converted values of every token in the source collection. + + + + Converts the value. + + The type to convert the value to. + A cast as a of . + A converted value. + + + + Converts the value. + + The source collection type. + The type to convert the value to. + A cast as a of . + A converted value. + + + + Returns a collection of child tokens of every array in the source collection. + + The source collection type. + An of that contains the source collection. + An of that contains the values of every token in the source collection. + + + + Returns a collection of converted child tokens of every array in the source collection. + + An of that contains the source collection. + The type to convert the values to. + The source collection type. + An that contains the converted values of every token in the source collection. + + + + Returns the input typed as . + + An of that contains the source collection. + The input typed as . + + + + Returns the input typed as . + + The source collection type. + An of that contains the source collection. + The input typed as . + + + + Represents a collection of objects. + + The type of token. + + + + Gets the of with the specified key. + + + + + + Represents a JSON array. + + + + + + + + Writes this token to a asynchronously. + + A into which this method will write. + The token to monitor for cancellation requests. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + A representing the asynchronous load. The property contains the JSON that was read from the specified . + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + A representing the asynchronous load. The property contains the JSON that was read from the specified . + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Gets the node type for this . + + The type. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the specified content. + + The contents of the array. + + + + Initializes a new instance of the class with the specified content. + + The contents of the array. + + + + Loads an from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Loads an from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + A that contains the JSON that was read from the specified . + + + + Load a from a string that contains JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + + + + + + Load a from a string that contains JSON. + + A that contains JSON. + The used to load the JSON. + If this is null, default load settings will be used. + A populated from the string that contains JSON. + + + + + + + Creates a from an object. + + The object that will be used to create . + A with the values of the specified object. + + + + Creates a from an object. + + The object that will be used to create . + The that will be used to read the object. + A with the values of the specified object. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Gets the with the specified key. + + The with the specified key. + + + + Gets or sets the at the specified index. + + + + + + Determines the index of a specific item in the . + + The object to locate in the . + + The index of if found in the list; otherwise, -1. + + + + + Inserts an item to the at the specified index. + + The zero-based index at which should be inserted. + The object to insert into the . + + is not a valid index in the . + + + + + Removes the item at the specified index. + + The zero-based index of the item to remove. + + is not a valid index in the . + + + + + Returns an enumerator that iterates through the collection. + + + A of that can be used to iterate through the collection. + + + + + Adds an item to the . + + The object to add to the . + + + + Removes all items from the . + + + + + Determines whether the contains a specific value. + + The object to locate in the . + + true if is found in the ; otherwise, false. + + + + + Copies the elements of the to an array, starting at a particular array index. + + The array. + Index of the array. + + + + Gets a value indicating whether the is read-only. + + true if the is read-only; otherwise, false. + + + + Removes the first occurrence of a specific object from the . + + The object to remove from the . + + true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original . + + + + + Represents a JSON constructor. + + + + + Writes this token to a asynchronously. + + A into which this method will write. + The token to monitor for cancellation requests. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous load. The + property returns a that contains the JSON that was read from the specified . + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous load. The + property returns a that contains the JSON that was read from the specified . + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Gets or sets the name of this constructor. + + The constructor name. + + + + Gets the node type for this . + + The type. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the specified name and content. + + The constructor name. + The contents of the constructor. + + + + Initializes a new instance of the class with the specified name and content. + + The constructor name. + The contents of the constructor. + + + + Initializes a new instance of the class with the specified name. + + The constructor name. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Gets the with the specified key. + + The with the specified key. + + + + Loads a from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + A that contains the JSON that was read from the specified . + + + + Represents a token that can contain other tokens. + + + + + Occurs when the list changes or an item in the list changes. + + + + + Occurs before an item is added to the collection. + + + + + Occurs when the items list of the collection has changed, or the collection is reset. + + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Raises the event. + + The instance containing the event data. + + + + Raises the event. + + The instance containing the event data. + + + + Raises the event. + + The instance containing the event data. + + + + Gets a value indicating whether this token has child tokens. + + + true if this token has child values; otherwise, false. + + + + + Get the first child token of this token. + + + A containing the first child token of the . + + + + + Get the last child token of this token. + + + A containing the last child token of the . + + + + + Returns a collection of the child tokens of this token, in document order. + + + An of containing the child tokens of this , in document order. + + + + + Returns a collection of the child values of this token, in document order. + + The type to convert the values to. + + A containing the child values of this , in document order. + + + + + Returns a collection of the descendant tokens for this token in document order. + + An of containing the descendant tokens of the . + + + + Returns a collection of the tokens that contain this token, and all descendant tokens of this token, in document order. + + An of containing this token, and all the descendant tokens of the . + + + + Adds the specified content as children of this . + + The content to be added. + + + + Adds the specified content as the first children of this . + + The content to be added. + + + + Creates a that can be used to add tokens to the . + + A that is ready to have content written to it. + + + + Replaces the child nodes of this token with the specified content. + + The content. + + + + Removes the child nodes from this token. + + + + + Merge the specified content into this . + + The content to be merged. + + + + Merge the specified content into this using . + + The content to be merged. + The used to merge the content. + + + + Gets the count of child JSON tokens. + + The count of child JSON tokens. + + + + Represents a collection of objects. + + The type of token. + + + + An empty collection of objects. + + + + + Initializes a new instance of the struct. + + The enumerable. + + + + Returns an enumerator that can be used to iterate through the collection. + + + A that can be used to iterate through the collection. + + + + + Gets the of with the specified key. + + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Represents a JSON object. + + + + + + + + Writes this token to a asynchronously. + + A into which this method will write. + The token to monitor for cancellation requests. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous load. The + property returns a that contains the JSON that was read from the specified . + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous load. The + property returns a that contains the JSON that was read from the specified . + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Occurs when a property value changes. + + + + + Occurs when a property value is changing. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the specified content. + + The contents of the object. + + + + Initializes a new instance of the class with the specified content. + + The contents of the object. + + + + Gets the node type for this . + + The type. + + + + Gets an of of this object's properties. + + An of of this object's properties. + + + + Gets a with the specified name. + + The property name. + A with the specified name or null. + + + + Gets the with the specified name. + The exact name will be searched for first and if no matching property is found then + the will be used to match a property. + + The property name. + One of the enumeration values that specifies how the strings will be compared. + A matched with the specified name or null. + + + + Gets a of of this object's property values. + + A of of this object's property values. + + + + Gets the with the specified key. + + The with the specified key. + + + + Gets or sets the with the specified property name. + + + + + + Loads a from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + is not valid JSON. + + + + + Loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + A that contains the JSON that was read from the specified . + + is not valid JSON. + + + + + Load a from a string that contains JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + is not valid JSON. + + + + + + + + Load a from a string that contains JSON. + + A that contains JSON. + The used to load the JSON. + If this is null, default load settings will be used. + A populated from the string that contains JSON. + + is not valid JSON. + + + + + + + + Creates a from an object. + + The object that will be used to create . + A with the values of the specified object. + + + + Creates a from an object. + + The object that will be used to create . + The that will be used to read the object. + A with the values of the specified object. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Gets the with the specified property name. + + Name of the property. + The with the specified property name. + + + + Gets the with the specified property name. + The exact property name will be searched for first and if no matching property is found then + the will be used to match a property. + + Name of the property. + One of the enumeration values that specifies how the strings will be compared. + The with the specified property name. + + + + Tries to get the with the specified property name. + The exact property name will be searched for first and if no matching property is found then + the will be used to match a property. + + Name of the property. + The value. + One of the enumeration values that specifies how the strings will be compared. + true if a value was successfully retrieved; otherwise, false. + + + + Adds the specified property name. + + Name of the property. + The value. + + + + Determines whether the JSON object has the specified property name. + + Name of the property. + true if the JSON object has the specified property name; otherwise, false. + + + + Removes the property with the specified name. + + Name of the property. + true if item was successfully removed; otherwise, false. + + + + Tries to get the with the specified property name. + + Name of the property. + The value. + true if a value was successfully retrieved; otherwise, false. + + + + Returns an enumerator that can be used to iterate through the collection. + + + A that can be used to iterate through the collection. + + + + + Raises the event with the provided arguments. + + Name of the property. + + + + Raises the event with the provided arguments. + + Name of the property. + + + + Returns the responsible for binding operations performed on this object. + + The expression tree representation of the runtime value. + + The to bind this object. + + + + + Represents a JSON property. + + + + + Writes this token to a asynchronously. + + A into which this method will write. + The token to monitor for cancellation requests. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The token to monitor for cancellation requests. The default value is . + A representing the asynchronous creation. The + property returns a that contains the JSON that was read from the specified . + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + A representing the asynchronous creation. The + property returns a that contains the JSON that was read from the specified . + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Gets the property name. + + The property name. + + + + Gets or sets the property value. + + The property value. + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Gets the node type for this . + + The type. + + + + Initializes a new instance of the class. + + The property name. + The property content. + + + + Initializes a new instance of the class. + + The property name. + The property content. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Loads a from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + A that contains the JSON that was read from the specified . + + + + Represents a view of a . + + + + + Initializes a new instance of the class. + + The name. + + + + When overridden in a derived class, returns whether resetting an object changes its value. + + + true if resetting the component changes its value; otherwise, false. + + The component to test for reset capability. + + + + When overridden in a derived class, gets the current value of the property on a component. + + + The value of a property for a given component. + + The component with the property for which to retrieve the value. + + + + When overridden in a derived class, resets the value for this property of the component to the default value. + + The component with the property value that is to be reset to the default value. + + + + When overridden in a derived class, sets the value of the component to a different value. + + The component with the property value that is to be set. + The new value. + + + + When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted. + + + true if the property should be persisted; otherwise, false. + + The component with the property to be examined for persistence. + + + + When overridden in a derived class, gets the type of the component this property is bound to. + + + A that represents the type of component this property is bound to. + When the or + + methods are invoked, the object specified might be an instance of this type. + + + + + When overridden in a derived class, gets a value indicating whether this property is read-only. + + + true if the property is read-only; otherwise, false. + + + + + When overridden in a derived class, gets the type of the property. + + + A that represents the type of the property. + + + + + Gets the hash code for the name of the member. + + + + The hash code for the name of the member. + + + + + Represents a raw JSON string. + + + + + Asynchronously creates an instance of with the content of the reader's current token. + + The reader. + The token to monitor for cancellation requests. The default value is . + A representing the asynchronous creation. The + property returns an instance of with the content of the reader's current token. + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class. + + The raw json. + + + + Creates an instance of with the content of the reader's current token. + + The reader. + An instance of with the content of the reader's current token. + + + + Specifies the settings used when cloning JSON. + + + + + Initializes a new instance of the class. + + + + + Gets or sets a flag that indicates whether to copy annotations when cloning a . + The default value is true. + + + A flag that indicates whether to copy annotations when cloning a . + + + + + Specifies the settings used when loading JSON. + + + + + Initializes a new instance of the class. + + + + + Gets or sets how JSON comments are handled when loading JSON. + The default value is . + + The JSON comment handling. + + + + Gets or sets how JSON line info is handled when loading JSON. + The default value is . + + The JSON line info handling. + + + + Gets or sets how duplicate property names in JSON objects are handled when loading JSON. + The default value is . + + The JSON duplicate property name handling. + + + + Specifies the settings used when merging JSON. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the method used when merging JSON arrays. + + The method used when merging JSON arrays. + + + + Gets or sets how null value properties are merged. + + How null value properties are merged. + + + + Gets or sets the comparison used to match property names while merging. + The exact property name will be searched for first and if no matching property is found then + the will be used to match a property. + + The comparison used to match property names while merging. + + + + Specifies the settings used when selecting JSON. + + + + + Gets or sets a timeout that will be used when executing regular expressions. + + The timeout that will be used when executing regular expressions. + + + + Gets or sets a flag that indicates whether an error should be thrown if + no tokens are found when evaluating part of the expression. + + + A flag that indicates whether an error should be thrown if + no tokens are found when evaluating part of the expression. + + + + + Represents an abstract JSON token. + + + + + Writes this token to a asynchronously. + + A into which this method will write. + The token to monitor for cancellation requests. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Writes this token to a asynchronously. + + A into which this method will write. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Asynchronously creates a from a . + + An positioned at the token to read into this . + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous creation. The + property returns a that contains + the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Asynchronously creates a from a . + + An positioned at the token to read into this . + The used to load the JSON. + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous creation. The + property returns a that contains + the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Asynchronously creates a from a . + + A positioned at the token to read into this . + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous creation. The + property returns a that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Asynchronously creates a from a . + + A positioned at the token to read into this . + The used to load the JSON. + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous creation. The + property returns a that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Gets a comparer that can compare two tokens for value equality. + + A that can compare two nodes for value equality. + + + + Gets or sets the parent. + + The parent. + + + + Gets the root of this . + + The root of this . + + + + Gets the node type for this . + + The type. + + + + Gets a value indicating whether this token has child tokens. + + + true if this token has child values; otherwise, false. + + + + + Compares the values of two tokens, including the values of all descendant tokens. + + The first to compare. + The second to compare. + true if the tokens are equal; otherwise false. + + + + Gets the next sibling token of this node. + + The that contains the next sibling token. + + + + Gets the previous sibling token of this node. + + The that contains the previous sibling token. + + + + Gets the path of the JSON token. + + + + + Adds the specified content immediately after this token. + + A content object that contains simple content or a collection of content objects to be added after this token. + + + + Adds the specified content immediately before this token. + + A content object that contains simple content or a collection of content objects to be added before this token. + + + + Returns a collection of the ancestor tokens of this token. + + A collection of the ancestor tokens of this token. + + + + Returns a collection of tokens that contain this token, and the ancestors of this token. + + A collection of tokens that contain this token, and the ancestors of this token. + + + + Returns a collection of the sibling tokens after this token, in document order. + + A collection of the sibling tokens after this tokens, in document order. + + + + Returns a collection of the sibling tokens before this token, in document order. + + A collection of the sibling tokens before this token, in document order. + + + + Gets the with the specified key. + + The with the specified key. + + + + Gets the with the specified key converted to the specified type. + + The type to convert the token to. + The token key. + The converted token value. + + + + Get the first child token of this token. + + A containing the first child token of the . + + + + Get the last child token of this token. + + A containing the last child token of the . + + + + Returns a collection of the child tokens of this token, in document order. + + An of containing the child tokens of this , in document order. + + + + Returns a collection of the child tokens of this token, in document order, filtered by the specified type. + + The type to filter the child tokens on. + A containing the child tokens of this , in document order. + + + + Returns a collection of the child values of this token, in document order. + + The type to convert the values to. + A containing the child values of this , in document order. + + + + Removes this token from its parent. + + + + + Replaces this token with the specified token. + + The value. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Returns the indented JSON for this token. + + + ToString() returns a non-JSON string value for tokens with a type of . + If you want the JSON for all token types then you should use . + + + The indented JSON for this token. + + + + + Returns the JSON for this token using the given formatting and converters. + + Indicates how the output should be formatted. + A collection of s which will be used when writing the token. + The JSON for this token using the given formatting and converters. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to []. + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from [] to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Creates a for this token. + + A that can be used to read this token and its descendants. + + + + Creates a from an object. + + The object that will be used to create . + A with the value of the specified object. + + + + Creates a from an object using the specified . + + The object that will be used to create . + The that will be used when reading the object. + A with the value of the specified object. + + + + Creates an instance of the specified .NET type from the . + + The object type that the token will be deserialized to. + The new object created from the JSON value. + + + + Creates an instance of the specified .NET type from the . + + The object type that the token will be deserialized to. + The new object created from the JSON value. + + + + Creates an instance of the specified .NET type from the using the specified . + + The object type that the token will be deserialized to. + The that will be used when creating the object. + The new object created from the JSON value. + + + + Creates an instance of the specified .NET type from the using the specified . + + The object type that the token will be deserialized to. + The that will be used when creating the object. + The new object created from the JSON value. + + + + Creates a from a . + + A positioned at the token to read into this . + + A that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Creates a from a . + + An positioned at the token to read into this . + The used to load the JSON. + If this is null, default load settings will be used. + + A that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Load a from a string that contains JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + + + Load a from a string that contains JSON. + + A that contains JSON. + The used to load the JSON. + If this is null, default load settings will be used. + A populated from the string that contains JSON. + + + + Creates a from a . + + A positioned at the token to read into this . + The used to load the JSON. + If this is null, default load settings will be used. + + A that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Creates a from a . + + A positioned at the token to read into this . + + A that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Selects a using a JSONPath expression. Selects the token that matches the object path. + + + A that contains a JSONPath expression. + + A , or null. + + + + Selects a using a JSONPath expression. Selects the token that matches the object path. + + + A that contains a JSONPath expression. + + A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression. + A . + + + + Selects a using a JSONPath expression. Selects the token that matches the object path. + + + A that contains a JSONPath expression. + + The used to select tokens. + A . + + + + Selects a collection of elements using a JSONPath expression. + + + A that contains a JSONPath expression. + + An of that contains the selected elements. + + + + Selects a collection of elements using a JSONPath expression. + + + A that contains a JSONPath expression. + + A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression. + An of that contains the selected elements. + + + + Selects a collection of elements using a JSONPath expression. + + + A that contains a JSONPath expression. + + The used to select tokens. + An of that contains the selected elements. + + + + Returns the responsible for binding operations performed on this object. + + The expression tree representation of the runtime value. + + The to bind this object. + + + + + Returns the responsible for binding operations performed on this object. + + The expression tree representation of the runtime value. + + The to bind this object. + + + + + Creates a new instance of the . All child tokens are recursively cloned. + + A new instance of the . + + + + Creates a new instance of the . All child tokens are recursively cloned. + + A object to configure cloning settings. + A new instance of the . + + + + Adds an object to the annotation list of this . + + The annotation to add. + + + + Get the first annotation object of the specified type from this . + + The type of the annotation to retrieve. + The first annotation object that matches the specified type, or null if no annotation is of the specified type. + + + + Gets the first annotation object of the specified type from this . + + The of the annotation to retrieve. + The first annotation object that matches the specified type, or null if no annotation is of the specified type. + + + + Gets a collection of annotations of the specified type for this . + + The type of the annotations to retrieve. + An that contains the annotations for this . + + + + Gets a collection of annotations of the specified type for this . + + The of the annotations to retrieve. + An of that contains the annotations that match the specified type for this . + + + + Removes the annotations of the specified type from this . + + The type of annotations to remove. + + + + Removes the annotations of the specified type from this . + + The of annotations to remove. + + + + Compares tokens to determine whether they are equal. + + + + + Determines whether the specified objects are equal. + + The first object of type to compare. + The second object of type to compare. + + true if the specified objects are equal; otherwise, false. + + + + + Returns a hash code for the specified object. + + The for which a hash code is to be returned. + A hash code for the specified object. + The type of is a reference type and is null. + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized JSON data. + + + + + Gets the at the reader's current position. + + + + + Initializes a new instance of the class. + + The token to read from. + + + + Initializes a new instance of the class. + + The token to read from. + The initial path of the token. It is prepended to the returned . + + + + Reads the next JSON token from the underlying . + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Gets the path of the current JSON token. + + + + + Specifies the type of token. + + + + + No token type has been set. + + + + + A JSON object. + + + + + A JSON array. + + + + + A JSON constructor. + + + + + A JSON object property. + + + + + A comment. + + + + + An integer value. + + + + + A float value. + + + + + A string value. + + + + + A boolean value. + + + + + A null value. + + + + + An undefined value. + + + + + A date value. + + + + + A raw JSON value. + + + + + A collection of bytes value. + + + + + A Guid value. + + + + + A Uri value. + + + + + A TimeSpan value. + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data. + + + + + Gets the at the writer's current position. + + + + + Gets the token being written. + + The token being written. + + + + Initializes a new instance of the class writing to the given . + + The container being written to. + + + + Initializes a new instance of the class. + + + + + Flushes whatever is in the buffer to the underlying . + + + + + Closes this writer. + If is set to true, the JSON is auto-completed. + + + Setting to true has no additional effect, since the underlying is a type that cannot be closed. + + + + + Writes the beginning of a JSON object. + + + + + Writes the beginning of a JSON array. + + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes the end. + + The token. + + + + Writes the property name of a name/value pair on a JSON object. + + The name of the property. + + + + Writes a value. + An error will be raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes raw JSON. + + The raw JSON to write. + + + + Writes a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a [] value. + + The [] value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Represents a value in JSON (string, integer, date, etc). + + + + + Writes this token to a asynchronously. + + A into which this method will write. + The token to monitor for cancellation requests. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Gets a value indicating whether this token has child tokens. + + + true if this token has child values; otherwise, false. + + + + + Creates a comment with the given value. + + The value. + A comment with the given value. + + + + Creates a string with the given value. + + The value. + A string with the given value. + + + + Creates a null value. + + A null value. + + + + Creates a undefined value. + + A undefined value. + + + + Gets the node type for this . + + The type. + + + + Gets or sets the underlying token value. + + The underlying token value. + + + + Writes this token to a . + + A into which this method will write. + A collection of s which will be used when writing the token. + + + + Indicates whether the current object is equal to another object of the same type. + + + true if the current object is equal to the parameter; otherwise, false. + + An object to compare with this object. + + + + Determines whether the specified is equal to the current . + + The to compare with the current . + + true if the specified is equal to the current ; otherwise, false. + + + + + Serves as a hash function for a particular type. + + + A hash code for the current . + + + + + Returns a that represents this instance. + + + ToString() returns a non-JSON string value for tokens with a type of . + If you want the JSON for all token types then you should use . + + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format provider. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + The format provider. + + A that represents this instance. + + + + + Returns the responsible for binding operations performed on this object. + + The expression tree representation of the runtime value. + + The to bind this object. + + + + + Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object. + + An object to compare with this instance. + + A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings: + Value + Meaning + Less than zero + This instance is less than . + Zero + This instance is equal to . + Greater than zero + This instance is greater than . + + + is not of the same type as this instance. + + + + + Specifies how line information is handled when loading JSON. + + + + + Ignore line information. + + + + + Load line information. + + + + + Specifies how JSON arrays are merged together. + + + + Concatenate arrays. + + + Union arrays, skipping items that already exist. + + + Replace all array items. + + + Merge array items together, matched by index. + + + + Specifies how null value properties are merged. + + + + + The content's null value properties will be ignored during merging. + + + + + The content's null value properties will be merged. + + + + + Specifies the member serialization options for the . + + + + + All public members are serialized by default. Members can be excluded using or . + This is the default member serialization mode. + + + + + Only members marked with or are serialized. + This member serialization mode can also be set by marking the class with . + + + + + All public and private fields are serialized. Members can be excluded using or . + This member serialization mode can also be set by marking the class with + and setting IgnoreSerializableAttribute on to false. + + + + + Specifies metadata property handling options for the . + + + + + Read metadata properties located at the start of a JSON object. + + + + + Read metadata properties located anywhere in a JSON object. Note that this setting will impact performance. + + + + + Do not try to read metadata properties. + + + + + Specifies missing member handling options for the . + + + + + Ignore a missing member and do not attempt to deserialize it. + + + + + Throw a when a missing member is encountered during deserialization. + + + + + Specifies null value handling options for the . + + + + + + + + + Include null values when serializing and deserializing objects. + + + + + Ignore null values when serializing and deserializing objects. + + + + + Specifies how object creation is handled by the . + + + + + Reuse existing objects, create new objects when needed. + + + + + Only reuse existing objects. + + + + + Always create new objects. + + + + + Specifies reference handling options for the . + Note that references cannot be preserved when a value is set via a non-default constructor such as types that implement . + + + + + + + + Do not preserve references when serializing types. + + + + + Preserve references when serializing into a JSON object structure. + + + + + Preserve references when serializing into a JSON array structure. + + + + + Preserve references when serializing. + + + + + Specifies reference loop handling options for the . + + + + + Throw a when a loop is encountered. + + + + + Ignore loop references and do not serialize. + + + + + Serialize loop references. + + + + + Indicating whether a property is required. + + + + + The property is not required. The default state. + + + + + The property must be defined in JSON but can be a null value. + + + + + The property must be defined in JSON and cannot be a null value. + + + + + The property is not required but it cannot be a null value. + + + + + + Contains the JSON schema extension methods. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + + Determines whether the is valid. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + The source to test. + The schema to test with. + + true if the specified is valid; otherwise, false. + + + + + + Determines whether the is valid. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + The source to test. + The schema to test with. + When this method returns, contains any error messages generated while validating. + + true if the specified is valid; otherwise, false. + + + + + + Validates the specified . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + The source to test. + The schema to test with. + + + + + Validates the specified . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + The source to test. + The schema to test with. + The validation event handler. + + + + + An in-memory representation of a JSON Schema. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Gets or sets the id. + + + + + Gets or sets the title. + + + + + Gets or sets whether the object is required. + + + + + Gets or sets whether the object is read-only. + + + + + Gets or sets whether the object is visible to users. + + + + + Gets or sets whether the object is transient. + + + + + Gets or sets the description of the object. + + + + + Gets or sets the types of values allowed by the object. + + The type. + + + + Gets or sets the pattern. + + The pattern. + + + + Gets or sets the minimum length. + + The minimum length. + + + + Gets or sets the maximum length. + + The maximum length. + + + + Gets or sets a number that the value should be divisible by. + + A number that the value should be divisible by. + + + + Gets or sets the minimum. + + The minimum. + + + + Gets or sets the maximum. + + The maximum. + + + + Gets or sets a flag indicating whether the value can not equal the number defined by the minimum attribute (). + + A flag indicating whether the value can not equal the number defined by the minimum attribute (). + + + + Gets or sets a flag indicating whether the value can not equal the number defined by the maximum attribute (). + + A flag indicating whether the value can not equal the number defined by the maximum attribute (). + + + + Gets or sets the minimum number of items. + + The minimum number of items. + + + + Gets or sets the maximum number of items. + + The maximum number of items. + + + + Gets or sets the of items. + + The of items. + + + + Gets or sets a value indicating whether items in an array are validated using the instance at their array position from . + + + true if items are validated using their array position; otherwise, false. + + + + + Gets or sets the of additional items. + + The of additional items. + + + + Gets or sets a value indicating whether additional items are allowed. + + + true if additional items are allowed; otherwise, false. + + + + + Gets or sets whether the array items must be unique. + + + + + Gets or sets the of properties. + + The of properties. + + + + Gets or sets the of additional properties. + + The of additional properties. + + + + Gets or sets the pattern properties. + + The pattern properties. + + + + Gets or sets a value indicating whether additional properties are allowed. + + + true if additional properties are allowed; otherwise, false. + + + + + Gets or sets the required property if this property is present. + + The required property if this property is present. + + + + Gets or sets the a collection of valid enum values allowed. + + A collection of valid enum values allowed. + + + + Gets or sets disallowed types. + + The disallowed types. + + + + Gets or sets the default value. + + The default value. + + + + Gets or sets the collection of that this schema extends. + + The collection of that this schema extends. + + + + Gets or sets the format. + + The format. + + + + Initializes a new instance of the class. + + + + + Reads a from the specified . + + The containing the JSON Schema to read. + The object representing the JSON Schema. + + + + Reads a from the specified . + + The containing the JSON Schema to read. + The to use when resolving schema references. + The object representing the JSON Schema. + + + + Load a from a string that contains JSON Schema. + + A that contains JSON Schema. + A populated from the string that contains JSON Schema. + + + + Load a from a string that contains JSON Schema using the specified . + + A that contains JSON Schema. + The resolver. + A populated from the string that contains JSON Schema. + + + + Writes this schema to a . + + A into which this method will write. + + + + Writes this schema to a using the specified . + + A into which this method will write. + The resolver used. + + + + Returns a that represents the current . + + + A that represents the current . + + + + + + Returns detailed information about the schema exception. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Gets the line number indicating where the error occurred. + + The line number indicating where the error occurred. + + + + Gets the line position indicating where the error occurred. + + The line position indicating where the error occurred. + + + + Gets the path to the JSON where the error occurred. + + The path to the JSON where the error occurred. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + + Generates a from a specified . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Gets or sets how undefined schemas are handled by the serializer. + + + + + Gets or sets the contract resolver. + + The contract resolver. + + + + Generate a from the specified type. + + The type to generate a from. + A generated from the specified type. + + + + Generate a from the specified type. + + The type to generate a from. + The used to resolve schema references. + A generated from the specified type. + + + + Generate a from the specified type. + + The type to generate a from. + Specify whether the generated root will be nullable. + A generated from the specified type. + + + + Generate a from the specified type. + + The type to generate a from. + The used to resolve schema references. + Specify whether the generated root will be nullable. + A generated from the specified type. + + + + + Resolves from an id. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Gets or sets the loaded schemas. + + The loaded schemas. + + + + Initializes a new instance of the class. + + + + + Gets a for the specified reference. + + The id. + A for the specified reference. + + + + + The value types allowed by the . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + No type specified. + + + + + String type. + + + + + Float type. + + + + + Integer type. + + + + + Boolean type. + + + + + Object type. + + + + + Array type. + + + + + Null type. + + + + + Any type. + + + + + + Specifies undefined schema Id handling options for the . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Do not infer a schema Id. + + + + + Use the .NET type name as the schema Id. + + + + + Use the assembly qualified .NET type name as the schema Id. + + + + + + Returns detailed information related to the . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Gets the associated with the validation error. + + The JsonSchemaException associated with the validation error. + + + + Gets the path of the JSON location where the validation error occurred. + + The path of the JSON location where the validation error occurred. + + + + Gets the text description corresponding to the validation error. + + The text description. + + + + + Represents the callback method that will handle JSON schema validation events and the . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + A camel case naming strategy. + + + + + Initializes a new instance of the class. + + + A flag indicating whether dictionary keys should be processed. + + + A flag indicating whether explicitly specified property names should be processed, + e.g. a property name customized with a . + + + + + Initializes a new instance of the class. + + + A flag indicating whether dictionary keys should be processed. + + + A flag indicating whether explicitly specified property names should be processed, + e.g. a property name customized with a . + + + A flag indicating whether extension data names should be processed. + + + + + Initializes a new instance of the class. + + + + + Resolves the specified property name. + + The property name to resolve. + The resolved property name. + + + + Resolves member mappings for a type, camel casing property names. + + + + + Initializes a new instance of the class. + + + + + Resolves the contract for a given type. + + The type to resolve a contract for. + The contract for a given type. + + + + Used by to resolve a for a given . + + + + + Gets a value indicating whether members are being get and set using dynamic code generation. + This value is determined by the runtime permissions available. + + + true if using dynamic code generation; otherwise, false. + + + + + Gets or sets the default members search flags. + + The default members search flags. + + + + Gets or sets a value indicating whether compiler generated members should be serialized. + + + true if serialized compiler generated members; otherwise, false. + + + + + Gets or sets a value indicating whether to ignore the interface when serializing and deserializing types. + + + true if the interface will be ignored when serializing and deserializing types; otherwise, false. + + + + + Gets or sets a value indicating whether to ignore the attribute when serializing and deserializing types. + + + true if the attribute will be ignored when serializing and deserializing types; otherwise, false. + + + + + Gets or sets a value indicating whether to ignore IsSpecified members when serializing and deserializing types. + + + true if the IsSpecified members will be ignored when serializing and deserializing types; otherwise, false. + + + + + Gets or sets a value indicating whether to ignore ShouldSerialize members when serializing and deserializing types. + + + true if the ShouldSerialize members will be ignored when serializing and deserializing types; otherwise, false. + + + + + Gets or sets the naming strategy used to resolve how property names and dictionary keys are serialized. + + The naming strategy used to resolve how property names and dictionary keys are serialized. + + + + Initializes a new instance of the class. + + + + + Resolves the contract for a given type. + + The type to resolve a contract for. + The contract for a given type. + + + + Gets the serializable members for the type. + + The type to get serializable members for. + The serializable members for the type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates the constructor parameters. + + The constructor to create properties for. + The type's member properties. + Properties for the given . + + + + Creates a for the given . + + The matching member property. + The constructor parameter. + A created for the given . + + + + Resolves the default for the contract. + + Type of the object. + The contract's default . + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Determines which contract type is created for the given type. + + Type of the object. + A for the given type. + + + + Creates properties for the given . + + The type to create properties for. + /// The member serialization mode for the type. + Properties for the given . + + + + Creates the used by the serializer to get and set values from a member. + + The member. + The used by the serializer to get and set values from a member. + + + + Creates a for the given . + + The member's parent . + The member to create a for. + A created for the given . + + + + Resolves the name of the property. + + Name of the property. + Resolved name of the property. + + + + Resolves the name of the extension data. By default no changes are made to extension data names. + + Name of the extension data. + Resolved name of the extension data. + + + + Resolves the key of the dictionary. By default is used to resolve dictionary keys. + + Key of the dictionary. + Resolved key of the dictionary. + + + + Gets the resolved name of the property. + + Name of the property. + Name of the property. + + + + The default naming strategy. Property names and dictionary keys are unchanged. + + + + + Resolves the specified property name. + + The property name to resolve. + The resolved property name. + + + + The default serialization binder used when resolving and loading classes from type names. + + + + + Initializes a new instance of the class. + + + + + When overridden in a derived class, controls the binding of a serialized object to a type. + + Specifies the name of the serialized object. + Specifies the name of the serialized object. + + The type of the object the formatter creates a new instance of. + + + + + When overridden in a derived class, controls the binding of a serialized object to a type. + + The type of the object the formatter creates a new instance of. + Specifies the name of the serialized object. + Specifies the name of the serialized object. + + + + Represents a trace writer that writes to the application's instances. + + + + + Gets the that will be used to filter the trace messages passed to the writer. + For example a filter level of will exclude messages and include , + and messages. + + + The that will be used to filter the trace messages passed to the writer. + + + + + Writes the specified trace level, message and optional exception. + + The at which to write this trace. + The trace message. + The trace exception. This parameter is optional. + + + + Provides information surrounding an error. + + + + + Gets the error. + + The error. + + + + Gets the original object that caused the error. + + The original object that caused the error. + + + + Gets the member that caused the error. + + The member that caused the error. + + + + Gets the path of the JSON location where the error occurred. + + The path of the JSON location where the error occurred. + + + + Gets or sets a value indicating whether this is handled. + + true if handled; otherwise, false. + + + + Provides data for the Error event. + + + + + Gets the current object the error event is being raised against. + + The current object the error event is being raised against. + + + + Gets the error context. + + The error context. + + + + Initializes a new instance of the class. + + The current object. + The error context. + + + + Provides methods to get attributes. + + + + + Returns a collection of all of the attributes, or an empty collection if there are no attributes. + + When true, look up the hierarchy chain for the inherited custom attribute. + A collection of s, or an empty collection. + + + + Returns a collection of attributes, identified by type, or an empty collection if there are no attributes. + + The type of the attributes. + When true, look up the hierarchy chain for the inherited custom attribute. + A collection of s, or an empty collection. + + + + Used by to resolve a for a given . + + + + + + + + + Resolves the contract for a given type. + + The type to resolve a contract for. + The contract for a given type. + + + + Used to resolve references when serializing and deserializing JSON by the . + + + + + Resolves a reference to its object. + + The serialization context. + The reference to resolve. + The object that was resolved from the reference. + + + + Gets the reference for the specified object. + + The serialization context. + The object to get a reference for. + The reference to the object. + + + + Determines whether the specified object is referenced. + + The serialization context. + The object to test for a reference. + + true if the specified object is referenced; otherwise, false. + + + + + Adds a reference to the specified object. + + The serialization context. + The reference. + The object to reference. + + + + Allows users to control class loading and mandate what class to load. + + + + + When implemented, controls the binding of a serialized object to a type. + + Specifies the name of the serialized object. + Specifies the name of the serialized object + The type of the object the formatter creates a new instance of. + + + + When implemented, controls the binding of a serialized object to a type. + + The type of the object the formatter creates a new instance of. + Specifies the name of the serialized object. + Specifies the name of the serialized object. + + + + Represents a trace writer. + + + + + Gets the that will be used to filter the trace messages passed to the writer. + For example a filter level of will exclude messages and include , + and messages. + + The that will be used to filter the trace messages passed to the writer. + + + + Writes the specified trace level, message and optional exception. + + The at which to write this trace. + The trace message. + The trace exception. This parameter is optional. + + + + Provides methods to get and set values. + + + + + Sets the value. + + The target to set the value on. + The value to set on the target. + + + + Gets the value. + + The target to get the value from. + The value. + + + + Contract details for a used by the . + + + + + Gets the of the collection items. + + The of the collection items. + + + + Gets a value indicating whether the collection type is a multidimensional array. + + true if the collection type is a multidimensional array; otherwise, false. + + + + Gets or sets the function used to create the object. When set this function will override . + + The function used to create the object. + + + + Gets a value indicating whether the creator has a parameter with the collection values. + + true if the creator has a parameter with the collection values; otherwise, false. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Gets or sets the default collection items . + + The converter. + + + + Gets or sets a value indicating whether the collection items preserve object references. + + true if collection items preserve object references; otherwise, false. + + + + Gets or sets the collection item reference loop handling. + + The reference loop handling. + + + + Gets or sets the collection item type name handling. + + The type name handling. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Handles serialization callback events. + + The object that raised the callback event. + The streaming context. + + + + Handles serialization error callback events. + + The object that raised the callback event. + The streaming context. + The error context. + + + + Sets extension data for an object during deserialization. + + The object to set extension data on. + The extension data key. + The extension data value. + + + + Gets extension data for an object during serialization. + + The object to set extension data on. + + + + Contract details for a used by the . + + + + + Gets the underlying type for the contract. + + The underlying type for the contract. + + + + Gets or sets the type created during deserialization. + + The type created during deserialization. + + + + Gets or sets whether this type contract is serialized as a reference. + + Whether this type contract is serialized as a reference. + + + + Gets or sets the default for this contract. + + The converter. + + + + Gets the internally resolved for the contract's type. + This converter is used as a fallback converter when no other converter is resolved. + Setting will always override this converter. + + + + + Gets or sets all methods called immediately after deserialization of the object. + + The methods called immediately after deserialization of the object. + + + + Gets or sets all methods called during deserialization of the object. + + The methods called during deserialization of the object. + + + + Gets or sets all methods called after serialization of the object graph. + + The methods called after serialization of the object graph. + + + + Gets or sets all methods called before serialization of the object. + + The methods called before serialization of the object. + + + + Gets or sets all method called when an error is thrown during the serialization of the object. + + The methods called when an error is thrown during the serialization of the object. + + + + Gets or sets the default creator method used to create the object. + + The default creator method used to create the object. + + + + Gets or sets a value indicating whether the default creator is non-public. + + true if the default object creator is non-public; otherwise, false. + + + + Contract details for a used by the . + + + + + Gets or sets the dictionary key resolver. + + The dictionary key resolver. + + + + Gets the of the dictionary keys. + + The of the dictionary keys. + + + + Gets the of the dictionary values. + + The of the dictionary values. + + + + Gets or sets the function used to create the object. When set this function will override . + + The function used to create the object. + + + + Gets a value indicating whether the creator has a parameter with the dictionary values. + + true if the creator has a parameter with the dictionary values; otherwise, false. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Gets the object's properties. + + The object's properties. + + + + Gets or sets the property name resolver. + + The property name resolver. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Gets or sets the object constructor. + + The object constructor. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Gets or sets the object member serialization. + + The member object serialization. + + + + Gets or sets the missing member handling used when deserializing this object. + + The missing member handling. + + + + Gets or sets a value that indicates whether the object's properties are required. + + + A value indicating whether the object's properties are required. + + + + + Gets or sets how the object's properties with null values are handled during serialization and deserialization. + + How the object's properties with null values are handled during serialization and deserialization. + + + + Gets the object's properties. + + The object's properties. + + + + Gets a collection of instances that define the parameters used with . + + + + + Gets or sets the function used to create the object. When set this function will override . + This function is called with a collection of arguments which are defined by the collection. + + The function used to create the object. + + + + Gets or sets the extension data setter. + + + + + Gets or sets the extension data getter. + + + + + Gets or sets the extension data value type. + + + + + Gets or sets the extension data name resolver. + + The extension data name resolver. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Maps a JSON property to a .NET member or constructor parameter. + + + + + Gets or sets the name of the property. + + The name of the property. + + + + Gets or sets the type that declared this property. + + The type that declared this property. + + + + Gets or sets the order of serialization of a member. + + The numeric order of serialization. + + + + Gets or sets the name of the underlying member or parameter. + + The name of the underlying member or parameter. + + + + Gets the that will get and set the during serialization. + + The that will get and set the during serialization. + + + + Gets or sets the for this property. + + The for this property. + + + + Gets or sets the type of the property. + + The type of the property. + + + + Gets or sets the for the property. + If set this converter takes precedence over the contract converter for the property type. + + The converter. + + + + Gets or sets the member converter. + + The member converter. + + + + Gets or sets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets or sets a value indicating whether this is readable. + + true if readable; otherwise, false. + + + + Gets or sets a value indicating whether this is writable. + + true if writable; otherwise, false. + + + + Gets or sets a value indicating whether this has a member attribute. + + true if has a member attribute; otherwise, false. + + + + Gets the default value. + + The default value. + + + + Gets or sets a value indicating whether this is required. + + A value indicating whether this is required. + + + + Gets a value indicating whether has a value specified. + + + + + Gets or sets a value indicating whether this property preserves object references. + + + true if this instance is reference; otherwise, false. + + + + + Gets or sets the property null value handling. + + The null value handling. + + + + Gets or sets the property default value handling. + + The default value handling. + + + + Gets or sets the property reference loop handling. + + The reference loop handling. + + + + Gets or sets the property object creation handling. + + The object creation handling. + + + + Gets or sets or sets the type name handling. + + The type name handling. + + + + Gets or sets a predicate used to determine whether the property should be serialized. + + A predicate used to determine whether the property should be serialized. + + + + Gets or sets a predicate used to determine whether the property should be deserialized. + + A predicate used to determine whether the property should be deserialized. + + + + Gets or sets a predicate used to determine whether the property should be serialized. + + A predicate used to determine whether the property should be serialized. + + + + Gets or sets an action used to set whether the property has been deserialized. + + An action used to set whether the property has been deserialized. + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Gets or sets the converter used when serializing the property's collection items. + + The collection's items converter. + + + + Gets or sets whether this property's collection items are serialized as a reference. + + Whether this property's collection items are serialized as a reference. + + + + Gets or sets the type name handling used when serializing the property's collection items. + + The collection's items type name handling. + + + + Gets or sets the reference loop handling used when serializing the property's collection items. + + The collection's items reference loop handling. + + + + A collection of objects. + + + + + Initializes a new instance of the class. + + The type. + + + + When implemented in a derived class, extracts the key from the specified element. + + The element from which to extract the key. + The key for the specified element. + + + + Adds a object. + + The property to add to the collection. + + + + Gets the closest matching object. + First attempts to get an exact case match of and then + a case insensitive match. + + Name of the property. + A matching property if found. + + + + Gets a property by property name. + + The name of the property to get. + Type property name string comparison. + A matching property if found. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Lookup and create an instance of the type described by the argument. + + The type to create. + Optional arguments to pass to an initializing constructor of the JsonConverter. + If null, the default constructor is used. + + + + A kebab case naming strategy. + + + + + Initializes a new instance of the class. + + + A flag indicating whether dictionary keys should be processed. + + + A flag indicating whether explicitly specified property names should be processed, + e.g. a property name customized with a . + + + + + Initializes a new instance of the class. + + + A flag indicating whether dictionary keys should be processed. + + + A flag indicating whether explicitly specified property names should be processed, + e.g. a property name customized with a . + + + A flag indicating whether extension data names should be processed. + + + + + Initializes a new instance of the class. + + + + + Resolves the specified property name. + + The property name to resolve. + The resolved property name. + + + + Represents a trace writer that writes to memory. When the trace message limit is + reached then old trace messages will be removed as new messages are added. + + + + + Gets the that will be used to filter the trace messages passed to the writer. + For example a filter level of will exclude messages and include , + and messages. + + + The that will be used to filter the trace messages passed to the writer. + + + + + Initializes a new instance of the class. + + + + + Writes the specified trace level, message and optional exception. + + The at which to write this trace. + The trace message. + The trace exception. This parameter is optional. + + + + Returns an enumeration of the most recent trace messages. + + An enumeration of the most recent trace messages. + + + + Returns a of the most recent trace messages. + + + A of the most recent trace messages. + + + + + A base class for resolving how property names and dictionary keys are serialized. + + + + + A flag indicating whether dictionary keys should be processed. + Defaults to false. + + + + + A flag indicating whether extension data names should be processed. + Defaults to false. + + + + + A flag indicating whether explicitly specified property names, + e.g. a property name customized with a , should be processed. + Defaults to false. + + + + + Gets the serialized name for a given property name. + + The initial property name. + A flag indicating whether the property has had a name explicitly specified. + The serialized property name. + + + + Gets the serialized name for a given extension data name. + + The initial extension data name. + The serialized extension data name. + + + + Gets the serialized key for a given dictionary key. + + The initial dictionary key. + The serialized dictionary key. + + + + Resolves the specified property name. + + The property name to resolve. + The resolved property name. + + + + Hash code calculation + + + + + + Object equality implementation + + + + + + + Compare to another NamingStrategy + + + + + + + Represents a method that constructs an object. + + The object type to create. + + + + When applied to a method, specifies that the method is called when an error occurs serializing an object. + + + + + Provides methods to get attributes from a , , or . + + + + + Initializes a new instance of the class. + + The instance to get attributes for. This parameter should be a , , or . + + + + Returns a collection of all of the attributes, or an empty collection if there are no attributes. + + When true, look up the hierarchy chain for the inherited custom attribute. + A collection of s, or an empty collection. + + + + Returns a collection of attributes, identified by type, or an empty collection if there are no attributes. + + The type of the attributes. + When true, look up the hierarchy chain for the inherited custom attribute. + A collection of s, or an empty collection. + + + + Get and set values for a using reflection. + + + + + Initializes a new instance of the class. + + The member info. + + + + Sets the value. + + The target to set the value on. + The value to set on the target. + + + + Gets the value. + + The target to get the value from. + The value. + + + + A snake case naming strategy. + + + + + Initializes a new instance of the class. + + + A flag indicating whether dictionary keys should be processed. + + + A flag indicating whether explicitly specified property names should be processed, + e.g. a property name customized with a . + + + + + Initializes a new instance of the class. + + + A flag indicating whether dictionary keys should be processed. + + + A flag indicating whether explicitly specified property names should be processed, + e.g. a property name customized with a . + + + A flag indicating whether extension data names should be processed. + + + + + Initializes a new instance of the class. + + + + + Resolves the specified property name. + + The property name to resolve. + The resolved property name. + + + + Specifies how strings are escaped when writing JSON text. + + + + + Only control characters (e.g. newline) are escaped. + + + + + All non-ASCII and control characters (e.g. newline) are escaped. + + + + + HTML (<, >, &, ', ") and control characters (e.g. newline) are escaped. + + + + + Indicates the method that will be used during deserialization for locating and loading assemblies. + + + + + In simple mode, the assembly used during deserialization need not match exactly the assembly used during serialization. Specifically, the version numbers need not match as the LoadWithPartialName method of the class is used to load the assembly. + + + + + In full mode, the assembly used during deserialization must match exactly the assembly used during serialization. The Load method of the class is used to load the assembly. + + + + + Specifies type name handling options for the . + + + should be used with caution when your application deserializes JSON from an external source. + Incoming types should be validated with a custom + when deserializing with a value other than . + + + + + Do not include the .NET type name when serializing types. + + + + + Include the .NET type name when serializing into a JSON object structure. + + + + + Include the .NET type name when serializing into a JSON array structure. + + + + + Always include the .NET type name when serializing. + + + + + Include the .NET type name when the type of the object being serialized is not the same as its declared type. + Note that this doesn't include the root serialized object by default. To include the root object's type name in JSON + you must specify a root type object with + or . + + + + + + + + + + Don't run action but let a compiler detect the code in action as an executable block. + + + + + Ensure(() => new T()); + + + + + Ensure generic list type can be (de)deserializable on AOT environment. + + The type of elements in the list + + + + Ensure generic dictionary type can be (de)deserializable on AOT environment. + + The type of the keys in the dictionary. + The type of the values in the dictionary. + + + + Always return false but compiler doesn't know it. + + False + + + + Determines whether the collection is null or empty. + + The collection. + + true if the collection is null or empty; otherwise, false. + + + + + Adds the elements of the specified collection to the specified generic . + + The list to add to. + The collection of elements to add. + + + + Converts the value to the specified type. If the value is unable to be converted, the + value is checked whether it assignable to the specified type. + + The value to convert. + The culture to use when converting. + The type to convert or cast the value to. + + The converted type. If conversion was unsuccessful, the initial value + is returned if assignable to the target type. + + + + + Helper method for generating a MetaObject which calls a + specific method on Dynamic that returns a result + + + + + Helper method for generating a MetaObject which calls a + specific method on Dynamic, but uses one of the arguments for + the result. + + + + + Helper method for generating a MetaObject which calls a + specific method on Dynamic, but uses one of the arguments for + the result. + + + + + Returns a Restrictions object which includes our current restrictions merged + with a restriction limiting our type + + + + + Helper class for serializing immutable collections. + Note that this is used by all builds, even those that don't support immutable collections, in case the DLL is GACed + https://github.com/JamesNK/Newtonsoft.Json/issues/652 + + + + + Gets the type of the typed collection's items. + + The type. + The type of the typed collection's items. + + + + Gets the member's underlying type. + + The member. + The underlying type of the member. + + + + Determines whether the property is an indexed property. + + The property. + + true if the property is an indexed property; otherwise, false. + + + + + Gets the member's value on the object. + + The member. + The target object. + The member's value on the object. + + + + Sets the member's value on the target object. + + The member. + The target. + The value. + + + + Determines whether the specified MemberInfo can be read. + + The MemberInfo to determine whether can be read. + /// if set to true then allow the member to be gotten non-publicly. + + true if the specified MemberInfo can be read; otherwise, false. + + + + + Determines whether the specified MemberInfo can be set. + + The MemberInfo to determine whether can be set. + if set to true then allow the member to be set non-publicly. + if set to true then allow the member to be set if read-only. + + true if the specified MemberInfo can be set; otherwise, false. + + + + + Builds a string. Unlike this class lets you reuse its internal buffer. + + + + + Determines whether the string is all white space. Empty string will return false. + + The string to test whether it is all white space. + + true if the string is all white space; otherwise, false. + + + + + Specifies the state of the . + + + + + An exception has been thrown, which has left the in an invalid state. + You may call the method to put the in the Closed state. + Any other method calls result in an being thrown. + + + + + The method has been called. + + + + + An object is being written. + + + + + An array is being written. + + + + + A constructor is being written. + + + + + A property is being written. + + + + + A write method has not been called. + + + + Specifies that an output will not be null even if the corresponding type allows it. + + + Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. + + + Initializes the attribute with the specified return value condition. + + The return value condition. If the method returns this value, the associated parameter will not be null. + + + + Gets the return value condition. + + + Specifies that an output may be null even if the corresponding type disallows it. + + + Specifies that null is allowed as an input even if the corresponding type disallows it. + + + + Specifies that the method will not return if the associated Boolean parameter is passed the specified value. + + + + + Initializes a new instance of the class. + + + The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to + the associated parameter matches this value. + + + + Gets the condition parameter value. + + + diff --git a/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.xml.meta b/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.xml.meta new file mode 100644 index 0000000..b03dc8c --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Runtime/AOT/Newtonsoft.Json.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4c5640e415edbe342bbe339175268dfc +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.dll b/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.dll new file mode 100644 index 0000000..edc21fe Binary files /dev/null and b/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.dll differ diff --git a/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.dll.meta b/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.dll.meta new file mode 100644 index 0000000..a6dbe0d --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.dll.meta @@ -0,0 +1,82 @@ +fileFormatVersion: 2 +guid: 8c4bfcb5b17948478ccb955bccff9652 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.pdb.meta b/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.pdb.meta new file mode 100644 index 0000000..1856538 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.pdb.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7d34f3cc1c0185b4990cf748e55a8688 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.xml b/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.xml new file mode 100644 index 0000000..ec898e0 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.xml @@ -0,0 +1,11372 @@ + + + + Newtonsoft.Json + + + + + Represents a BSON Oid (object id). + + + + + Gets or sets the value of the Oid. + + The value of the Oid. + + + + Initializes a new instance of the class. + + The Oid value. + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized BSON data. + + + + + Gets or sets a value indicating whether binary data reading should be compatible with incorrect Json.NET 3.5 written binary. + + + true if binary data reading will be compatible with incorrect Json.NET 3.5 written binary; otherwise, false. + + + + + Gets or sets a value indicating whether the root object will be read as a JSON array. + + + true if the root object will be read as a JSON array; otherwise, false. + + + + + Gets or sets the used when reading values from BSON. + + The used when reading values from BSON. + + + + Initializes a new instance of the class. + + The containing the BSON data to read. + + + + Initializes a new instance of the class. + + The containing the BSON data to read. + + + + Initializes a new instance of the class. + + The containing the BSON data to read. + if set to true the root object will be read as a JSON array. + The used when reading values from BSON. + + + + Initializes a new instance of the class. + + The containing the BSON data to read. + if set to true the root object will be read as a JSON array. + The used when reading values from BSON. + + + + Reads the next JSON token from the underlying . + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Changes the reader's state to . + If is set to true, the underlying is also closed. + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating BSON data. + + + + + Gets or sets the used when writing values to BSON. + When set to no conversion will occur. + + The used when writing values to BSON. + + + + Initializes a new instance of the class. + + The to write to. + + + + Initializes a new instance of the class. + + The to write to. + + + + Flushes whatever is in the buffer to the underlying and also flushes the underlying stream. + + + + + Writes the end. + + The token. + + + + Writes a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes raw JSON. + + The raw JSON to write. + + + + Writes raw JSON where a value is expected and updates the writer's state. + + The raw JSON to write. + + + + Writes the beginning of a JSON array. + + + + + Writes the beginning of a JSON object. + + + + + Writes the property name of a name/value pair on a JSON object. + + The name of the property. + + + + Closes this writer. + If is set to true, the underlying is also closed. + If is set to true, the JSON is auto-completed. + + + + + Writes a value. + An error will raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a [] value. + + The [] value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a [] value that represents a BSON object id. + + The Object ID value to write. + + + + Writes a BSON regex. + + The regex pattern. + The regex options. + + + + Specifies how constructors are used when initializing objects during deserialization by the . + + + + + First attempt to use the public default constructor, then fall back to a single parameterized constructor, then to the non-public default constructor. + + + + + Json.NET will use a non-public default constructor before falling back to a parameterized constructor. + + + + + Converts a binary value to and from a base 64 string value. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a to and from JSON and BSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Creates a custom object. + + The object type to convert. + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Creates an object which will then be populated by the serializer. + + Type of the object. + The created object. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Gets a value indicating whether this can write JSON. + + + true if this can write JSON; otherwise, false. + + + + + Converts a to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Converts a to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Provides a base class for converting a to and from JSON. + + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a F# discriminated union type to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts an Entity Framework to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts an to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Gets a value indicating whether this can write JSON. + + + true if this can write JSON; otherwise, false. + + + + + Converts a to and from the ISO 8601 date format (e.g. "2008-04-12T12:53Z"). + + + + + Gets or sets the date time styles used when converting a date to and from JSON. + + The date time styles used when converting a date to and from JSON. + + + + Gets or sets the date time format used when converting a date to and from JSON. + + The date time format used when converting a date to and from JSON. + + + + Gets or sets the culture used when converting a date to and from JSON. + + The culture used when converting a date to and from JSON. + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Converts a to and from a JavaScript Date constructor (e.g. new Date(52231943)). + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing property value of the JSON that is being converted. + The calling serializer. + The object value. + + + + Converts a to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a to and from JSON and BSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts an to and from its name string value. + + + + + Gets or sets a value indicating whether the written enum text should be camel case. + The default value is false. + + true if the written enum text will be camel case; otherwise, false. + + + + Gets or sets the naming strategy used to resolve how enum text is written. + + The naming strategy used to resolve how enum text is written. + + + + Gets or sets a value indicating whether integer values are allowed when serializing and deserializing. + The default value is true. + + true if integers are allowed when serializing and deserializing; otherwise, false. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + true if the written enum text will be camel case; otherwise, false. + + + + Initializes a new instance of the class. + + The naming strategy used to resolve how enum text is written. + true if integers are allowed when serializing and deserializing; otherwise, false. + + + + Initializes a new instance of the class. + + The of the used to write enum text. + + + + Initializes a new instance of the class. + + The of the used to write enum text. + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + When non-null, there must be a constructor defined in the that exactly matches the number, + order, and type of these parameters. + + + + + Initializes a new instance of the class. + + The of the used to write enum text. + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + When non-null, there must be a constructor defined in the that exactly matches the number, + order, and type of these parameters. + + true if integers are allowed when serializing and deserializing; otherwise, false. + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a to and from Unix epoch time + + + + + Gets or sets a value indicating whether the dates before Unix epoch + should converted to and from JSON. + + + true to allow converting dates before Unix epoch to and from JSON; + false to throw an exception when a date being converted to or from JSON + occurred before Unix epoch. The default value is false. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + true to allow converting dates before Unix epoch to and from JSON; + false to throw an exception when a date being converted to or from JSON + occurred before Unix epoch. The default value is false. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing property value of the JSON that is being converted. + The calling serializer. + The object value. + + + + Converts a to and from a string (e.g. "1.2.3.4"). + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing property value of the JSON that is being converted. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts XML to and from JSON. + + + + + Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produced multiple root elements. + + The name of the deserialized root element. + + + + Gets or sets a value to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + true if the array attribute is written to the XML; otherwise, false. + + + + Gets or sets a value indicating whether to write the root JSON object. + + true if the JSON root object is omitted; otherwise, false. + + + + Gets or sets a value indicating whether to encode special characters when converting JSON to XML. + If true, special characters like ':', '@', '?', '#' and '$' in JSON property names aren't used to specify + XML namespaces, attributes or processing directives. Instead special characters are encoded and written + as part of the XML element name. + + true if special characters are encoded; otherwise, false. + + + + Writes the JSON representation of the object. + + The to write to. + The calling serializer. + The value. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Checks if the is a namespace attribute. + + Attribute name to test. + The attribute name prefix if it has one, otherwise an empty string. + true if attribute name is for a namespace attribute, otherwise false. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Specifies how dates are formatted when writing JSON text. + + + + + Dates are written in the ISO 8601 format, e.g. "2012-03-21T05:40Z". + + + + + Dates are written in the Microsoft JSON format, e.g. "\/Date(1198908717056)\/". + + + + + Specifies how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON text. + + + + + Date formatted strings are not parsed to a date type and are read as strings. + + + + + Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to . + + + + + Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to . + + + + + Specifies how to treat the time value when converting between string and . + + + + + Treat as local time. If the object represents a Coordinated Universal Time (UTC), it is converted to the local time. + + + + + Treat as a UTC. If the object represents a local time, it is converted to a UTC. + + + + + Treat as a local time if a is being converted to a string. + If a string is being converted to , convert to a local time if a time zone is specified. + + + + + Time zone information should be preserved when converting. + + + + + The default JSON name table implementation. + + + + + Initializes a new instance of the class. + + + + + Gets a string containing the same characters as the specified range of characters in the given array. + + The character array containing the name to find. + The zero-based index into the array specifying the first character of the name. + The number of characters in the name. + A string containing the same characters as the specified range of characters in the given array. + + + + Adds the specified string into name table. + + The string to add. + This method is not thread-safe. + The resolved string. + + + + Specifies default value handling options for the . + + + + + + + + + Include members where the member value is the same as the member's default value when serializing objects. + Included members are written to JSON. Has no effect when deserializing. + + + + + Ignore members where the member value is the same as the member's default value when serializing objects + so that it is not written to JSON. + This option will ignore all default values (e.g. null for objects and nullable types; 0 for integers, + decimals and floating point numbers; and false for booleans). The default value ignored can be changed by + placing the on the property. + + + + + Members with a default value but no JSON will be set to their default value when deserializing. + + + + + Ignore members where the member value is the same as the member's default value when serializing objects + and set members to their default value when deserializing. + + + + + Specifies float format handling options when writing special floating point numbers, e.g. , + and with . + + + + + Write special floating point values as strings in JSON, e.g. "NaN", "Infinity", "-Infinity". + + + + + Write special floating point values as symbols in JSON, e.g. NaN, Infinity, -Infinity. + Note that this will produce non-valid JSON. + + + + + Write special floating point values as the property's default value in JSON, e.g. 0.0 for a property, null for a of property. + + + + + Specifies how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. + + + + + Floating point numbers are parsed to . + + + + + Floating point numbers are parsed to . + + + + + Specifies formatting options for the . + + + + + No special formatting is applied. This is the default. + + + + + Causes child objects to be indented according to the and settings. + + + + + Provides an interface for using pooled arrays. + + The array type content. + + + + Rent an array from the pool. This array must be returned when it is no longer needed. + + The minimum required length of the array. The returned array may be longer. + The rented array from the pool. This array must be returned when it is no longer needed. + + + + Return an array to the pool. + + The array that is being returned. + + + + Provides an interface to enable a class to return line and position information. + + + + + Gets a value indicating whether the class can return line information. + + + true if and can be provided; otherwise, false. + + + + + Gets the current line number. + + The current line number or 0 if no line information is available (for example, when returns false). + + + + Gets the current line position. + + The current line position or 0 if no line information is available (for example, when returns false). + + + + Instructs the how to serialize the collection. + + + + + Gets or sets a value indicating whether null items are allowed in the collection. + + true if null items are allowed in the collection; otherwise, false. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with a flag indicating whether the array can contain null items. + + A flag indicating whether the array can contain null items. + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + Instructs the to use the specified constructor when deserializing that object. + + + + + Instructs the how to serialize the object. + + + + + Gets or sets the id. + + The id. + + + + Gets or sets the title. + + The title. + + + + Gets or sets the description. + + The description. + + + + Gets or sets the collection's items converter. + + The collection's items converter. + + + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + When non-null, there must be a constructor defined in the that exactly matches the number, + order, and type of these parameters. + + + + [JsonContainer(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })] + + + + + + Gets or sets the of the . + + The of the . + + + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + When non-null, there must be a constructor defined in the that exactly matches the number, + order, and type of these parameters. + + + + [JsonContainer(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })] + + + + + + Gets or sets a value that indicates whether to preserve object references. + + + true to keep object reference; otherwise, false. The default is false. + + + + + Gets or sets a value that indicates whether to preserve collection's items references. + + + true to keep collection's items object references; otherwise, false. The default is false. + + + + + Gets or sets the reference loop handling used when serializing the collection's items. + + The reference loop handling. + + + + Gets or sets the type name handling used when serializing the collection's items. + + The type name handling. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + Provides methods for converting between .NET types and JSON types. + + + + + + + + Gets or sets a function that creates default . + Default settings are automatically used by serialization methods on , + and and on . + To serialize without using any default settings create a with + . + + + + + Represents JavaScript's boolean value true as a string. This field is read-only. + + + + + Represents JavaScript's boolean value false as a string. This field is read-only. + + + + + Represents JavaScript's null as a string. This field is read-only. + + + + + Represents JavaScript's undefined as a string. This field is read-only. + + + + + Represents JavaScript's positive infinity as a string. This field is read-only. + + + + + Represents JavaScript's negative infinity as a string. This field is read-only. + + + + + Represents JavaScript's NaN as a string. This field is read-only. + + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation using the specified. + + The value to convert. + The format the date will be converted to. + The time zone handling when the date is converted to a string. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation using the specified. + + The value to convert. + The format the date will be converted to. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + The string delimiter character. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + The string delimiter character. + The string escape handling. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Serializes the specified object to a JSON string. + + The object to serialize. + A JSON string representation of the object. + + + + Serializes the specified object to a JSON string using formatting. + + The object to serialize. + Indicates how the output should be formatted. + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using a collection of . + + The object to serialize. + A collection of converters used while serializing. + A JSON string representation of the object. + + + + Serializes the specified object to a JSON string using formatting and a collection of . + + The object to serialize. + Indicates how the output should be formatted. + A collection of converters used while serializing. + A JSON string representation of the object. + + + + Serializes the specified object to a JSON string using . + + The object to serialize. + The used to serialize the object. + If this is null, default serialization settings will be used. + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using a type, formatting and . + + The object to serialize. + The used to serialize the object. + If this is null, default serialization settings will be used. + + The type of the value being serialized. + This parameter is used when is to write out the type name if the type of the value does not match. + Specifying the type is optional. + + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using formatting and . + + The object to serialize. + Indicates how the output should be formatted. + The used to serialize the object. + If this is null, default serialization settings will be used. + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using a type, formatting and . + + The object to serialize. + Indicates how the output should be formatted. + The used to serialize the object. + If this is null, default serialization settings will be used. + + The type of the value being serialized. + This parameter is used when is to write out the type name if the type of the value does not match. + Specifying the type is optional. + + + A JSON string representation of the object. + + + + + Deserializes the JSON to a .NET object. + + The JSON to deserialize. + The deserialized object from the JSON string. + + + + Deserializes the JSON to a .NET object using . + + The JSON to deserialize. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type. + + The JSON to deserialize. + The of object being deserialized. + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type. + + The type of the object to deserialize to. + The JSON to deserialize. + The deserialized object from the JSON string. + + + + Deserializes the JSON to the given anonymous type. + + + The anonymous type to deserialize to. This can't be specified + traditionally and must be inferred from the anonymous type passed + as a parameter. + + The JSON to deserialize. + The anonymous type object. + The deserialized anonymous type from the JSON string. + + + + Deserializes the JSON to the given anonymous type using . + + + The anonymous type to deserialize to. This can't be specified + traditionally and must be inferred from the anonymous type passed + as a parameter. + + The JSON to deserialize. + The anonymous type object. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + The deserialized anonymous type from the JSON string. + + + + Deserializes the JSON to the specified .NET type using a collection of . + + The type of the object to deserialize to. + The JSON to deserialize. + Converters to use while deserializing. + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type using . + + The type of the object to deserialize to. + The object to deserialize. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type using a collection of . + + The JSON to deserialize. + The type of the object to deserialize. + Converters to use while deserializing. + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type using . + + The JSON to deserialize. + The type of the object to deserialize to. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + The deserialized object from the JSON string. + + + + Populates the object with values from the JSON string. + + The JSON to populate values from. + The target object to populate values onto. + + + + Populates the object with values from the JSON string using . + + The JSON to populate values from. + The target object to populate values onto. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + + + + Serializes the to a JSON string. + + The node to serialize. + A JSON string of the . + + + + Serializes the to a JSON string using formatting. + + The node to serialize. + Indicates how the output should be formatted. + A JSON string of the . + + + + Serializes the to a JSON string using formatting and omits the root object if is true. + + The node to serialize. + Indicates how the output should be formatted. + Omits writing the root object. + A JSON string of the . + + + + Deserializes the from a JSON string. + + The JSON string. + The deserialized . + + + + Deserializes the from a JSON string nested in a root element specified by . + + The JSON string. + The name of the root element to append when deserializing. + The deserialized . + + + + Deserializes the from a JSON string nested in a root element specified by + and writes a Json.NET array attribute for collections. + + The JSON string. + The name of the root element to append when deserializing. + + A value to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + The deserialized . + + + + Deserializes the from a JSON string nested in a root element specified by , + writes a Json.NET array attribute for collections, and encodes special characters. + + The JSON string. + The name of the root element to append when deserializing. + + A value to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + + A value to indicate whether to encode special characters when converting JSON to XML. + If true, special characters like ':', '@', '?', '#' and '$' in JSON property names aren't used to specify + XML namespaces, attributes or processing directives. Instead special characters are encoded and written + as part of the XML element name. + + The deserialized . + + + + Serializes the to a JSON string. + + The node to convert to JSON. + A JSON string of the . + + + + Serializes the to a JSON string using formatting. + + The node to convert to JSON. + Indicates how the output should be formatted. + A JSON string of the . + + + + Serializes the to a JSON string using formatting and omits the root object if is true. + + The node to serialize. + Indicates how the output should be formatted. + Omits writing the root object. + A JSON string of the . + + + + Deserializes the from a JSON string. + + The JSON string. + The deserialized . + + + + Deserializes the from a JSON string nested in a root element specified by . + + The JSON string. + The name of the root element to append when deserializing. + The deserialized . + + + + Deserializes the from a JSON string nested in a root element specified by + and writes a Json.NET array attribute for collections. + + The JSON string. + The name of the root element to append when deserializing. + + A value to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + The deserialized . + + + + Deserializes the from a JSON string nested in a root element specified by , + writes a Json.NET array attribute for collections, and encodes special characters. + + The JSON string. + The name of the root element to append when deserializing. + + A value to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + + A value to indicate whether to encode special characters when converting JSON to XML. + If true, special characters like ':', '@', '?', '#' and '$' in JSON property names aren't used to specify + XML namespaces, attributes or processing directives. Instead special characters are encoded and written + as part of the XML element name. + + The deserialized . + + + + Converts an object to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Gets a value indicating whether this can read JSON. + + true if this can read JSON; otherwise, false. + + + + Gets a value indicating whether this can write JSON. + + true if this can write JSON; otherwise, false. + + + + Converts an object to and from JSON. + + The object type to convert. + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. If there is no existing value then null will be used. + The existing value has a value. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Instructs the to use the specified when serializing the member or class. + + + + + Gets the of the . + + The of the . + + + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + + + + + Initializes a new instance of the class. + + Type of the . + + + + Initializes a new instance of the class. + + Type of the . + Parameter list to use when constructing the . Can be null. + + + + Represents a collection of . + + + + + Instructs the how to serialize the collection. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + The exception thrown when an error occurs during JSON serialization or deserialization. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Instructs the to deserialize properties with no matching class member into the specified collection + and write values during serialization. + + + + + Gets or sets a value that indicates whether to write extension data when serializing the object. + + + true to write extension data when serializing the object; otherwise, false. The default is true. + + + + + Gets or sets a value that indicates whether to read extension data when deserializing the object. + + + true to read extension data when deserializing the object; otherwise, false. The default is true. + + + + + Initializes a new instance of the class. + + + + + Instructs the not to serialize the public field or public read/write property value. + + + + + Base class for a table of atomized string objects. + + + + + Gets a string containing the same characters as the specified range of characters in the given array. + + The character array containing the name to find. + The zero-based index into the array specifying the first character of the name. + The number of characters in the name. + A string containing the same characters as the specified range of characters in the given array. + + + + Instructs the how to serialize the object. + + + + + Gets or sets the member serialization. + + The member serialization. + + + + Gets or sets the missing member handling used when deserializing this object. + + The missing member handling. + + + + Gets or sets how the object's properties with null values are handled during serialization and deserialization. + + How the object's properties with null values are handled during serialization and deserialization. + + + + Gets or sets a value that indicates whether the object's properties are required. + + + A value indicating whether the object's properties are required. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified member serialization. + + The member serialization. + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + Instructs the to always serialize the member with the specified name. + + + + + Gets or sets the type used when serializing the property's collection items. + + The collection's items type. + + + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + When non-null, there must be a constructor defined in the that exactly matches the number, + order, and type of these parameters. + + + + [JsonProperty(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })] + + + + + + Gets or sets the of the . + + The of the . + + + + The parameter list to use when constructing the described by . + If null, the default constructor is used. + When non-null, there must be a constructor defined in the that exactly matches the number, + order, and type of these parameters. + + + + [JsonProperty(NamingStrategyType = typeof(MyNamingStrategy), NamingStrategyParameters = new object[] { 123, "Four" })] + + + + + + Gets or sets the null value handling used when serializing this property. + + The null value handling. + + + + Gets or sets the default value handling used when serializing this property. + + The default value handling. + + + + Gets or sets the reference loop handling used when serializing this property. + + The reference loop handling. + + + + Gets or sets the object creation handling used when deserializing this property. + + The object creation handling. + + + + Gets or sets the type name handling used when serializing this property. + + The type name handling. + + + + Gets or sets whether this property's value is serialized as a reference. + + Whether this property's value is serialized as a reference. + + + + Gets or sets the order of serialization of a member. + + The numeric order of serialization. + + + + Gets or sets a value indicating whether this property is required. + + + A value indicating whether this property is required. + + + + + Gets or sets the name of the property. + + The name of the property. + + + + Gets or sets the reference loop handling used when serializing the property's collection items. + + The collection's items reference loop handling. + + + + Gets or sets the type name handling used when serializing the property's collection items. + + The collection's items type name handling. + + + + Gets or sets whether this property's collection items are serialized as a reference. + + Whether this property's collection items are serialized as a reference. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified name. + + Name of the property. + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized JSON data. + + + + + Asynchronously reads the next JSON token from the source. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns true if the next token was read successfully; false if there are no more tokens to read. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously skips the children of the current token. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a []. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the []. This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously reads the next JSON token from the source as a . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the . This result will be null at the end of an array. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Specifies the state of the reader. + + + + + A read method has not been called. + + + + + The end of the file has been reached successfully. + + + + + Reader is at a property. + + + + + Reader is at the start of an object. + + + + + Reader is in an object. + + + + + Reader is at the start of an array. + + + + + Reader is in an array. + + + + + The method has been called. + + + + + Reader has just read a value. + + + + + Reader is at the start of a constructor. + + + + + Reader is in a constructor. + + + + + An error occurred that prevents the read operation from continuing. + + + + + The end of the file has been reached successfully. + + + + + Gets the current reader state. + + The current reader state. + + + + Gets or sets a value indicating whether the source should be closed when this reader is closed. + + + true to close the source when this reader is closed; otherwise false. The default is true. + + + + + Gets or sets a value indicating whether multiple pieces of JSON content can + be read from a continuous stream without erroring. + + + true to support reading multiple pieces of JSON content; otherwise false. + The default is false. + + + + + Gets the quotation mark character used to enclose the value of a string. + + + + + Gets or sets how time zones are handled when reading JSON. + + + + + Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON. + + + + + Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. + + + + + Gets or sets how custom date formatted strings are parsed when reading JSON. + + + + + Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a . + A null value means there is no maximum. + The default value is 64. + + + + + Gets the type of the current JSON token. + + + + + Gets the text value of the current JSON token. + + + + + Gets the .NET type for the current JSON token. + + + + + Gets the depth of the current token in the JSON document. + + The depth of the current token in the JSON document. + + + + Gets the path of the current JSON token. + + + + + Gets or sets the culture used when reading JSON. Defaults to . + + + + + Initializes a new instance of the class. + + + + + Reads the next JSON token from the source. + + true if the next token was read successfully; false if there are no more tokens to read. + + + + Reads the next JSON token from the source as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a []. + + A [] or null if the next JSON token is null. This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the source as a of . + + A of . This method will return null at the end of an array. + + + + Skips the children of the current token. + + + + + Sets the current token. + + The new token. + + + + Sets the current token and value. + + The new token. + The value. + + + + Sets the current token and value. + + The new token. + The value. + A flag indicating whether the position index inside an array should be updated. + + + + Sets the state based on current token type. + + + + + Releases unmanaged and - optionally - managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + Changes the reader's state to . + If is set to true, the source is also closed. + + + + + The exception thrown when an error occurs while reading JSON text. + + + + + Gets the line number indicating where the error occurred. + + The line number indicating where the error occurred. + + + + Gets the line position indicating where the error occurred. + + The line position indicating where the error occurred. + + + + Gets the path to the JSON where the error occurred. + + The path to the JSON where the error occurred. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Initializes a new instance of the class + with a specified error message, JSON path, line number, line position, and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The path to the JSON where the error occurred. + The line number indicating where the error occurred. + The line position indicating where the error occurred. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Instructs the to always serialize the member, and to require that the member has a value. + + + + + The exception thrown when an error occurs during JSON serialization or deserialization. + + + + + Gets the line number indicating where the error occurred. + + The line number indicating where the error occurred. + + + + Gets the line position indicating where the error occurred. + + The line position indicating where the error occurred. + + + + Gets the path to the JSON where the error occurred. + + The path to the JSON where the error occurred. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Initializes a new instance of the class + with a specified error message, JSON path, line number, line position, and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The path to the JSON where the error occurred. + The line number indicating where the error occurred. + The line position indicating where the error occurred. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Serializes and deserializes objects into and from the JSON format. + The enables you to control how objects are encoded into JSON. + + + + + Occurs when the errors during serialization and deserialization. + + + + + Gets or sets the used by the serializer when resolving references. + + + + + Gets or sets the used by the serializer when resolving type names. + + + + + Gets or sets the used by the serializer when resolving type names. + + + + + Gets or sets the used by the serializer when writing trace messages. + + The trace writer. + + + + Gets or sets the equality comparer used by the serializer when comparing references. + + The equality comparer. + + + + Gets or sets how type name writing and reading is handled by the serializer. + The default value is . + + + should be used with caution when your application deserializes JSON from an external source. + Incoming types should be validated with a custom + when deserializing with a value other than . + + + + + Gets or sets how a type name assembly is written and resolved by the serializer. + The default value is . + + The type name assembly format. + + + + Gets or sets how a type name assembly is written and resolved by the serializer. + The default value is . + + The type name assembly format. + + + + Gets or sets how object references are preserved by the serializer. + The default value is . + + + + + Gets or sets how reference loops (e.g. a class referencing itself) is handled. + The default value is . + + + + + Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization. + The default value is . + + + + + Gets or sets how null values are handled during serialization and deserialization. + The default value is . + + + + + Gets or sets how default values are handled during serialization and deserialization. + The default value is . + + + + + Gets or sets how objects are created during deserialization. + The default value is . + + The object creation handling. + + + + Gets or sets how constructors are used during deserialization. + The default value is . + + The constructor handling. + + + + Gets or sets how metadata properties are used during deserialization. + The default value is . + + The metadata properties handling. + + + + Gets a collection that will be used during serialization. + + Collection that will be used during serialization. + + + + Gets or sets the contract resolver used by the serializer when + serializing .NET objects to JSON and vice versa. + + + + + Gets or sets the used by the serializer when invoking serialization callback methods. + + The context. + + + + Indicates how JSON text output is formatted. + The default value is . + + + + + Gets or sets how dates are written to JSON text. + The default value is . + + + + + Gets or sets how time zones are handled during serialization and deserialization. + The default value is . + + + + + Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON. + The default value is . + + + + + Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. + The default value is . + + + + + Gets or sets how special floating point numbers, e.g. , + and , + are written as JSON text. + The default value is . + + + + + Gets or sets how strings are escaped when writing JSON text. + The default value is . + + + + + Gets or sets how and values are formatted when writing JSON text, + and the expected date format when reading JSON text. + The default value is "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK". + + + + + Gets or sets the culture used when reading JSON. + The default value is . + + + + + Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a . + A null value means there is no maximum. + The default value is 64. + + + + + Gets a value indicating whether there will be a check for additional JSON content after deserializing an object. + The default value is false. + + + true if there will be a check for additional JSON content after deserializing an object; otherwise, false. + + + + + Initializes a new instance of the class. + + + + + Creates a new instance. + The will not use default settings + from . + + + A new instance. + The will not use default settings + from . + + + + + Creates a new instance using the specified . + The will not use default settings + from . + + The settings to be applied to the . + + A new instance using the specified . + The will not use default settings + from . + + + + + Creates a new instance. + The will use default settings + from . + + + A new instance. + The will use default settings + from . + + + + + Creates a new instance using the specified . + The will use default settings + from as well as the specified . + + The settings to be applied to the . + + A new instance using the specified . + The will use default settings + from as well as the specified . + + + + + Populates the JSON values onto the target object. + + The that contains the JSON structure to read values from. + The target object to populate values onto. + + + + Populates the JSON values onto the target object. + + The that contains the JSON structure to read values from. + The target object to populate values onto. + + + + Deserializes the JSON structure contained by the specified . + + The that contains the JSON structure to deserialize. + The being deserialized. + + + + Deserializes the JSON structure contained by the specified + into an instance of the specified type. + + The containing the object. + The of object being deserialized. + The instance of being deserialized. + + + + Deserializes the JSON structure contained by the specified + into an instance of the specified type. + + The containing the object. + The type of the object to deserialize. + The instance of being deserialized. + + + + Deserializes the JSON structure contained by the specified + into an instance of the specified type. + + The containing the object. + The of object being deserialized. + The instance of being deserialized. + + + + Serializes the specified and writes the JSON structure + using the specified . + + The used to write the JSON structure. + The to serialize. + + + + Serializes the specified and writes the JSON structure + using the specified . + + The used to write the JSON structure. + The to serialize. + + The type of the value being serialized. + This parameter is used when is to write out the type name if the type of the value does not match. + Specifying the type is optional. + + + + + Serializes the specified and writes the JSON structure + using the specified . + + The used to write the JSON structure. + The to serialize. + + The type of the value being serialized. + This parameter is used when is Auto to write out the type name if the type of the value does not match. + Specifying the type is optional. + + + + + Serializes the specified and writes the JSON structure + using the specified . + + The used to write the JSON structure. + The to serialize. + + + + Specifies the settings on a object. + + + + + Gets or sets how reference loops (e.g. a class referencing itself) are handled. + The default value is . + + Reference loop handling. + + + + Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization. + The default value is . + + Missing member handling. + + + + Gets or sets how objects are created during deserialization. + The default value is . + + The object creation handling. + + + + Gets or sets how null values are handled during serialization and deserialization. + The default value is . + + Null value handling. + + + + Gets or sets how default values are handled during serialization and deserialization. + The default value is . + + The default value handling. + + + + Gets or sets a collection that will be used during serialization. + + The converters. + + + + Gets or sets how object references are preserved by the serializer. + The default value is . + + The preserve references handling. + + + + Gets or sets how type name writing and reading is handled by the serializer. + The default value is . + + + should be used with caution when your application deserializes JSON from an external source. + Incoming types should be validated with a custom + when deserializing with a value other than . + + The type name handling. + + + + Gets or sets how metadata properties are used during deserialization. + The default value is . + + The metadata properties handling. + + + + Gets or sets how a type name assembly is written and resolved by the serializer. + The default value is . + + The type name assembly format. + + + + Gets or sets how a type name assembly is written and resolved by the serializer. + The default value is . + + The type name assembly format. + + + + Gets or sets how constructors are used during deserialization. + The default value is . + + The constructor handling. + + + + Gets or sets the contract resolver used by the serializer when + serializing .NET objects to JSON and vice versa. + + The contract resolver. + + + + Gets or sets the equality comparer used by the serializer when comparing references. + + The equality comparer. + + + + Gets or sets the used by the serializer when resolving references. + + The reference resolver. + + + + Gets or sets a function that creates the used by the serializer when resolving references. + + A function that creates the used by the serializer when resolving references. + + + + Gets or sets the used by the serializer when writing trace messages. + + The trace writer. + + + + Gets or sets the used by the serializer when resolving type names. + + The binder. + + + + Gets or sets the used by the serializer when resolving type names. + + The binder. + + + + Gets or sets the error handler called during serialization and deserialization. + + The error handler called during serialization and deserialization. + + + + Gets or sets the used by the serializer when invoking serialization callback methods. + + The context. + + + + Gets or sets how and values are formatted when writing JSON text, + and the expected date format when reading JSON text. + The default value is "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK". + + + + + Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a . + A null value means there is no maximum. + The default value is 64. + + + + + Indicates how JSON text output is formatted. + The default value is . + + + + + Gets or sets how dates are written to JSON text. + The default value is . + + + + + Gets or sets how time zones are handled during serialization and deserialization. + The default value is . + + + + + Gets or sets how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON. + The default value is . + + + + + Gets or sets how special floating point numbers, e.g. , + and , + are written as JSON. + The default value is . + + + + + Gets or sets how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. + The default value is . + + + + + Gets or sets how strings are escaped when writing JSON text. + The default value is . + + + + + Gets or sets the culture used when reading JSON. + The default value is . + + + + + Gets a value indicating whether there will be a check for additional content after deserializing an object. + The default value is false. + + + true if there will be a check for additional content after deserializing an object; otherwise, false. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + using values copied from the passed in . + + + + + Represents a reader that provides fast, non-cached, forward-only access to JSON text data. + + + + + Asynchronously reads the next JSON token from the source. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns true if the next token was read successfully; false if there are no more tokens to read. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a []. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the []. This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a of . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the of . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously reads the next JSON token from the source as a . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous read. The + property returns the . This result will be null at the end of an array. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Initializes a new instance of the class with the specified . + + The containing the JSON data to read. + + + + Gets or sets the reader's property name table. + + + + + Gets or sets the reader's character buffer pool. + + + + + Reads the next JSON token from the underlying . + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a []. + + A [] or null if the next JSON token is null. This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Changes the reader's state to . + If is set to true, the underlying is also closed. + + + + + Gets a value indicating whether the class can return line information. + + + true if and can be provided; otherwise, false. + + + + + Gets the current line number. + + + The current line number or 0 if no line information is available (for example, returns false). + + + + + Gets the current line position. + + + The current line position or 0 if no line information is available (for example, returns false). + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data. + + + + + Asynchronously flushes whatever is in the buffer to the destination and also flushes the destination. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the JSON value delimiter. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the specified end token. + + The end token to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously closes this writer. + If is set to true, the destination is also closed. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the end of the current JSON object or array. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes indent characters. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes an indent space. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes raw JSON without changing the writer's state. + + The raw JSON to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a null value. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the property name of a name/value pair of a JSON object. + + The name of the property. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the property name of a name/value pair of a JSON object. + + The name of the property. + A flag to indicate whether the text should be escaped when it is written as a JSON property name. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the beginning of a JSON array. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the beginning of a JSON object. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the start of a constructor with the given name. + + The name of the constructor. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes an undefined value. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the given white space. + + The string of white space characters. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a [] value. + + The [] value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes a comment /*...*/ containing the specified text. + + Text to place inside the comment. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the end of an array. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the end of a constructor. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes the end of a JSON object. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Asynchronously writes raw JSON where a value is expected and updates the writer's state. + + The raw JSON to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + Derived classes must override this method to get asynchronous behaviour. Otherwise it will + execute synchronously, returning an already-completed task. + + + + Gets or sets the writer's character array pool. + + + + + Gets or sets how many s to write for each level in the hierarchy when is set to . + + + + + Gets or sets which character to use to quote attribute values. + + + + + Gets or sets which character to use for indenting when is set to . + + + + + Gets or sets a value indicating whether object names will be surrounded with quotes. + + + + + Initializes a new instance of the class using the specified . + + The to write to. + + + + Flushes whatever is in the buffer to the underlying and also flushes the underlying . + + + + + Closes this writer. + If is set to true, the underlying is also closed. + If is set to true, the JSON is auto-completed. + + + + + Writes the beginning of a JSON object. + + + + + Writes the beginning of a JSON array. + + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes the specified end token. + + The end token to write. + + + + Writes the property name of a name/value pair on a JSON object. + + The name of the property. + + + + Writes the property name of a name/value pair on a JSON object. + + The name of the property. + A flag to indicate whether the text should be escaped when it is written as a JSON property name. + + + + Writes indent characters. + + + + + Writes the JSON value delimiter. + + + + + Writes an indent space. + + + + + Writes a value. + An error will raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes raw JSON. + + The raw JSON to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a value. + + The value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a [] value. + + The [] value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes the given white space. + + The string of white space characters. + + + + Specifies the type of JSON token. + + + + + This is returned by the if a read method has not been called. + + + + + An object start token. + + + + + An array start token. + + + + + A constructor start token. + + + + + An object property name. + + + + + A comment. + + + + + Raw JSON. + + + + + An integer. + + + + + A float. + + + + + A string. + + + + + A boolean. + + + + + A null token. + + + + + An undefined token. + + + + + An object end token. + + + + + An array end token. + + + + + A constructor end token. + + + + + A Date. + + + + + Byte data. + + + + + + Represents a reader that provides validation. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Sets an event handler for receiving schema validation errors. + + + + + Gets the text value of the current JSON token. + + + + + + Gets the depth of the current token in the JSON document. + + The depth of the current token in the JSON document. + + + + Gets the path of the current JSON token. + + + + + Gets the quotation mark character used to enclose the value of a string. + + + + + + Gets the type of the current JSON token. + + + + + + Gets the .NET type for the current JSON token. + + + + + + Initializes a new instance of the class that + validates the content returned from the given . + + The to read from while validating. + + + + Gets or sets the schema. + + The schema. + + + + Gets the used to construct this . + + The specified in the constructor. + + + + Changes the reader's state to . + If is set to true, the underlying is also closed. + + + + + Reads the next JSON token from the underlying as a of . + + A of . + + + + Reads the next JSON token from the underlying as a []. + + + A [] or null if the next JSON token is null. + + + + + Reads the next JSON token from the underlying as a of . + + A of . + + + + Reads the next JSON token from the underlying as a of . + + A of . + + + + Reads the next JSON token from the underlying as a of . + + A of . + + + + Reads the next JSON token from the underlying as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . This method will return null at the end of an array. + + + + Reads the next JSON token from the underlying as a of . + + A of . + + + + Reads the next JSON token from the underlying . + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data. + + + + + Asynchronously closes this writer. + If is set to true, the destination is also closed. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously flushes whatever is in the buffer to the destination and also flushes the destination. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the specified end token. + + The end token to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes indent characters. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the JSON value delimiter. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes an indent space. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes raw JSON without changing the writer's state. + + The raw JSON to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the end of the current JSON object or array. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the end of an array. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the end of a constructor. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the end of a JSON object. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a null value. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the property name of a name/value pair of a JSON object. + + The name of the property. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the property name of a name/value pair of a JSON object. + + The name of the property. + A flag to indicate whether the text should be escaped when it is written as a JSON property name. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the beginning of a JSON array. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a comment /*...*/ containing the specified text. + + Text to place inside the comment. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes raw JSON where a value is expected and updates the writer's state. + + The raw JSON to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the start of a constructor with the given name. + + The name of the constructor. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the beginning of a JSON object. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the current token. + + The to read the token from. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the current token. + + The to read the token from. + A flag indicating whether the current token's children should be written. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the token and its value. + + The to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the token and its value. + + The to write. + + The value to write. + A value is only required for tokens that have an associated value, e.g. the property name for . + null can be passed to the method for tokens that don't have a value, e.g. . + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a [] value. + + The [] value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a value. + + The value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes a of value. + + The of value to write. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes an undefined value. + + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously writes the given white space. + + The string of white space characters. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Asynchronously ets the state of the . + + The being written. + The value being written. + The token to monitor for cancellation requests. The default value is . + A that represents the asynchronous operation. + The default behaviour is to execute synchronously, returning an already-completed task. Derived + classes can override this behaviour for true asynchronicity. + + + + Gets or sets a value indicating whether the destination should be closed when this writer is closed. + + + true to close the destination when this writer is closed; otherwise false. The default is true. + + + + + Gets or sets a value indicating whether the JSON should be auto-completed when this writer is closed. + + + true to auto-complete the JSON when this writer is closed; otherwise false. The default is true. + + + + + Gets the top. + + The top. + + + + Gets the state of the writer. + + + + + Gets the path of the writer. + + + + + Gets or sets a value indicating how JSON text output should be formatted. + + + + + Gets or sets how dates are written to JSON text. + + + + + Gets or sets how time zones are handled when writing JSON text. + + + + + Gets or sets how strings are escaped when writing JSON text. + + + + + Gets or sets how special floating point numbers, e.g. , + and , + are written to JSON text. + + + + + Gets or sets how and values are formatted when writing JSON text. + + + + + Gets or sets the culture used when writing JSON. Defaults to . + + + + + Initializes a new instance of the class. + + + + + Flushes whatever is in the buffer to the destination and also flushes the destination. + + + + + Closes this writer. + If is set to true, the destination is also closed. + If is set to true, the JSON is auto-completed. + + + + + Writes the beginning of a JSON object. + + + + + Writes the end of a JSON object. + + + + + Writes the beginning of a JSON array. + + + + + Writes the end of an array. + + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes the end constructor. + + + + + Writes the property name of a name/value pair of a JSON object. + + The name of the property. + + + + Writes the property name of a name/value pair of a JSON object. + + The name of the property. + A flag to indicate whether the text should be escaped when it is written as a JSON property name. + + + + Writes the end of the current JSON object or array. + + + + + Writes the current token and its children. + + The to read the token from. + + + + Writes the current token. + + The to read the token from. + A flag indicating whether the current token's children should be written. + + + + Writes the token and its value. + + The to write. + + The value to write. + A value is only required for tokens that have an associated value, e.g. the property name for . + null can be passed to the method for tokens that don't have a value, e.g. . + + + + + Writes the token. + + The to write. + + + + Writes the specified end token. + + The end token to write. + + + + Writes indent characters. + + + + + Writes the JSON value delimiter. + + + + + Writes an indent space. + + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes raw JSON without changing the writer's state. + + The raw JSON to write. + + + + Writes raw JSON where a value is expected and updates the writer's state. + + The raw JSON to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a of value. + + The of value to write. + + + + Writes a [] value. + + The [] value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + An error will raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes the given white space. + + The string of white space characters. + + + + Releases unmanaged and - optionally - managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + Sets the state of the . + + The being written. + The value being written. + + + + The exception thrown when an error occurs while writing JSON text. + + + + + Gets the path to the JSON where the error occurred. + + The path to the JSON where the error occurred. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Initializes a new instance of the class + with a specified error message, JSON path and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The path to the JSON where the error occurred. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Specifies how JSON comments are handled when loading JSON. + + + + + Ignore comments. + + + + + Load comments as a with type . + + + + + Specifies how duplicate property names are handled when loading JSON. + + + + + Replace the existing value when there is a duplicate property. The value of the last property in the JSON object will be used. + + + + + Ignore the new value when there is a duplicate property. The value of the first property in the JSON object will be used. + + + + + Throw a when a duplicate property is encountered. + + + + + Contains the LINQ to JSON extension methods. + + + + + Returns a collection of tokens that contains the ancestors of every token in the source collection. + + The type of the objects in source, constrained to . + An of that contains the source collection. + An of that contains the ancestors of every token in the source collection. + + + + Returns a collection of tokens that contains every token in the source collection, and the ancestors of every token in the source collection. + + The type of the objects in source, constrained to . + An of that contains the source collection. + An of that contains every token in the source collection, the ancestors of every token in the source collection. + + + + Returns a collection of tokens that contains the descendants of every token in the source collection. + + The type of the objects in source, constrained to . + An of that contains the source collection. + An of that contains the descendants of every token in the source collection. + + + + Returns a collection of tokens that contains every token in the source collection, and the descendants of every token in the source collection. + + The type of the objects in source, constrained to . + An of that contains the source collection. + An of that contains every token in the source collection, and the descendants of every token in the source collection. + + + + Returns a collection of child properties of every object in the source collection. + + An of that contains the source collection. + An of that contains the properties of every object in the source collection. + + + + Returns a collection of child values of every object in the source collection with the given key. + + An of that contains the source collection. + The token key. + An of that contains the values of every token in the source collection with the given key. + + + + Returns a collection of child values of every object in the source collection. + + An of that contains the source collection. + An of that contains the values of every token in the source collection. + + + + Returns a collection of converted child values of every object in the source collection with the given key. + + The type to convert the values to. + An of that contains the source collection. + The token key. + An that contains the converted values of every token in the source collection with the given key. + + + + Returns a collection of converted child values of every object in the source collection. + + The type to convert the values to. + An of that contains the source collection. + An that contains the converted values of every token in the source collection. + + + + Converts the value. + + The type to convert the value to. + A cast as a of . + A converted value. + + + + Converts the value. + + The source collection type. + The type to convert the value to. + A cast as a of . + A converted value. + + + + Returns a collection of child tokens of every array in the source collection. + + The source collection type. + An of that contains the source collection. + An of that contains the values of every token in the source collection. + + + + Returns a collection of converted child tokens of every array in the source collection. + + An of that contains the source collection. + The type to convert the values to. + The source collection type. + An that contains the converted values of every token in the source collection. + + + + Returns the input typed as . + + An of that contains the source collection. + The input typed as . + + + + Returns the input typed as . + + The source collection type. + An of that contains the source collection. + The input typed as . + + + + Represents a collection of objects. + + The type of token. + + + + Gets the of with the specified key. + + + + + + Represents a JSON array. + + + + + + + + Writes this token to a asynchronously. + + A into which this method will write. + The token to monitor for cancellation requests. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + A representing the asynchronous load. The property contains the JSON that was read from the specified . + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + A representing the asynchronous load. The property contains the JSON that was read from the specified . + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Gets the node type for this . + + The type. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the specified content. + + The contents of the array. + + + + Initializes a new instance of the class with the specified content. + + The contents of the array. + + + + Loads an from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Loads an from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + A that contains the JSON that was read from the specified . + + + + Load a from a string that contains JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + + + + + + Load a from a string that contains JSON. + + A that contains JSON. + The used to load the JSON. + If this is null, default load settings will be used. + A populated from the string that contains JSON. + + + + + + + Creates a from an object. + + The object that will be used to create . + A with the values of the specified object. + + + + Creates a from an object. + + The object that will be used to create . + The that will be used to read the object. + A with the values of the specified object. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Gets the with the specified key. + + The with the specified key. + + + + Gets or sets the at the specified index. + + + + + + Determines the index of a specific item in the . + + The object to locate in the . + + The index of if found in the list; otherwise, -1. + + + + + Inserts an item to the at the specified index. + + The zero-based index at which should be inserted. + The object to insert into the . + + is not a valid index in the . + + + + + Removes the item at the specified index. + + The zero-based index of the item to remove. + + is not a valid index in the . + + + + + Returns an enumerator that iterates through the collection. + + + A of that can be used to iterate through the collection. + + + + + Adds an item to the . + + The object to add to the . + + + + Removes all items from the . + + + + + Determines whether the contains a specific value. + + The object to locate in the . + + true if is found in the ; otherwise, false. + + + + + Copies the elements of the to an array, starting at a particular array index. + + The array. + Index of the array. + + + + Gets a value indicating whether the is read-only. + + true if the is read-only; otherwise, false. + + + + Removes the first occurrence of a specific object from the . + + The object to remove from the . + + true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original . + + + + + Represents a JSON constructor. + + + + + Writes this token to a asynchronously. + + A into which this method will write. + The token to monitor for cancellation requests. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous load. The + property returns a that contains the JSON that was read from the specified . + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous load. The + property returns a that contains the JSON that was read from the specified . + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Gets or sets the name of this constructor. + + The constructor name. + + + + Gets the node type for this . + + The type. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the specified name and content. + + The constructor name. + The contents of the constructor. + + + + Initializes a new instance of the class with the specified name and content. + + The constructor name. + The contents of the constructor. + + + + Initializes a new instance of the class with the specified name. + + The constructor name. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Gets the with the specified key. + + The with the specified key. + + + + Loads a from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + A that contains the JSON that was read from the specified . + + + + Represents a token that can contain other tokens. + + + + + Occurs when the list changes or an item in the list changes. + + + + + Occurs before an item is added to the collection. + + + + + Occurs when the items list of the collection has changed, or the collection is reset. + + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Raises the event. + + The instance containing the event data. + + + + Raises the event. + + The instance containing the event data. + + + + Raises the event. + + The instance containing the event data. + + + + Gets a value indicating whether this token has child tokens. + + + true if this token has child values; otherwise, false. + + + + + Get the first child token of this token. + + + A containing the first child token of the . + + + + + Get the last child token of this token. + + + A containing the last child token of the . + + + + + Returns a collection of the child tokens of this token, in document order. + + + An of containing the child tokens of this , in document order. + + + + + Returns a collection of the child values of this token, in document order. + + The type to convert the values to. + + A containing the child values of this , in document order. + + + + + Returns a collection of the descendant tokens for this token in document order. + + An of containing the descendant tokens of the . + + + + Returns a collection of the tokens that contain this token, and all descendant tokens of this token, in document order. + + An of containing this token, and all the descendant tokens of the . + + + + Adds the specified content as children of this . + + The content to be added. + + + + Adds the specified content as the first children of this . + + The content to be added. + + + + Creates a that can be used to add tokens to the . + + A that is ready to have content written to it. + + + + Replaces the child nodes of this token with the specified content. + + The content. + + + + Removes the child nodes from this token. + + + + + Merge the specified content into this . + + The content to be merged. + + + + Merge the specified content into this using . + + The content to be merged. + The used to merge the content. + + + + Gets the count of child JSON tokens. + + The count of child JSON tokens. + + + + Represents a collection of objects. + + The type of token. + + + + An empty collection of objects. + + + + + Initializes a new instance of the struct. + + The enumerable. + + + + Returns an enumerator that can be used to iterate through the collection. + + + A that can be used to iterate through the collection. + + + + + Gets the of with the specified key. + + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Represents a JSON object. + + + + + + + + Writes this token to a asynchronously. + + A into which this method will write. + The token to monitor for cancellation requests. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous load. The + property returns a that contains the JSON that was read from the specified . + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous load. The + property returns a that contains the JSON that was read from the specified . + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Occurs when a property value changes. + + + + + Occurs when a property value is changing. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the specified content. + + The contents of the object. + + + + Initializes a new instance of the class with the specified content. + + The contents of the object. + + + + Gets the node type for this . + + The type. + + + + Gets an of of this object's properties. + + An of of this object's properties. + + + + Gets a with the specified name. + + The property name. + A with the specified name or null. + + + + Gets the with the specified name. + The exact name will be searched for first and if no matching property is found then + the will be used to match a property. + + The property name. + One of the enumeration values that specifies how the strings will be compared. + A matched with the specified name or null. + + + + Gets a of of this object's property values. + + A of of this object's property values. + + + + Gets the with the specified key. + + The with the specified key. + + + + Gets or sets the with the specified property name. + + + + + + Loads a from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + is not valid JSON. + + + + + Loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + A that contains the JSON that was read from the specified . + + is not valid JSON. + + + + + Load a from a string that contains JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + is not valid JSON. + + + + + + + + Load a from a string that contains JSON. + + A that contains JSON. + The used to load the JSON. + If this is null, default load settings will be used. + A populated from the string that contains JSON. + + is not valid JSON. + + + + + + + + Creates a from an object. + + The object that will be used to create . + A with the values of the specified object. + + + + Creates a from an object. + + The object that will be used to create . + The that will be used to read the object. + A with the values of the specified object. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Gets the with the specified property name. + + Name of the property. + The with the specified property name. + + + + Gets the with the specified property name. + The exact property name will be searched for first and if no matching property is found then + the will be used to match a property. + + Name of the property. + One of the enumeration values that specifies how the strings will be compared. + The with the specified property name. + + + + Tries to get the with the specified property name. + The exact property name will be searched for first and if no matching property is found then + the will be used to match a property. + + Name of the property. + The value. + One of the enumeration values that specifies how the strings will be compared. + true if a value was successfully retrieved; otherwise, false. + + + + Adds the specified property name. + + Name of the property. + The value. + + + + Determines whether the JSON object has the specified property name. + + Name of the property. + true if the JSON object has the specified property name; otherwise, false. + + + + Removes the property with the specified name. + + Name of the property. + true if item was successfully removed; otherwise, false. + + + + Tries to get the with the specified property name. + + Name of the property. + The value. + true if a value was successfully retrieved; otherwise, false. + + + + Returns an enumerator that can be used to iterate through the collection. + + + A that can be used to iterate through the collection. + + + + + Raises the event with the provided arguments. + + Name of the property. + + + + Raises the event with the provided arguments. + + Name of the property. + + + + Returns the responsible for binding operations performed on this object. + + The expression tree representation of the runtime value. + + The to bind this object. + + + + + Represents a JSON property. + + + + + Writes this token to a asynchronously. + + A into which this method will write. + The token to monitor for cancellation requests. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The token to monitor for cancellation requests. The default value is . + A representing the asynchronous creation. The + property returns a that contains the JSON that was read from the specified . + + + + Asynchronously loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + A representing the asynchronous creation. The + property returns a that contains the JSON that was read from the specified . + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Gets the property name. + + The property name. + + + + Gets or sets the property value. + + The property value. + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Gets the node type for this . + + The type. + + + + Initializes a new instance of the class. + + The property name. + The property content. + + + + Initializes a new instance of the class. + + The property name. + The property content. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Loads a from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Loads a from a . + + A that will be read for the content of the . + The used to load the JSON. + If this is null, default load settings will be used. + A that contains the JSON that was read from the specified . + + + + Represents a view of a . + + + + + Initializes a new instance of the class. + + The name. + + + + When overridden in a derived class, returns whether resetting an object changes its value. + + + true if resetting the component changes its value; otherwise, false. + + The component to test for reset capability. + + + + When overridden in a derived class, gets the current value of the property on a component. + + + The value of a property for a given component. + + The component with the property for which to retrieve the value. + + + + When overridden in a derived class, resets the value for this property of the component to the default value. + + The component with the property value that is to be reset to the default value. + + + + When overridden in a derived class, sets the value of the component to a different value. + + The component with the property value that is to be set. + The new value. + + + + When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted. + + + true if the property should be persisted; otherwise, false. + + The component with the property to be examined for persistence. + + + + When overridden in a derived class, gets the type of the component this property is bound to. + + + A that represents the type of component this property is bound to. + When the or + + methods are invoked, the object specified might be an instance of this type. + + + + + When overridden in a derived class, gets a value indicating whether this property is read-only. + + + true if the property is read-only; otherwise, false. + + + + + When overridden in a derived class, gets the type of the property. + + + A that represents the type of the property. + + + + + Gets the hash code for the name of the member. + + + + The hash code for the name of the member. + + + + + Represents a raw JSON string. + + + + + Asynchronously creates an instance of with the content of the reader's current token. + + The reader. + The token to monitor for cancellation requests. The default value is . + A representing the asynchronous creation. The + property returns an instance of with the content of the reader's current token. + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class. + + The raw json. + + + + Creates an instance of with the content of the reader's current token. + + The reader. + An instance of with the content of the reader's current token. + + + + Specifies the settings used when cloning JSON. + + + + + Initializes a new instance of the class. + + + + + Gets or sets a flag that indicates whether to copy annotations when cloning a . + The default value is true. + + + A flag that indicates whether to copy annotations when cloning a . + + + + + Specifies the settings used when loading JSON. + + + + + Initializes a new instance of the class. + + + + + Gets or sets how JSON comments are handled when loading JSON. + The default value is . + + The JSON comment handling. + + + + Gets or sets how JSON line info is handled when loading JSON. + The default value is . + + The JSON line info handling. + + + + Gets or sets how duplicate property names in JSON objects are handled when loading JSON. + The default value is . + + The JSON duplicate property name handling. + + + + Specifies the settings used when merging JSON. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the method used when merging JSON arrays. + + The method used when merging JSON arrays. + + + + Gets or sets how null value properties are merged. + + How null value properties are merged. + + + + Gets or sets the comparison used to match property names while merging. + The exact property name will be searched for first and if no matching property is found then + the will be used to match a property. + + The comparison used to match property names while merging. + + + + Specifies the settings used when selecting JSON. + + + + + Gets or sets a timeout that will be used when executing regular expressions. + + The timeout that will be used when executing regular expressions. + + + + Gets or sets a flag that indicates whether an error should be thrown if + no tokens are found when evaluating part of the expression. + + + A flag that indicates whether an error should be thrown if + no tokens are found when evaluating part of the expression. + + + + + Represents an abstract JSON token. + + + + + Writes this token to a asynchronously. + + A into which this method will write. + The token to monitor for cancellation requests. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Writes this token to a asynchronously. + + A into which this method will write. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Asynchronously creates a from a . + + An positioned at the token to read into this . + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous creation. The + property returns a that contains + the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Asynchronously creates a from a . + + An positioned at the token to read into this . + The used to load the JSON. + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous creation. The + property returns a that contains + the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Asynchronously creates a from a . + + A positioned at the token to read into this . + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous creation. The + property returns a that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Asynchronously creates a from a . + + A positioned at the token to read into this . + The used to load the JSON. + If this is null, default load settings will be used. + The token to monitor for cancellation requests. The default value is . + + A that represents the asynchronous creation. The + property returns a that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Gets a comparer that can compare two tokens for value equality. + + A that can compare two nodes for value equality. + + + + Gets or sets the parent. + + The parent. + + + + Gets the root of this . + + The root of this . + + + + Gets the node type for this . + + The type. + + + + Gets a value indicating whether this token has child tokens. + + + true if this token has child values; otherwise, false. + + + + + Compares the values of two tokens, including the values of all descendant tokens. + + The first to compare. + The second to compare. + true if the tokens are equal; otherwise false. + + + + Gets the next sibling token of this node. + + The that contains the next sibling token. + + + + Gets the previous sibling token of this node. + + The that contains the previous sibling token. + + + + Gets the path of the JSON token. + + + + + Adds the specified content immediately after this token. + + A content object that contains simple content or a collection of content objects to be added after this token. + + + + Adds the specified content immediately before this token. + + A content object that contains simple content or a collection of content objects to be added before this token. + + + + Returns a collection of the ancestor tokens of this token. + + A collection of the ancestor tokens of this token. + + + + Returns a collection of tokens that contain this token, and the ancestors of this token. + + A collection of tokens that contain this token, and the ancestors of this token. + + + + Returns a collection of the sibling tokens after this token, in document order. + + A collection of the sibling tokens after this tokens, in document order. + + + + Returns a collection of the sibling tokens before this token, in document order. + + A collection of the sibling tokens before this token, in document order. + + + + Gets the with the specified key. + + The with the specified key. + + + + Gets the with the specified key converted to the specified type. + + The type to convert the token to. + The token key. + The converted token value. + + + + Get the first child token of this token. + + A containing the first child token of the . + + + + Get the last child token of this token. + + A containing the last child token of the . + + + + Returns a collection of the child tokens of this token, in document order. + + An of containing the child tokens of this , in document order. + + + + Returns a collection of the child tokens of this token, in document order, filtered by the specified type. + + The type to filter the child tokens on. + A containing the child tokens of this , in document order. + + + + Returns a collection of the child values of this token, in document order. + + The type to convert the values to. + A containing the child values of this , in document order. + + + + Removes this token from its parent. + + + + + Replaces this token with the specified token. + + The value. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Returns the indented JSON for this token. + + + ToString() returns a non-JSON string value for tokens with a type of . + If you want the JSON for all token types then you should use . + + + The indented JSON for this token. + + + + + Returns the JSON for this token using the given formatting and converters. + + Indicates how the output should be formatted. + A collection of s which will be used when writing the token. + The JSON for this token using the given formatting and converters. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to []. + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to of . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from [] to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from of to . + + The value to create a from. + The initialized with the specified value. + + + + Creates a for this token. + + A that can be used to read this token and its descendants. + + + + Creates a from an object. + + The object that will be used to create . + A with the value of the specified object. + + + + Creates a from an object using the specified . + + The object that will be used to create . + The that will be used when reading the object. + A with the value of the specified object. + + + + Creates an instance of the specified .NET type from the . + + The object type that the token will be deserialized to. + The new object created from the JSON value. + + + + Creates an instance of the specified .NET type from the . + + The object type that the token will be deserialized to. + The new object created from the JSON value. + + + + Creates an instance of the specified .NET type from the using the specified . + + The object type that the token will be deserialized to. + The that will be used when creating the object. + The new object created from the JSON value. + + + + Creates an instance of the specified .NET type from the using the specified . + + The object type that the token will be deserialized to. + The that will be used when creating the object. + The new object created from the JSON value. + + + + Creates a from a . + + A positioned at the token to read into this . + + A that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Creates a from a . + + An positioned at the token to read into this . + The used to load the JSON. + If this is null, default load settings will be used. + + A that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Load a from a string that contains JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + + + Load a from a string that contains JSON. + + A that contains JSON. + The used to load the JSON. + If this is null, default load settings will be used. + A populated from the string that contains JSON. + + + + Creates a from a . + + A positioned at the token to read into this . + The used to load the JSON. + If this is null, default load settings will be used. + + A that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Creates a from a . + + A positioned at the token to read into this . + + A that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Selects a using a JSONPath expression. Selects the token that matches the object path. + + + A that contains a JSONPath expression. + + A , or null. + + + + Selects a using a JSONPath expression. Selects the token that matches the object path. + + + A that contains a JSONPath expression. + + A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression. + A . + + + + Selects a using a JSONPath expression. Selects the token that matches the object path. + + + A that contains a JSONPath expression. + + The used to select tokens. + A . + + + + Selects a collection of elements using a JSONPath expression. + + + A that contains a JSONPath expression. + + An of that contains the selected elements. + + + + Selects a collection of elements using a JSONPath expression. + + + A that contains a JSONPath expression. + + A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression. + An of that contains the selected elements. + + + + Selects a collection of elements using a JSONPath expression. + + + A that contains a JSONPath expression. + + The used to select tokens. + An of that contains the selected elements. + + + + Returns the responsible for binding operations performed on this object. + + The expression tree representation of the runtime value. + + The to bind this object. + + + + + Returns the responsible for binding operations performed on this object. + + The expression tree representation of the runtime value. + + The to bind this object. + + + + + Creates a new instance of the . All child tokens are recursively cloned. + + A new instance of the . + + + + Creates a new instance of the . All child tokens are recursively cloned. + + A object to configure cloning settings. + A new instance of the . + + + + Adds an object to the annotation list of this . + + The annotation to add. + + + + Get the first annotation object of the specified type from this . + + The type of the annotation to retrieve. + The first annotation object that matches the specified type, or null if no annotation is of the specified type. + + + + Gets the first annotation object of the specified type from this . + + The of the annotation to retrieve. + The first annotation object that matches the specified type, or null if no annotation is of the specified type. + + + + Gets a collection of annotations of the specified type for this . + + The type of the annotations to retrieve. + An that contains the annotations for this . + + + + Gets a collection of annotations of the specified type for this . + + The of the annotations to retrieve. + An of that contains the annotations that match the specified type for this . + + + + Removes the annotations of the specified type from this . + + The type of annotations to remove. + + + + Removes the annotations of the specified type from this . + + The of annotations to remove. + + + + Compares tokens to determine whether they are equal. + + + + + Determines whether the specified objects are equal. + + The first object of type to compare. + The second object of type to compare. + + true if the specified objects are equal; otherwise, false. + + + + + Returns a hash code for the specified object. + + The for which a hash code is to be returned. + A hash code for the specified object. + The type of is a reference type and is null. + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized JSON data. + + + + + Gets the at the reader's current position. + + + + + Initializes a new instance of the class. + + The token to read from. + + + + Initializes a new instance of the class. + + The token to read from. + The initial path of the token. It is prepended to the returned . + + + + Reads the next JSON token from the underlying . + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Gets the path of the current JSON token. + + + + + Specifies the type of token. + + + + + No token type has been set. + + + + + A JSON object. + + + + + A JSON array. + + + + + A JSON constructor. + + + + + A JSON object property. + + + + + A comment. + + + + + An integer value. + + + + + A float value. + + + + + A string value. + + + + + A boolean value. + + + + + A null value. + + + + + An undefined value. + + + + + A date value. + + + + + A raw JSON value. + + + + + A collection of bytes value. + + + + + A Guid value. + + + + + A Uri value. + + + + + A TimeSpan value. + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data. + + + + + Gets the at the writer's current position. + + + + + Gets the token being written. + + The token being written. + + + + Initializes a new instance of the class writing to the given . + + The container being written to. + + + + Initializes a new instance of the class. + + + + + Flushes whatever is in the buffer to the underlying . + + + + + Closes this writer. + If is set to true, the JSON is auto-completed. + + + Setting to true has no additional effect, since the underlying is a type that cannot be closed. + + + + + Writes the beginning of a JSON object. + + + + + Writes the beginning of a JSON array. + + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes the end. + + The token. + + + + Writes the property name of a name/value pair on a JSON object. + + The name of the property. + + + + Writes a value. + An error will be raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes raw JSON. + + The raw JSON to write. + + + + Writes a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a [] value. + + The [] value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Represents a value in JSON (string, integer, date, etc). + + + + + Writes this token to a asynchronously. + + A into which this method will write. + The token to monitor for cancellation requests. + A collection of which will be used when writing the token. + A that represents the asynchronous write operation. + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Gets a value indicating whether this token has child tokens. + + + true if this token has child values; otherwise, false. + + + + + Creates a comment with the given value. + + The value. + A comment with the given value. + + + + Creates a string with the given value. + + The value. + A string with the given value. + + + + Creates a null value. + + A null value. + + + + Creates a undefined value. + + A undefined value. + + + + Gets the node type for this . + + The type. + + + + Gets or sets the underlying token value. + + The underlying token value. + + + + Writes this token to a . + + A into which this method will write. + A collection of s which will be used when writing the token. + + + + Indicates whether the current object is equal to another object of the same type. + + + true if the current object is equal to the parameter; otherwise, false. + + An object to compare with this object. + + + + Determines whether the specified is equal to the current . + + The to compare with the current . + + true if the specified is equal to the current ; otherwise, false. + + + + + Serves as a hash function for a particular type. + + + A hash code for the current . + + + + + Returns a that represents this instance. + + + ToString() returns a non-JSON string value for tokens with a type of . + If you want the JSON for all token types then you should use . + + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format provider. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + The format provider. + + A that represents this instance. + + + + + Returns the responsible for binding operations performed on this object. + + The expression tree representation of the runtime value. + + The to bind this object. + + + + + Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object. + + An object to compare with this instance. + + A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings: + Value + Meaning + Less than zero + This instance is less than . + Zero + This instance is equal to . + Greater than zero + This instance is greater than . + + + is not of the same type as this instance. + + + + + Specifies how line information is handled when loading JSON. + + + + + Ignore line information. + + + + + Load line information. + + + + + Specifies how JSON arrays are merged together. + + + + Concatenate arrays. + + + Union arrays, skipping items that already exist. + + + Replace all array items. + + + Merge array items together, matched by index. + + + + Specifies how null value properties are merged. + + + + + The content's null value properties will be ignored during merging. + + + + + The content's null value properties will be merged. + + + + + Specifies the member serialization options for the . + + + + + All public members are serialized by default. Members can be excluded using or . + This is the default member serialization mode. + + + + + Only members marked with or are serialized. + This member serialization mode can also be set by marking the class with . + + + + + All public and private fields are serialized. Members can be excluded using or . + This member serialization mode can also be set by marking the class with + and setting IgnoreSerializableAttribute on to false. + + + + + Specifies metadata property handling options for the . + + + + + Read metadata properties located at the start of a JSON object. + + + + + Read metadata properties located anywhere in a JSON object. Note that this setting will impact performance. + + + + + Do not try to read metadata properties. + + + + + Specifies missing member handling options for the . + + + + + Ignore a missing member and do not attempt to deserialize it. + + + + + Throw a when a missing member is encountered during deserialization. + + + + + Specifies null value handling options for the . + + + + + + + + + Include null values when serializing and deserializing objects. + + + + + Ignore null values when serializing and deserializing objects. + + + + + Specifies how object creation is handled by the . + + + + + Reuse existing objects, create new objects when needed. + + + + + Only reuse existing objects. + + + + + Always create new objects. + + + + + Specifies reference handling options for the . + Note that references cannot be preserved when a value is set via a non-default constructor such as types that implement . + + + + + + + + Do not preserve references when serializing types. + + + + + Preserve references when serializing into a JSON object structure. + + + + + Preserve references when serializing into a JSON array structure. + + + + + Preserve references when serializing. + + + + + Specifies reference loop handling options for the . + + + + + Throw a when a loop is encountered. + + + + + Ignore loop references and do not serialize. + + + + + Serialize loop references. + + + + + Indicating whether a property is required. + + + + + The property is not required. The default state. + + + + + The property must be defined in JSON but can be a null value. + + + + + The property must be defined in JSON and cannot be a null value. + + + + + The property is not required but it cannot be a null value. + + + + + + Contains the JSON schema extension methods. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + + Determines whether the is valid. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + The source to test. + The schema to test with. + + true if the specified is valid; otherwise, false. + + + + + + Determines whether the is valid. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + The source to test. + The schema to test with. + When this method returns, contains any error messages generated while validating. + + true if the specified is valid; otherwise, false. + + + + + + Validates the specified . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + The source to test. + The schema to test with. + + + + + Validates the specified . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + The source to test. + The schema to test with. + The validation event handler. + + + + + An in-memory representation of a JSON Schema. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Gets or sets the id. + + + + + Gets or sets the title. + + + + + Gets or sets whether the object is required. + + + + + Gets or sets whether the object is read-only. + + + + + Gets or sets whether the object is visible to users. + + + + + Gets or sets whether the object is transient. + + + + + Gets or sets the description of the object. + + + + + Gets or sets the types of values allowed by the object. + + The type. + + + + Gets or sets the pattern. + + The pattern. + + + + Gets or sets the minimum length. + + The minimum length. + + + + Gets or sets the maximum length. + + The maximum length. + + + + Gets or sets a number that the value should be divisible by. + + A number that the value should be divisible by. + + + + Gets or sets the minimum. + + The minimum. + + + + Gets or sets the maximum. + + The maximum. + + + + Gets or sets a flag indicating whether the value can not equal the number defined by the minimum attribute (). + + A flag indicating whether the value can not equal the number defined by the minimum attribute (). + + + + Gets or sets a flag indicating whether the value can not equal the number defined by the maximum attribute (). + + A flag indicating whether the value can not equal the number defined by the maximum attribute (). + + + + Gets or sets the minimum number of items. + + The minimum number of items. + + + + Gets or sets the maximum number of items. + + The maximum number of items. + + + + Gets or sets the of items. + + The of items. + + + + Gets or sets a value indicating whether items in an array are validated using the instance at their array position from . + + + true if items are validated using their array position; otherwise, false. + + + + + Gets or sets the of additional items. + + The of additional items. + + + + Gets or sets a value indicating whether additional items are allowed. + + + true if additional items are allowed; otherwise, false. + + + + + Gets or sets whether the array items must be unique. + + + + + Gets or sets the of properties. + + The of properties. + + + + Gets or sets the of additional properties. + + The of additional properties. + + + + Gets or sets the pattern properties. + + The pattern properties. + + + + Gets or sets a value indicating whether additional properties are allowed. + + + true if additional properties are allowed; otherwise, false. + + + + + Gets or sets the required property if this property is present. + + The required property if this property is present. + + + + Gets or sets the a collection of valid enum values allowed. + + A collection of valid enum values allowed. + + + + Gets or sets disallowed types. + + The disallowed types. + + + + Gets or sets the default value. + + The default value. + + + + Gets or sets the collection of that this schema extends. + + The collection of that this schema extends. + + + + Gets or sets the format. + + The format. + + + + Initializes a new instance of the class. + + + + + Reads a from the specified . + + The containing the JSON Schema to read. + The object representing the JSON Schema. + + + + Reads a from the specified . + + The containing the JSON Schema to read. + The to use when resolving schema references. + The object representing the JSON Schema. + + + + Load a from a string that contains JSON Schema. + + A that contains JSON Schema. + A populated from the string that contains JSON Schema. + + + + Load a from a string that contains JSON Schema using the specified . + + A that contains JSON Schema. + The resolver. + A populated from the string that contains JSON Schema. + + + + Writes this schema to a . + + A into which this method will write. + + + + Writes this schema to a using the specified . + + A into which this method will write. + The resolver used. + + + + Returns a that represents the current . + + + A that represents the current . + + + + + + Returns detailed information about the schema exception. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Gets the line number indicating where the error occurred. + + The line number indicating where the error occurred. + + + + Gets the line position indicating where the error occurred. + + The line position indicating where the error occurred. + + + + Gets the path to the JSON where the error occurred. + + The path to the JSON where the error occurred. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or null if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + + Generates a from a specified . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Gets or sets how undefined schemas are handled by the serializer. + + + + + Gets or sets the contract resolver. + + The contract resolver. + + + + Generate a from the specified type. + + The type to generate a from. + A generated from the specified type. + + + + Generate a from the specified type. + + The type to generate a from. + The used to resolve schema references. + A generated from the specified type. + + + + Generate a from the specified type. + + The type to generate a from. + Specify whether the generated root will be nullable. + A generated from the specified type. + + + + Generate a from the specified type. + + The type to generate a from. + The used to resolve schema references. + Specify whether the generated root will be nullable. + A generated from the specified type. + + + + + Resolves from an id. + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Gets or sets the loaded schemas. + + The loaded schemas. + + + + Initializes a new instance of the class. + + + + + Gets a for the specified reference. + + The id. + A for the specified reference. + + + + + The value types allowed by the . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + No type specified. + + + + + String type. + + + + + Float type. + + + + + Integer type. + + + + + Boolean type. + + + + + Object type. + + + + + Array type. + + + + + Null type. + + + + + Any type. + + + + + + Specifies undefined schema Id handling options for the . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Do not infer a schema Id. + + + + + Use the .NET type name as the schema Id. + + + + + Use the assembly qualified .NET type name as the schema Id. + + + + + + Returns detailed information related to the . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + Gets the associated with the validation error. + + The JsonSchemaException associated with the validation error. + + + + Gets the path of the JSON location where the validation error occurred. + + The path of the JSON location where the validation error occurred. + + + + Gets the text description corresponding to the validation error. + + The text description. + + + + + Represents the callback method that will handle JSON schema validation events and the . + + + JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details. + + + + + + A camel case naming strategy. + + + + + Initializes a new instance of the class. + + + A flag indicating whether dictionary keys should be processed. + + + A flag indicating whether explicitly specified property names should be processed, + e.g. a property name customized with a . + + + + + Initializes a new instance of the class. + + + A flag indicating whether dictionary keys should be processed. + + + A flag indicating whether explicitly specified property names should be processed, + e.g. a property name customized with a . + + + A flag indicating whether extension data names should be processed. + + + + + Initializes a new instance of the class. + + + + + Resolves the specified property name. + + The property name to resolve. + The resolved property name. + + + + Resolves member mappings for a type, camel casing property names. + + + + + Initializes a new instance of the class. + + + + + Resolves the contract for a given type. + + The type to resolve a contract for. + The contract for a given type. + + + + Used by to resolve a for a given . + + + + + Gets a value indicating whether members are being get and set using dynamic code generation. + This value is determined by the runtime permissions available. + + + true if using dynamic code generation; otherwise, false. + + + + + Gets or sets the default members search flags. + + The default members search flags. + + + + Gets or sets a value indicating whether compiler generated members should be serialized. + + + true if serialized compiler generated members; otherwise, false. + + + + + Gets or sets a value indicating whether to ignore the interface when serializing and deserializing types. + + + true if the interface will be ignored when serializing and deserializing types; otherwise, false. + + + + + Gets or sets a value indicating whether to ignore the attribute when serializing and deserializing types. + + + true if the attribute will be ignored when serializing and deserializing types; otherwise, false. + + + + + Gets or sets a value indicating whether to ignore IsSpecified members when serializing and deserializing types. + + + true if the IsSpecified members will be ignored when serializing and deserializing types; otherwise, false. + + + + + Gets or sets a value indicating whether to ignore ShouldSerialize members when serializing and deserializing types. + + + true if the ShouldSerialize members will be ignored when serializing and deserializing types; otherwise, false. + + + + + Gets or sets the naming strategy used to resolve how property names and dictionary keys are serialized. + + The naming strategy used to resolve how property names and dictionary keys are serialized. + + + + Initializes a new instance of the class. + + + + + Resolves the contract for a given type. + + The type to resolve a contract for. + The contract for a given type. + + + + Gets the serializable members for the type. + + The type to get serializable members for. + The serializable members for the type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates the constructor parameters. + + The constructor to create properties for. + The type's member properties. + Properties for the given . + + + + Creates a for the given . + + The matching member property. + The constructor parameter. + A created for the given . + + + + Resolves the default for the contract. + + Type of the object. + The contract's default . + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Determines which contract type is created for the given type. + + Type of the object. + A for the given type. + + + + Creates properties for the given . + + The type to create properties for. + /// The member serialization mode for the type. + Properties for the given . + + + + Creates the used by the serializer to get and set values from a member. + + The member. + The used by the serializer to get and set values from a member. + + + + Creates a for the given . + + The member's parent . + The member to create a for. + A created for the given . + + + + Resolves the name of the property. + + Name of the property. + Resolved name of the property. + + + + Resolves the name of the extension data. By default no changes are made to extension data names. + + Name of the extension data. + Resolved name of the extension data. + + + + Resolves the key of the dictionary. By default is used to resolve dictionary keys. + + Key of the dictionary. + Resolved key of the dictionary. + + + + Gets the resolved name of the property. + + Name of the property. + Name of the property. + + + + The default naming strategy. Property names and dictionary keys are unchanged. + + + + + Resolves the specified property name. + + The property name to resolve. + The resolved property name. + + + + The default serialization binder used when resolving and loading classes from type names. + + + + + Initializes a new instance of the class. + + + + + When overridden in a derived class, controls the binding of a serialized object to a type. + + Specifies the name of the serialized object. + Specifies the name of the serialized object. + + The type of the object the formatter creates a new instance of. + + + + + When overridden in a derived class, controls the binding of a serialized object to a type. + + The type of the object the formatter creates a new instance of. + Specifies the name of the serialized object. + Specifies the name of the serialized object. + + + + Represents a trace writer that writes to the application's instances. + + + + + Gets the that will be used to filter the trace messages passed to the writer. + For example a filter level of will exclude messages and include , + and messages. + + + The that will be used to filter the trace messages passed to the writer. + + + + + Writes the specified trace level, message and optional exception. + + The at which to write this trace. + The trace message. + The trace exception. This parameter is optional. + + + + Provides information surrounding an error. + + + + + Gets the error. + + The error. + + + + Gets the original object that caused the error. + + The original object that caused the error. + + + + Gets the member that caused the error. + + The member that caused the error. + + + + Gets the path of the JSON location where the error occurred. + + The path of the JSON location where the error occurred. + + + + Gets or sets a value indicating whether this is handled. + + true if handled; otherwise, false. + + + + Provides data for the Error event. + + + + + Gets the current object the error event is being raised against. + + The current object the error event is being raised against. + + + + Gets the error context. + + The error context. + + + + Initializes a new instance of the class. + + The current object. + The error context. + + + + Get and set values for a using dynamic methods. + + + + + Initializes a new instance of the class. + + The member info. + + + + Sets the value. + + The target to set the value on. + The value to set on the target. + + + + Gets the value. + + The target to get the value from. + The value. + + + + Provides methods to get attributes. + + + + + Returns a collection of all of the attributes, or an empty collection if there are no attributes. + + When true, look up the hierarchy chain for the inherited custom attribute. + A collection of s, or an empty collection. + + + + Returns a collection of attributes, identified by type, or an empty collection if there are no attributes. + + The type of the attributes. + When true, look up the hierarchy chain for the inherited custom attribute. + A collection of s, or an empty collection. + + + + Used by to resolve a for a given . + + + + + + + + + Resolves the contract for a given type. + + The type to resolve a contract for. + The contract for a given type. + + + + Used to resolve references when serializing and deserializing JSON by the . + + + + + Resolves a reference to its object. + + The serialization context. + The reference to resolve. + The object that was resolved from the reference. + + + + Gets the reference for the specified object. + + The serialization context. + The object to get a reference for. + The reference to the object. + + + + Determines whether the specified object is referenced. + + The serialization context. + The object to test for a reference. + + true if the specified object is referenced; otherwise, false. + + + + + Adds a reference to the specified object. + + The serialization context. + The reference. + The object to reference. + + + + Allows users to control class loading and mandate what class to load. + + + + + When implemented, controls the binding of a serialized object to a type. + + Specifies the name of the serialized object. + Specifies the name of the serialized object + The type of the object the formatter creates a new instance of. + + + + When implemented, controls the binding of a serialized object to a type. + + The type of the object the formatter creates a new instance of. + Specifies the name of the serialized object. + Specifies the name of the serialized object. + + + + Represents a trace writer. + + + + + Gets the that will be used to filter the trace messages passed to the writer. + For example a filter level of will exclude messages and include , + and messages. + + The that will be used to filter the trace messages passed to the writer. + + + + Writes the specified trace level, message and optional exception. + + The at which to write this trace. + The trace message. + The trace exception. This parameter is optional. + + + + Provides methods to get and set values. + + + + + Sets the value. + + The target to set the value on. + The value to set on the target. + + + + Gets the value. + + The target to get the value from. + The value. + + + + Contract details for a used by the . + + + + + Gets the of the collection items. + + The of the collection items. + + + + Gets a value indicating whether the collection type is a multidimensional array. + + true if the collection type is a multidimensional array; otherwise, false. + + + + Gets or sets the function used to create the object. When set this function will override . + + The function used to create the object. + + + + Gets a value indicating whether the creator has a parameter with the collection values. + + true if the creator has a parameter with the collection values; otherwise, false. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Gets or sets the default collection items . + + The converter. + + + + Gets or sets a value indicating whether the collection items preserve object references. + + true if collection items preserve object references; otherwise, false. + + + + Gets or sets the collection item reference loop handling. + + The reference loop handling. + + + + Gets or sets the collection item type name handling. + + The type name handling. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Handles serialization callback events. + + The object that raised the callback event. + The streaming context. + + + + Handles serialization error callback events. + + The object that raised the callback event. + The streaming context. + The error context. + + + + Sets extension data for an object during deserialization. + + The object to set extension data on. + The extension data key. + The extension data value. + + + + Gets extension data for an object during serialization. + + The object to set extension data on. + + + + Contract details for a used by the . + + + + + Gets the underlying type for the contract. + + The underlying type for the contract. + + + + Gets or sets the type created during deserialization. + + The type created during deserialization. + + + + Gets or sets whether this type contract is serialized as a reference. + + Whether this type contract is serialized as a reference. + + + + Gets or sets the default for this contract. + + The converter. + + + + Gets the internally resolved for the contract's type. + This converter is used as a fallback converter when no other converter is resolved. + Setting will always override this converter. + + + + + Gets or sets all methods called immediately after deserialization of the object. + + The methods called immediately after deserialization of the object. + + + + Gets or sets all methods called during deserialization of the object. + + The methods called during deserialization of the object. + + + + Gets or sets all methods called after serialization of the object graph. + + The methods called after serialization of the object graph. + + + + Gets or sets all methods called before serialization of the object. + + The methods called before serialization of the object. + + + + Gets or sets all method called when an error is thrown during the serialization of the object. + + The methods called when an error is thrown during the serialization of the object. + + + + Gets or sets the default creator method used to create the object. + + The default creator method used to create the object. + + + + Gets or sets a value indicating whether the default creator is non-public. + + true if the default object creator is non-public; otherwise, false. + + + + Contract details for a used by the . + + + + + Gets or sets the dictionary key resolver. + + The dictionary key resolver. + + + + Gets the of the dictionary keys. + + The of the dictionary keys. + + + + Gets the of the dictionary values. + + The of the dictionary values. + + + + Gets or sets the function used to create the object. When set this function will override . + + The function used to create the object. + + + + Gets a value indicating whether the creator has a parameter with the dictionary values. + + true if the creator has a parameter with the dictionary values; otherwise, false. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Gets the object's properties. + + The object's properties. + + + + Gets or sets the property name resolver. + + The property name resolver. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Gets or sets the object constructor. + + The object constructor. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Gets or sets the object member serialization. + + The member object serialization. + + + + Gets or sets the missing member handling used when deserializing this object. + + The missing member handling. + + + + Gets or sets a value that indicates whether the object's properties are required. + + + A value indicating whether the object's properties are required. + + + + + Gets or sets how the object's properties with null values are handled during serialization and deserialization. + + How the object's properties with null values are handled during serialization and deserialization. + + + + Gets the object's properties. + + The object's properties. + + + + Gets a collection of instances that define the parameters used with . + + + + + Gets or sets the function used to create the object. When set this function will override . + This function is called with a collection of arguments which are defined by the collection. + + The function used to create the object. + + + + Gets or sets the extension data setter. + + + + + Gets or sets the extension data getter. + + + + + Gets or sets the extension data value type. + + + + + Gets or sets the extension data name resolver. + + The extension data name resolver. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Maps a JSON property to a .NET member or constructor parameter. + + + + + Gets or sets the name of the property. + + The name of the property. + + + + Gets or sets the type that declared this property. + + The type that declared this property. + + + + Gets or sets the order of serialization of a member. + + The numeric order of serialization. + + + + Gets or sets the name of the underlying member or parameter. + + The name of the underlying member or parameter. + + + + Gets the that will get and set the during serialization. + + The that will get and set the during serialization. + + + + Gets or sets the for this property. + + The for this property. + + + + Gets or sets the type of the property. + + The type of the property. + + + + Gets or sets the for the property. + If set this converter takes precedence over the contract converter for the property type. + + The converter. + + + + Gets or sets the member converter. + + The member converter. + + + + Gets or sets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets or sets a value indicating whether this is readable. + + true if readable; otherwise, false. + + + + Gets or sets a value indicating whether this is writable. + + true if writable; otherwise, false. + + + + Gets or sets a value indicating whether this has a member attribute. + + true if has a member attribute; otherwise, false. + + + + Gets the default value. + + The default value. + + + + Gets or sets a value indicating whether this is required. + + A value indicating whether this is required. + + + + Gets a value indicating whether has a value specified. + + + + + Gets or sets a value indicating whether this property preserves object references. + + + true if this instance is reference; otherwise, false. + + + + + Gets or sets the property null value handling. + + The null value handling. + + + + Gets or sets the property default value handling. + + The default value handling. + + + + Gets or sets the property reference loop handling. + + The reference loop handling. + + + + Gets or sets the property object creation handling. + + The object creation handling. + + + + Gets or sets or sets the type name handling. + + The type name handling. + + + + Gets or sets a predicate used to determine whether the property should be serialized. + + A predicate used to determine whether the property should be serialized. + + + + Gets or sets a predicate used to determine whether the property should be deserialized. + + A predicate used to determine whether the property should be deserialized. + + + + Gets or sets a predicate used to determine whether the property should be serialized. + + A predicate used to determine whether the property should be serialized. + + + + Gets or sets an action used to set whether the property has been deserialized. + + An action used to set whether the property has been deserialized. + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Gets or sets the converter used when serializing the property's collection items. + + The collection's items converter. + + + + Gets or sets whether this property's collection items are serialized as a reference. + + Whether this property's collection items are serialized as a reference. + + + + Gets or sets the type name handling used when serializing the property's collection items. + + The collection's items type name handling. + + + + Gets or sets the reference loop handling used when serializing the property's collection items. + + The collection's items reference loop handling. + + + + A collection of objects. + + + + + Initializes a new instance of the class. + + The type. + + + + When implemented in a derived class, extracts the key from the specified element. + + The element from which to extract the key. + The key for the specified element. + + + + Adds a object. + + The property to add to the collection. + + + + Gets the closest matching object. + First attempts to get an exact case match of and then + a case insensitive match. + + Name of the property. + A matching property if found. + + + + Gets a property by property name. + + The name of the property to get. + Type property name string comparison. + A matching property if found. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Lookup and create an instance of the type described by the argument. + + The type to create. + Optional arguments to pass to an initializing constructor of the JsonConverter. + If null, the default constructor is used. + + + + A kebab case naming strategy. + + + + + Initializes a new instance of the class. + + + A flag indicating whether dictionary keys should be processed. + + + A flag indicating whether explicitly specified property names should be processed, + e.g. a property name customized with a . + + + + + Initializes a new instance of the class. + + + A flag indicating whether dictionary keys should be processed. + + + A flag indicating whether explicitly specified property names should be processed, + e.g. a property name customized with a . + + + A flag indicating whether extension data names should be processed. + + + + + Initializes a new instance of the class. + + + + + Resolves the specified property name. + + The property name to resolve. + The resolved property name. + + + + Represents a trace writer that writes to memory. When the trace message limit is + reached then old trace messages will be removed as new messages are added. + + + + + Gets the that will be used to filter the trace messages passed to the writer. + For example a filter level of will exclude messages and include , + and messages. + + + The that will be used to filter the trace messages passed to the writer. + + + + + Initializes a new instance of the class. + + + + + Writes the specified trace level, message and optional exception. + + The at which to write this trace. + The trace message. + The trace exception. This parameter is optional. + + + + Returns an enumeration of the most recent trace messages. + + An enumeration of the most recent trace messages. + + + + Returns a of the most recent trace messages. + + + A of the most recent trace messages. + + + + + A base class for resolving how property names and dictionary keys are serialized. + + + + + A flag indicating whether dictionary keys should be processed. + Defaults to false. + + + + + A flag indicating whether extension data names should be processed. + Defaults to false. + + + + + A flag indicating whether explicitly specified property names, + e.g. a property name customized with a , should be processed. + Defaults to false. + + + + + Gets the serialized name for a given property name. + + The initial property name. + A flag indicating whether the property has had a name explicitly specified. + The serialized property name. + + + + Gets the serialized name for a given extension data name. + + The initial extension data name. + The serialized extension data name. + + + + Gets the serialized key for a given dictionary key. + + The initial dictionary key. + The serialized dictionary key. + + + + Resolves the specified property name. + + The property name to resolve. + The resolved property name. + + + + Hash code calculation + + + + + + Object equality implementation + + + + + + + Compare to another NamingStrategy + + + + + + + Represents a method that constructs an object. + + The object type to create. + + + + When applied to a method, specifies that the method is called when an error occurs serializing an object. + + + + + Provides methods to get attributes from a , , or . + + + + + Initializes a new instance of the class. + + The instance to get attributes for. This parameter should be a , , or . + + + + Returns a collection of all of the attributes, or an empty collection if there are no attributes. + + When true, look up the hierarchy chain for the inherited custom attribute. + A collection of s, or an empty collection. + + + + Returns a collection of attributes, identified by type, or an empty collection if there are no attributes. + + The type of the attributes. + When true, look up the hierarchy chain for the inherited custom attribute. + A collection of s, or an empty collection. + + + + Get and set values for a using reflection. + + + + + Initializes a new instance of the class. + + The member info. + + + + Sets the value. + + The target to set the value on. + The value to set on the target. + + + + Gets the value. + + The target to get the value from. + The value. + + + + A snake case naming strategy. + + + + + Initializes a new instance of the class. + + + A flag indicating whether dictionary keys should be processed. + + + A flag indicating whether explicitly specified property names should be processed, + e.g. a property name customized with a . + + + + + Initializes a new instance of the class. + + + A flag indicating whether dictionary keys should be processed. + + + A flag indicating whether explicitly specified property names should be processed, + e.g. a property name customized with a . + + + A flag indicating whether extension data names should be processed. + + + + + Initializes a new instance of the class. + + + + + Resolves the specified property name. + + The property name to resolve. + The resolved property name. + + + + Specifies how strings are escaped when writing JSON text. + + + + + Only control characters (e.g. newline) are escaped. + + + + + All non-ASCII and control characters (e.g. newline) are escaped. + + + + + HTML (<, >, &, ', ") and control characters (e.g. newline) are escaped. + + + + + Indicates the method that will be used during deserialization for locating and loading assemblies. + + + + + In simple mode, the assembly used during deserialization need not match exactly the assembly used during serialization. Specifically, the version numbers need not match as the LoadWithPartialName method of the class is used to load the assembly. + + + + + In full mode, the assembly used during deserialization must match exactly the assembly used during serialization. The Load method of the class is used to load the assembly. + + + + + Specifies type name handling options for the . + + + should be used with caution when your application deserializes JSON from an external source. + Incoming types should be validated with a custom + when deserializing with a value other than . + + + + + Do not include the .NET type name when serializing types. + + + + + Include the .NET type name when serializing into a JSON object structure. + + + + + Include the .NET type name when serializing into a JSON array structure. + + + + + Always include the .NET type name when serializing. + + + + + Include the .NET type name when the type of the object being serialized is not the same as its declared type. + Note that this doesn't include the root serialized object by default. To include the root object's type name in JSON + you must specify a root type object with + or . + + + + + + + + + + Don't run action but let a compiler detect the code in action as an executable block. + + + + + Ensure(() => new T()); + + + + + Ensure generic list type can be (de)deserializable on AOT environment. + + The type of elements in the list + + + + Ensure generic dictionary type can be (de)deserializable on AOT environment. + + The type of the keys in the dictionary. + The type of the values in the dictionary. + + + + Always return false but compiler doesn't know it. + + False + + + + Determines whether the collection is null or empty. + + The collection. + + true if the collection is null or empty; otherwise, false. + + + + + Adds the elements of the specified collection to the specified generic . + + The list to add to. + The collection of elements to add. + + + + Converts the value to the specified type. If the value is unable to be converted, the + value is checked whether it assignable to the specified type. + + The value to convert. + The culture to use when converting. + The type to convert or cast the value to. + + The converted type. If conversion was unsuccessful, the initial value + is returned if assignable to the target type. + + + + + Helper method for generating a MetaObject which calls a + specific method on Dynamic that returns a result + + + + + Helper method for generating a MetaObject which calls a + specific method on Dynamic, but uses one of the arguments for + the result. + + + + + Helper method for generating a MetaObject which calls a + specific method on Dynamic, but uses one of the arguments for + the result. + + + + + Returns a Restrictions object which includes our current restrictions merged + with a restriction limiting our type + + + + + Helper class for serializing immutable collections. + Note that this is used by all builds, even those that don't support immutable collections, in case the DLL is GACed + https://github.com/JamesNK/Newtonsoft.Json/issues/652 + + + + + Gets the type of the typed collection's items. + + The type. + The type of the typed collection's items. + + + + Gets the member's underlying type. + + The member. + The underlying type of the member. + + + + Determines whether the property is an indexed property. + + The property. + + true if the property is an indexed property; otherwise, false. + + + + + Gets the member's value on the object. + + The member. + The target object. + The member's value on the object. + + + + Sets the member's value on the target object. + + The member. + The target. + The value. + + + + Determines whether the specified MemberInfo can be read. + + The MemberInfo to determine whether can be read. + /// if set to true then allow the member to be gotten non-publicly. + + true if the specified MemberInfo can be read; otherwise, false. + + + + + Determines whether the specified MemberInfo can be set. + + The MemberInfo to determine whether can be set. + if set to true then allow the member to be set non-publicly. + if set to true then allow the member to be set if read-only. + + true if the specified MemberInfo can be set; otherwise, false. + + + + + Builds a string. Unlike this class lets you reuse its internal buffer. + + + + + Determines whether the string is all white space. Empty string will return false. + + The string to test whether it is all white space. + + true if the string is all white space; otherwise, false. + + + + + Specifies the state of the . + + + + + An exception has been thrown, which has left the in an invalid state. + You may call the method to put the in the Closed state. + Any other method calls result in an being thrown. + + + + + The method has been called. + + + + + An object is being written. + + + + + An array is being written. + + + + + A constructor is being written. + + + + + A property is being written. + + + + + A write method has not been called. + + + + Specifies that an output will not be null even if the corresponding type allows it. + + + Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. + + + Initializes the attribute with the specified return value condition. + + The return value condition. If the method returns this value, the associated parameter will not be null. + + + + Gets the return value condition. + + + Specifies that an output may be null even if the corresponding type disallows it. + + + Specifies that null is allowed as an input even if the corresponding type disallows it. + + + + Specifies that the method will not return if the associated Boolean parameter is passed the specified value. + + + + + Initializes a new instance of the class. + + + The condition parameter value. Code after the method will be considered unreachable by diagnostics if the argument to + the associated parameter matches this value. + + + + Gets the condition parameter value. + + + diff --git a/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.xml.meta b/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.xml.meta new file mode 100644 index 0000000..fb52ffd --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Runtime/Newtonsoft.Json.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: fed01095b990a354289891ead909238f +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/Third Party Notices.md b/Packages/com.unity.nuget.newtonsoft-json/Third Party Notices.md new file mode 100644 index 0000000..3e19c8e --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Third Party Notices.md @@ -0,0 +1,76 @@ +This package contains third-party software components governed by the license(s) indicated below: +--------- + +Component Name: Newtonsoft.Json + +License Type: MIT + +The MIT License (MIT) + +Copyright (c) 2007 James Newton-King + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------- + +Component Name: Json.Net.Unity3D + +License Type: MIT + +The MIT License (MIT) + +Copyright (c) Copyright (c) 2016 SaladLab + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------- + +Component Name: Newtonsoft.Json-for-Unity + +License Type: MIT + +The MIT License (MIT) + +Copyright (c) Copyright (c) 2019 Kalle Jillheden (jilleJr) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +--------- +Component Name: com.newtonsoft.json + +License Type: MIT + +MIT License + +Copyright (c) 2019 Mike Wuetherick + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Packages/com.unity.nuget.newtonsoft-json/Third Party Notices.md.meta b/Packages/com.unity.nuget.newtonsoft-json/Third Party Notices.md.meta new file mode 100644 index 0000000..8a8b5b9 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/Third Party Notices.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 9422d9b1fde3cf644b4a0dddd10a7348 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/link.xml b/Packages/com.unity.nuget.newtonsoft-json/link.xml new file mode 100644 index 0000000..3a827cf --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/link.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Packages/com.unity.nuget.newtonsoft-json/link.xml.meta b/Packages/com.unity.nuget.newtonsoft-json/link.xml.meta new file mode 100644 index 0000000..6affe45 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/link.xml.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: a8a90c35b04530c4f971aaef6fdf3612 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.unity.nuget.newtonsoft-json/package.json b/Packages/com.unity.nuget.newtonsoft-json/package.json new file mode 100644 index 0000000..b5788f3 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/package.json @@ -0,0 +1 @@ +{"name":"com.unity.nuget.newtonsoft-json","displayName":"Newtonsoft Json","version":"3.2.2","unity":"2018.4","description":"Newtonsoft Json for use in Unity projects and Unity packages. Currently synced to version 13.0.2.\n\nThis package is used for advanced json serialization and deserialization. Most Unity users will be better suited using the existing json tools built into Unity.\nTo avoid assembly clashes, please use this package if you intend to use Newtonsoft Json.","type":"library","relatedPackages":{"com.unity.nuget.newtonsoft-json.tests":"3.2.1"},"_upm":{"changelog":"* Fixed Newtonsoft DLL when compiling with netstandard 2.0."},"upmCi":{"footprint":"2539acbff1d09eea1674262b4f0cad9172e2bda9"},"repository":{"url":"https://github.cds.internal.unity3d.com/unity/com.unity.nuget.newtonsoft-json.git","type":"git","revision":"d8e49aef8979bef617144382052ec2f479645eaf"}} \ No newline at end of file diff --git a/Packages/com.unity.nuget.newtonsoft-json/package.json.meta b/Packages/com.unity.nuget.newtonsoft-json/package.json.meta new file mode 100644 index 0000000..2be7706 --- /dev/null +++ b/Packages/com.unity.nuget.newtonsoft-json/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f8d4e5c2f2df25449ae8c391afbe5114 +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: