commit a7623cd55af212624eaf9210fe0209d5b8a610ec Author: wsycarlos Date: Sun Dec 28 23:11:56 2025 +0800 Initial Package with errors diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ff03d40 --- /dev/null +++ b/.gitignore @@ -0,0 +1,106 @@ +# This .gitignore file should be placed at the root of your Unity project directory +# +# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore +# +.utmp/ +/[Ll]ibrary/ +/[Tt]emp/ +/[Oo]bj/ +/[Bb]uild/ +/[Bb]uilds/ +/[Ll]ogs/ +/[Uu]ser[Ss]ettings/ +*.log + +# By default unity supports Blender asset imports, *.blend1 blender files do not need to be commited to version control. +*.blend1 +*.blend1.meta + +# MemoryCaptures can get excessive in size. +# They also could contain extremely sensitive data +/[Mm]emoryCaptures/ + +# Recordings can get excessive in size +/[Rr]ecordings/ + +# Uncomment this line if you wish to ignore the asset store tools plugin +# /[Aa]ssets/AssetStoreTools* + +# Autogenerated Jetbrains Rider plugin +/[Aa]ssets/Plugins/Editor/JetBrains* +# Jetbrains Rider personal-layer settings +*.DotSettings.user + +# Visual Studio cache directory +.vs/ + +# Gradle cache directory +.gradle/ + +# Autogenerated VS/MD/Consulo solution and project files +ExportedObj/ +.consulo/ +*.csproj +*.unityproj +*.sln +*.suo +*.tmp +*.user +*.userprefs +*.pidb +*.booproj +*.svd +*.pdb +*.mdb +*.opendb +*.VC.db + +# Unity3D generated meta files +*.pidb.meta +*.pdb.meta +*.mdb.meta + +# Unity3D generated file on crash reports +sysinfo.txt + +# Mono auto generated files +mono_crash.* + +# Builds +*.apk +*.aab +*.unitypackage +*.unitypackage.meta + +# Crashlytics generated file +crashlytics-build.properties + +# TestRunner generated files +InitTestScene*.unity* + +# Addressables default ignores, before user customizations +/ServerData +/[Aa]ssets/StreamingAssets/aa* +/[Aa]ssets/AddressableAssetsData/link.xml* +/[Aa]ssets/Addressables_Temp* +# By default, Addressables content builds will generate addressables_content_state.bin +# files in platform-specific subfolders, for example: +# /Assets/AddressableAssetsData/OSX/addressables_content_state.bin +/[Aa]ssets/AddressableAssetsData/*/*.bin* + +# Visual Scripting auto-generated files +/[Aa]ssets/Unity.VisualScripting.Generated/VisualScripting.Flow/UnitOptions.db +/[Aa]ssets/Unity.VisualScripting.Generated/VisualScripting.Flow/UnitOptions.db.meta +/[Aa]ssets/Unity.VisualScripting.Generated/VisualScripting.Core/Property Providers +/[Aa]ssets/Unity.VisualScripting.Generated/VisualScripting.Core/Property Providers.meta + +# Auto-generated scenes by play mode tests +/[Aa]ssets/[Ii]nit[Tt]est[Ss]cene*.unity* + +.vsconfig + +Logs/ +[Aa]ssets/ +[Pp]ublish/ +.vscode/settings.json +*.dat \ No newline at end of file diff --git a/Packages/com.bywaystudios.resourceloader/Editor.meta b/Packages/com.bywaystudios.resourceloader/Editor.meta new file mode 100644 index 0000000..06087f7 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: da7bdb8bfa22af447854131661c3f140 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.resourceloader/Editor/Byway.ResourceLoader.Editor.asmdef b/Packages/com.bywaystudios.resourceloader/Editor/Byway.ResourceLoader.Editor.asmdef new file mode 100644 index 0000000..75d76e4 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Editor/Byway.ResourceLoader.Editor.asmdef @@ -0,0 +1,18 @@ +{ + "name": "Byway.ResourceLoader.Editor", + "rootNamespace": "", + "references": [ + "Byway.ResourceLoader" + ], + "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.resourceloader/Editor/Byway.ResourceLoader.Editor.asmdef.meta b/Packages/com.bywaystudios.resourceloader/Editor/Byway.ResourceLoader.Editor.asmdef.meta new file mode 100644 index 0000000..4a3a0db --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Editor/Byway.ResourceLoader.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ceb5850fa4b1da54f8485d145ce1f7fb +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer.meta new file mode 100644 index 0000000..3090394 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fd9595fe20f16b6418ee574335afadca +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/AssetsOrder.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/AssetsOrder.cs new file mode 100644 index 0000000..7914d97 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/AssetsOrder.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/AssetsOrder.cs.meta new file mode 100644 index 0000000..22c68b5 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/DependencyData.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/DependencyData.cs new file mode 100644 index 0000000..a4e77a3 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/DependencyData.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/DependencyData.cs.meta new file mode 100644 index 0000000..6a1408c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzer.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzer.cs new file mode 100644 index 0000000..7401692 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzer.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzer.cs.meta new file mode 100644 index 0000000..0d35147 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzerController.CircularDependencyChecker.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzerController.CircularDependencyChecker.cs new file mode 100644 index 0000000..4732179 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzerController.CircularDependencyChecker.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzerController.CircularDependencyChecker.cs.meta new file mode 100644 index 0000000..561557b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzerController.Stamp.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzerController.Stamp.cs new file mode 100644 index 0000000..c964cbd --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzerController.Stamp.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzerController.Stamp.cs.meta new file mode 100644 index 0000000..ad6ddac --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzerController.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzerController.cs new file mode 100644 index 0000000..60f512f --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzerController.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/ResourceAnalyzerController.cs.meta new file mode 100644 index 0000000..e3411d0 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/ScatteredAssetsOrder.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/ScatteredAssetsOrder.cs new file mode 100644 index 0000000..7e89eac --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceAnalyzer/ScatteredAssetsOrder.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceAnalyzer/ScatteredAssetsOrder.cs.meta new file mode 100644 index 0000000..e5c159a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder.meta new file mode 100644 index 0000000..cab48f7 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2dd745915ad459e4c9d5aef04e1dfeea +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/AssetBundleCompressionType.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/AssetBundleCompressionType.cs new file mode 100644 index 0000000..90acffb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/AssetBundleCompressionType.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/AssetBundleCompressionType.cs.meta new file mode 100644 index 0000000..0baf1ad --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/IBuildEventHandler.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/IBuildEventHandler.cs new file mode 100644 index 0000000..4a37246 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/IBuildEventHandler.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/IBuildEventHandler.cs.meta new file mode 100644 index 0000000..80d99e1 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/Platform.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/Platform.cs new file mode 100644 index 0000000..35e7355 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/Platform.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/Platform.cs.meta new file mode 100644 index 0000000..fb32acc --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilder.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilder.cs new file mode 100644 index 0000000..a0c3cd6 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilder.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilder.cs.meta new file mode 100644 index 0000000..afd9986 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderConfigPathAttribute.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderConfigPathAttribute.cs new file mode 100644 index 0000000..0632b22 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderConfigPathAttribute.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderConfigPathAttribute.cs.meta new file mode 100644 index 0000000..a5d18b4 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.AssetData.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.AssetData.cs new file mode 100644 index 0000000..1431d4b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.AssetData.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.AssetData.cs.meta new file mode 100644 index 0000000..472e462 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.BuildReport.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.BuildReport.cs new file mode 100644 index 0000000..332a9f6 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.BuildReport.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.BuildReport.cs.meta new file mode 100644 index 0000000..70bd108 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.FileSystemHelper.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.FileSystemHelper.cs new file mode 100644 index 0000000..a0bd80a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.FileSystemHelper.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.FileSystemHelper.cs.meta new file mode 100644 index 0000000..754d7b6 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.ResourceCode.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.ResourceCode.cs new file mode 100644 index 0000000..2d0358f --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.ResourceCode.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.ResourceCode.cs.meta new file mode 100644 index 0000000..65a19fa --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.ResourceData.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.ResourceData.cs new file mode 100644 index 0000000..ad9afbd --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.ResourceData.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.ResourceData.cs.meta new file mode 100644 index 0000000..5a662b5 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.VersionListData.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.VersionListData.cs new file mode 100644 index 0000000..f45746d --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.VersionListData.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.VersionListData.cs.meta new file mode 100644 index 0000000..77b014a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.cs new file mode 100644 index 0000000..db2f945 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.DeterministicAssetBundle; + + 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.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceBuilder/ResourceBuilderController.cs.meta new file mode 100644 index 0000000..4bd0398 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceCollection.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection.meta new file mode 100644 index 0000000..80df7f1 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bc804e13da19ff043aac07751e249b43 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/Asset.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/Asset.cs new file mode 100644 index 0000000..fa7c54c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceCollection/Asset.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/Asset.cs.meta new file mode 100644 index 0000000..c983873 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceCollection/AssetType.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/AssetType.cs new file mode 100644 index 0000000..1259b6c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceCollection/AssetType.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/AssetType.cs.meta new file mode 100644 index 0000000..ead3459 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceCollection/LoadType.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/LoadType.cs new file mode 100644 index 0000000..8cec7db --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceCollection/LoadType.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/LoadType.cs.meta new file mode 100644 index 0000000..df7e038 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceCollection/Resource.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/Resource.cs new file mode 100644 index 0000000..04d378e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/Resource.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 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 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.resourceloader/Editor/ResourceCollection/Resource.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/Resource.cs.meta new file mode 100644 index 0000000..b4b12ad --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceCollection/ResourceCollection.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/ResourceCollection.cs new file mode 100644 index 0000000..75d6bfb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceCollection/ResourceCollection.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/ResourceCollection.cs.meta new file mode 100644 index 0000000..f79b8dd --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceCollection/ResourceCollectionConfigPathAttribute.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/ResourceCollectionConfigPathAttribute.cs new file mode 100644 index 0000000..cfcdbdf --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceCollection/ResourceCollectionConfigPathAttribute.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceCollection/ResourceCollectionConfigPathAttribute.cs.meta new file mode 100644 index 0000000..570a125 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor.meta new file mode 100644 index 0000000..c910193 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8e537bb30b04ebc41bd7575567444988 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/AssetSorterType.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/AssetSorterType.cs new file mode 100644 index 0000000..c8aafd7 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/AssetSorterType.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/AssetSorterType.cs.meta new file mode 100644 index 0000000..bfa9ba5 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/ResourceEditor.MenuState.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditor.MenuState.cs new file mode 100644 index 0000000..2692310 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/ResourceEditor.MenuState.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditor.MenuState.cs.meta new file mode 100644 index 0000000..70df25a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/ResourceEditor.ResourceFolder.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditor.ResourceFolder.cs new file mode 100644 index 0000000..98b2c69 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/ResourceEditor.ResourceFolder.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditor.ResourceFolder.cs.meta new file mode 100644 index 0000000..04868b9 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/ResourceEditor.ResourceItem.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditor.ResourceItem.cs new file mode 100644 index 0000000..d293444 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/ResourceEditor.ResourceItem.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditor.ResourceItem.cs.meta new file mode 100644 index 0000000..352c136 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/ResourceEditor.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditor.cs new file mode 100644 index 0000000..3b56daf --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditor.cs @@ -0,0 +1,1120 @@ +//------------------------------------------------------------ +// 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 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_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; + 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; + 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(60f)); + + if (GUI.GetNameOfFocusedControl() == "NewResourceNameTextField" || GUI.GetNameOfFocusedControl() == "NewResourceVariantTextField") + { + if (Event.current.isKey && Event.current.keyCode == KeyCode.Return) + { + EditorUtility.DisplayProgressBar("Add Resource", "Processing...", 0f); + AddResource(m_InputResourceName, m_InputResourceVariant, true); + EditorUtility.ClearProgressBar(); + Repaint(); + } + } + + if (GUILayout.Button("Add", GUILayout.Width(50f))) + { + EditorUtility.DisplayProgressBar("Add Resource", "Processing...", 0f); + AddResource(m_InputResourceName, m_InputResourceVariant, 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(60f)); + + if (GUI.GetNameOfFocusedControl() == "RenameResourceNameTextField" || GUI.GetNameOfFocusedControl() == "RenameResourceVariantTextField") + { + if (Event.current.isKey && Event.current.keyCode == KeyCode.Return) + { + EditorUtility.DisplayProgressBar("Rename Resource", "Processing...", 0f); + RenameResource(m_SelectedResource, m_InputResourceName, m_InputResourceVariant); + EditorUtility.ClearProgressBar(); + Repaint(); + } + } + + if (GUILayout.Button("OK", GUILayout.Width(50f))) + { + EditorUtility.DisplayProgressBar("Rename Resource", "Processing...", 0f); + RenameResource(m_SelectedResource, m_InputResourceName, m_InputResourceVariant); + 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, 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, bool refresh) + { + if (variant == string.Empty) + { + variant = null; + } + + string fullName = GetResourceFullName(name, variant); + if (m_Controller.AddResource(name, variant, null, LoadType.LoadFromFile, false)) + { + 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) + { + 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)) + { + 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.resourceloader/Editor/ResourceEditor/ResourceEditor.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditor.cs.meta new file mode 100644 index 0000000..a3dab36 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/ResourceEditorConfigPathAttribute.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditorConfigPathAttribute.cs new file mode 100644 index 0000000..fda042c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/ResourceEditorConfigPathAttribute.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditorConfigPathAttribute.cs.meta new file mode 100644 index 0000000..0071545 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/ResourceEditorController.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditorController.cs new file mode 100644 index 0000000..fb6114b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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) + { + return m_ResourceCollection.AddResource(name, variant, fileSystem, loadType, packed); + } + + 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.resourceloader/Editor/ResourceEditor/ResourceEditorController.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/ResourceEditorController.cs.meta new file mode 100644 index 0000000..71601b3 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/SourceAsset.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/SourceAsset.cs new file mode 100644 index 0000000..1684a59 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/SourceAsset.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/SourceAsset.cs.meta new file mode 100644 index 0000000..684ff15 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/SourceFolder.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/SourceFolder.cs new file mode 100644 index 0000000..69d974b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceEditor/SourceFolder.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceEditor/SourceFolder.cs.meta new file mode 100644 index 0000000..2732159 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourcePackBuilder.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourcePackBuilder.meta new file mode 100644 index 0000000..c737e64 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Editor/ResourcePackBuilder.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3564da2c360cfdb46acffa4b7f42d275 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.resourceloader/Editor/ResourcePackBuilder/ResourcePackBuilder.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourcePackBuilder/ResourcePackBuilder.cs new file mode 100644 index 0000000..60afb3c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourcePackBuilder/ResourcePackBuilder.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourcePackBuilder/ResourcePackBuilder.cs.meta new file mode 100644 index 0000000..8cbf15a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourcePackBuilder/ResourcePackBuilderController.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourcePackBuilder/ResourcePackBuilderController.cs new file mode 100644 index 0000000..477d73f --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourcePackBuilder/ResourcePackBuilderController.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourcePackBuilder/ResourcePackBuilderController.cs.meta new file mode 100644 index 0000000..ddf0964 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceSyncTools.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceSyncTools.meta new file mode 100644 index 0000000..78f6e43 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Editor/ResourceSyncTools.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3d96add3948f44049bb53f4207cdee15 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.resourceloader/Editor/ResourceSyncTools/ResourceSyncTools.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceSyncTools/ResourceSyncTools.cs new file mode 100644 index 0000000..9a0d9bb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceSyncTools/ResourceSyncTools.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceSyncTools/ResourceSyncTools.cs.meta new file mode 100644 index 0000000..72a8983 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceSyncTools/ResourceSyncToolsController.cs b/Packages/com.bywaystudios.resourceloader/Editor/ResourceSyncTools/ResourceSyncToolsController.cs new file mode 100644 index 0000000..12c5287 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Editor/ResourceSyncTools/ResourceSyncToolsController.cs.meta b/Packages/com.bywaystudios.resourceloader/Editor/ResourceSyncTools/ResourceSyncToolsController.cs.meta new file mode 100644 index 0000000..b3a7631 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/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.resourceloader/Runtime.meta b/Packages/com.bywaystudios.resourceloader/Runtime.meta new file mode 100644 index 0000000..8c6f730 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e2255dcc5c6cd5349819787a0ec15554 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.resourceloader/Runtime/Byway.ResourceLoader.asmdef b/Packages/com.bywaystudios.resourceloader/Runtime/Byway.ResourceLoader.asmdef new file mode 100644 index 0000000..6386ee1 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/Byway.ResourceLoader.asmdef @@ -0,0 +1,3 @@ +{ + "name": "Byway.ResourceLoader" +} diff --git a/Packages/com.bywaystudios.resourceloader/Runtime/Byway.ResourceLoader.asmdef.meta b/Packages/com.bywaystudios.resourceloader/Runtime/Byway.ResourceLoader.asmdef.meta new file mode 100644 index 0000000..9583758 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/Byway.ResourceLoader.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2ed8c5c15f686974c93241dd368c4cc8 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework.meta new file mode 100644 index 0000000..09cb8ec --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c59a93bee4270d54994aa089a32b353d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ApplyResourcesCompleteCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ApplyResourcesCompleteCallback.cs new file mode 100644 index 0000000..ac3cf34 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ApplyResourcesCompleteCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ApplyResourcesCompleteCallback.cs.meta new file mode 100644 index 0000000..d09b76c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/CheckResourcesCompleteCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/CheckResourcesCompleteCallback.cs new file mode 100644 index 0000000..5077a9a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/CheckResourcesCompleteCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/CheckResourcesCompleteCallback.cs.meta new file mode 100644 index 0000000..aab0b02 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/CheckVersionListResult.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/CheckVersionListResult.cs new file mode 100644 index 0000000..5ca6d37 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/CheckVersionListResult.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/CheckVersionListResult.cs.meta new file mode 100644 index 0000000..a9bfc16 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/Constant.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/Constant.cs new file mode 100644 index 0000000..7cda805 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/Constant.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/Constant.cs.meta new file mode 100644 index 0000000..c462ec9 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/DecryptResourceCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/DecryptResourceCallback.cs new file mode 100644 index 0000000..88febfe --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/DecryptResourceCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/DecryptResourceCallback.cs.meta new file mode 100644 index 0000000..6bf8649 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/HasAssetResult.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/HasAssetResult.cs new file mode 100644 index 0000000..ca472de --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/HasAssetResult.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/HasAssetResult.cs.meta new file mode 100644 index 0000000..49bcdc5 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ILoadResourceAgentHelper.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ILoadResourceAgentHelper.cs new file mode 100644 index 0000000..a01b1cb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ILoadResourceAgentHelper.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ILoadResourceAgentHelper.cs.meta new file mode 100644 index 0000000..852f4ca --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/IResourceGroup.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/IResourceGroup.cs new file mode 100644 index 0000000..fc42fd3 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/IResourceGroup.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/IResourceGroup.cs.meta new file mode 100644 index 0000000..125812e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/IResourceGroupCollection.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/IResourceGroupCollection.cs new file mode 100644 index 0000000..0ad3972 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/IResourceGroupCollection.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/IResourceGroupCollection.cs.meta new file mode 100644 index 0000000..88b3266 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/IResourceHelper.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/IResourceHelper.cs new file mode 100644 index 0000000..23b5e93 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/IResourceHelper.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/IResourceHelper.cs.meta new file mode 100644 index 0000000..ca146a2 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/IResourceManager.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/IResourceManager.cs new file mode 100644 index 0000000..15ac7d7 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/IResourceManager.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/IResourceManager.cs.meta new file mode 100644 index 0000000..5a29a4f --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/InitResourcesCompleteCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/InitResourcesCompleteCallback.cs new file mode 100644 index 0000000..e2554f3 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/InitResourcesCompleteCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/InitResourcesCompleteCallback.cs.meta new file mode 100644 index 0000000..4e5cbaf --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadAssetCallbacks.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadAssetCallbacks.cs new file mode 100644 index 0000000..a5015d6 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadAssetCallbacks.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadAssetCallbacks.cs.meta new file mode 100644 index 0000000..5ba0ef5 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadAssetDependencyAssetCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadAssetDependencyAssetCallback.cs new file mode 100644 index 0000000..d27644f --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadAssetDependencyAssetCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadAssetDependencyAssetCallback.cs.meta new file mode 100644 index 0000000..ead2a06 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadAssetFailureCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadAssetFailureCallback.cs new file mode 100644 index 0000000..6bbf320 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadAssetFailureCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadAssetFailureCallback.cs.meta new file mode 100644 index 0000000..2e83768 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadAssetSuccessCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadAssetSuccessCallback.cs new file mode 100644 index 0000000..42e1e2b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadAssetSuccessCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadAssetSuccessCallback.cs.meta new file mode 100644 index 0000000..11b3ddf --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadAssetUpdateCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadAssetUpdateCallback.cs new file mode 100644 index 0000000..c974418 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadAssetUpdateCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadAssetUpdateCallback.cs.meta new file mode 100644 index 0000000..3254e80 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadBinaryCallbacks.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadBinaryCallbacks.cs new file mode 100644 index 0000000..6f48103 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadBinaryCallbacks.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadBinaryCallbacks.cs.meta new file mode 100644 index 0000000..b31ddbb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadBinaryFailureCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadBinaryFailureCallback.cs new file mode 100644 index 0000000..b082502 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadBinaryFailureCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadBinaryFailureCallback.cs.meta new file mode 100644 index 0000000..8a20c3d --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadBinarySuccessCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadBinarySuccessCallback.cs new file mode 100644 index 0000000..d6c9476 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadBinarySuccessCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadBinarySuccessCallback.cs.meta new file mode 100644 index 0000000..8cf5290 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadBytesCallbacks.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadBytesCallbacks.cs new file mode 100644 index 0000000..0e371b3 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadBytesCallbacks.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadBytesCallbacks.cs.meta new file mode 100644 index 0000000..4260c1a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadBytesFailureCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadBytesFailureCallback.cs new file mode 100644 index 0000000..9195bf0 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadBytesFailureCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadBytesFailureCallback.cs.meta new file mode 100644 index 0000000..c89bbed --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadBytesSuccessCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadBytesSuccessCallback.cs new file mode 100644 index 0000000..538a67b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadBytesSuccessCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadBytesSuccessCallback.cs.meta new file mode 100644 index 0000000..7292201 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperErrorEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperErrorEventArgs.cs new file mode 100644 index 0000000..d6b7e7c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperErrorEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperErrorEventArgs.cs.meta new file mode 100644 index 0000000..3687f79 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperLoadCompleteEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperLoadCompleteEventArgs.cs new file mode 100644 index 0000000..24fbeaa --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperLoadCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperLoadCompleteEventArgs.cs.meta new file mode 100644 index 0000000..9f36f63 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperParseBytesCompleteEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperParseBytesCompleteEventArgs.cs new file mode 100644 index 0000000..c63d693 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperParseBytesCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperParseBytesCompleteEventArgs.cs.meta new file mode 100644 index 0000000..cad4369 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperReadBytesCompleteEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperReadBytesCompleteEventArgs.cs new file mode 100644 index 0000000..2dbec52 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperReadBytesCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperReadBytesCompleteEventArgs.cs.meta new file mode 100644 index 0000000..32060ad --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperReadFileCompleteEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperReadFileCompleteEventArgs.cs new file mode 100644 index 0000000..62c39ee --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperReadFileCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperReadFileCompleteEventArgs.cs.meta new file mode 100644 index 0000000..fe54932 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperUpdateEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperUpdateEventArgs.cs new file mode 100644 index 0000000..fded812 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperUpdateEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceAgentHelperUpdateEventArgs.cs.meta new file mode 100644 index 0000000..e94c220 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceProgress.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceProgress.cs new file mode 100644 index 0000000..6293362 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceProgress.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceProgress.cs.meta new file mode 100644 index 0000000..223acb6 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceStatus.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceStatus.cs new file mode 100644 index 0000000..ec8d2cc --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadResourceStatus.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadResourceStatus.cs.meta new file mode 100644 index 0000000..c298ad8 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadSceneCallbacks.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadSceneCallbacks.cs new file mode 100644 index 0000000..bbccf88 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadSceneCallbacks.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadSceneCallbacks.cs.meta new file mode 100644 index 0000000..77ff4f1 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadSceneDependencyAssetCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadSceneDependencyAssetCallback.cs new file mode 100644 index 0000000..17787a6 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadSceneDependencyAssetCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadSceneDependencyAssetCallback.cs.meta new file mode 100644 index 0000000..8a2099f --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadSceneFailureCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadSceneFailureCallback.cs new file mode 100644 index 0000000..4618031 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadSceneFailureCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadSceneFailureCallback.cs.meta new file mode 100644 index 0000000..5eccdf6 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadSceneSuccessCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadSceneSuccessCallback.cs new file mode 100644 index 0000000..3fefc8a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadSceneSuccessCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadSceneSuccessCallback.cs.meta new file mode 100644 index 0000000..712808f --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadSceneUpdateCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadSceneUpdateCallback.cs new file mode 100644 index 0000000..bfd5d7c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LoadSceneUpdateCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LoadSceneUpdateCallback.cs.meta new file mode 100644 index 0000000..742141d --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LocalVersionList.FileSystem.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LocalVersionList.FileSystem.cs new file mode 100644 index 0000000..7052cd0 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LocalVersionList.FileSystem.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LocalVersionList.FileSystem.cs.meta new file mode 100644 index 0000000..da33378 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LocalVersionList.Resource.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LocalVersionList.Resource.cs new file mode 100644 index 0000000..945ebb7 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LocalVersionList.Resource.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LocalVersionList.Resource.cs.meta new file mode 100644 index 0000000..9a13f24 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LocalVersionList.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LocalVersionList.cs new file mode 100644 index 0000000..bfeafbc --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/LocalVersionList.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/LocalVersionList.cs.meta new file mode 100644 index 0000000..789e429 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/PackageVersionList.Asset.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/PackageVersionList.Asset.cs new file mode 100644 index 0000000..2f35aa6 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/PackageVersionList.Asset.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/PackageVersionList.Asset.cs.meta new file mode 100644 index 0000000..6fd166b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/PackageVersionList.FileSystem.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/PackageVersionList.FileSystem.cs new file mode 100644 index 0000000..25e577c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/PackageVersionList.FileSystem.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/PackageVersionList.FileSystem.cs.meta new file mode 100644 index 0000000..9f5eac1 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/PackageVersionList.Resource.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/PackageVersionList.Resource.cs new file mode 100644 index 0000000..e2f7beb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/PackageVersionList.Resource.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/PackageVersionList.Resource.cs.meta new file mode 100644 index 0000000..3df6bab --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/PackageVersionList.ResourceGroup.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/PackageVersionList.ResourceGroup.cs new file mode 100644 index 0000000..630ba68 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/PackageVersionList.ResourceGroup.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/PackageVersionList.ResourceGroup.cs.meta new file mode 100644 index 0000000..27f9e73 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/PackageVersionList.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/PackageVersionList.cs new file mode 100644 index 0000000..cb1fca5 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/PackageVersionList.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/PackageVersionList.cs.meta new file mode 100644 index 0000000..2bc8e96 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/PackageVersionListSerializer.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/PackageVersionListSerializer.cs new file mode 100644 index 0000000..9038174 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/PackageVersionListSerializer.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/PackageVersionListSerializer.cs.meta new file mode 100644 index 0000000..bbd87fb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ReadOnlyVersionListSerializer.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ReadOnlyVersionListSerializer.cs new file mode 100644 index 0000000..6defb90 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ReadOnlyVersionListSerializer.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ReadOnlyVersionListSerializer.cs.meta new file mode 100644 index 0000000..9bd3003 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ReadWriteVersionListSerializer.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ReadWriteVersionListSerializer.cs new file mode 100644 index 0000000..1c902ed --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ReadWriteVersionListSerializer.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ReadWriteVersionListSerializer.cs.meta new file mode 100644 index 0000000..5b9d641 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceApplyFailureEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceApplyFailureEventArgs.cs new file mode 100644 index 0000000..5ca3bef --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceApplyFailureEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceApplyFailureEventArgs.cs.meta new file mode 100644 index 0000000..cf5c442 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceApplyStartEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceApplyStartEventArgs.cs new file mode 100644 index 0000000..f3876d1 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceApplyStartEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceApplyStartEventArgs.cs.meta new file mode 100644 index 0000000..803c715 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceApplySuccessEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceApplySuccessEventArgs.cs new file mode 100644 index 0000000..a73a332 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceApplySuccessEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceApplySuccessEventArgs.cs.meta new file mode 100644 index 0000000..5d589fc --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.AssetInfo.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.AssetInfo.cs new file mode 100644 index 0000000..6785c2e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.AssetInfo.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.AssetInfo.cs.meta new file mode 100644 index 0000000..a09e055 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.LoadType.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.LoadType.cs new file mode 100644 index 0000000..43825af --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.LoadType.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.LoadType.cs.meta new file mode 100644 index 0000000..f0831cb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ReadWriteResourceInfo.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ReadWriteResourceInfo.cs new file mode 100644 index 0000000..d349fb2 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ReadWriteResourceInfo.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ReadWriteResourceInfo.cs.meta new file mode 100644 index 0000000..aa1c9d8 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.CheckStatus.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.CheckStatus.cs new file mode 100644 index 0000000..5ab17ee --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.CheckStatus.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.CheckStatus.cs.meta new file mode 100644 index 0000000..24ace59 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.LocalVersionInfo.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.LocalVersionInfo.cs new file mode 100644 index 0000000..4f22410 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.LocalVersionInfo.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.LocalVersionInfo.cs.meta new file mode 100644 index 0000000..e750697 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.RemoteVersionInfo.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.RemoteVersionInfo.cs new file mode 100644 index 0000000..52bb19e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.RemoteVersionInfo.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.RemoteVersionInfo.cs.meta new file mode 100644 index 0000000..0ffe6c0 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.cs new file mode 100644 index 0000000..683f808 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.CheckInfo.cs.meta new file mode 100644 index 0000000..8ceee72 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.cs new file mode 100644 index 0000000..e3e9431 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceChecker.cs.meta new file mode 100644 index 0000000..f1b108c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceGroup.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceGroup.cs new file mode 100644 index 0000000..a215aad --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceGroup.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceGroup.cs.meta new file mode 100644 index 0000000..aec98d4 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceGroupCollection.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceGroupCollection.cs new file mode 100644 index 0000000..8439d8b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceGroupCollection.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceGroupCollection.cs.meta new file mode 100644 index 0000000..ef570e0 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceInfo.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceInfo.cs new file mode 100644 index 0000000..170d572 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceInfo.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceInfo.cs.meta new file mode 100644 index 0000000..e883907 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceIniter.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceIniter.cs new file mode 100644 index 0000000..0a89778 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceIniter.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceIniter.cs.meta new file mode 100644 index 0000000..dd77eac --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.AssetObject.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.AssetObject.cs new file mode 100644 index 0000000..695779a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.AssetObject.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.AssetObject.cs.meta new file mode 100644 index 0000000..2e99e77 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadAssetTask.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadAssetTask.cs new file mode 100644 index 0000000..ffc66be --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadAssetTask.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadAssetTask.cs.meta new file mode 100644 index 0000000..28f283b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadBinaryInfo.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadBinaryInfo.cs new file mode 100644 index 0000000..45657b0 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadBinaryInfo.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadBinaryInfo.cs.meta new file mode 100644 index 0000000..e0e0a8b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadDependencyAssetTask.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadDependencyAssetTask.cs new file mode 100644 index 0000000..6da2e63 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadDependencyAssetTask.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadDependencyAssetTask.cs.meta new file mode 100644 index 0000000..9ff26a8 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadResourceAgent.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadResourceAgent.cs new file mode 100644 index 0000000..f7d340f --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadResourceAgent.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadResourceAgent.cs.meta new file mode 100644 index 0000000..e49e493 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadResourceTaskBase.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadResourceTaskBase.cs new file mode 100644 index 0000000..b371f1e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadResourceTaskBase.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadResourceTaskBase.cs.meta new file mode 100644 index 0000000..9e9381e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadSceneTask.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadSceneTask.cs new file mode 100644 index 0000000..0ed85f5 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadSceneTask.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.LoadSceneTask.cs.meta new file mode 100644 index 0000000..ba54c82 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.ResourceObject.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.ResourceObject.cs new file mode 100644 index 0000000..9242566 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.ResourceObject.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.ResourceObject.cs.meta new file mode 100644 index 0000000..32d2856 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.cs new file mode 100644 index 0000000..4659931 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceLoader.cs.meta new file mode 100644 index 0000000..4784739 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceName.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceName.cs new file mode 100644 index 0000000..2a077e6 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceName.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceName.cs.meta new file mode 100644 index 0000000..2b00822 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceNameComparer.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceNameComparer.cs new file mode 100644 index 0000000..ece5d44 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceNameComparer.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceNameComparer.cs.meta new file mode 100644 index 0000000..9d83dc5 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceUpdater.ApplyInfo.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceUpdater.ApplyInfo.cs new file mode 100644 index 0000000..6272caf --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceUpdater.ApplyInfo.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceUpdater.ApplyInfo.cs.meta new file mode 100644 index 0000000..5145119 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceUpdater.UpdateInfo.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceUpdater.UpdateInfo.cs new file mode 100644 index 0000000..bd4c138 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceUpdater.UpdateInfo.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceUpdater.UpdateInfo.cs.meta new file mode 100644 index 0000000..cb90c2e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceUpdater.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceUpdater.cs new file mode 100644 index 0000000..b81aef0 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceUpdater.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceUpdater.cs.meta new file mode 100644 index 0000000..8de46ce --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceVerifier.VerifyInfo.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceVerifier.VerifyInfo.cs new file mode 100644 index 0000000..b6d2a6e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceVerifier.VerifyInfo.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceVerifier.VerifyInfo.cs.meta new file mode 100644 index 0000000..e863eca --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceVerifier.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceVerifier.cs new file mode 100644 index 0000000..ff6aa9b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.ResourceVerifier.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.ResourceVerifier.cs.meta new file mode 100644 index 0000000..0959144 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.VersionListProcessor.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.VersionListProcessor.cs new file mode 100644 index 0000000..d5caff4 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.VersionListProcessor.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.VersionListProcessor.cs.meta new file mode 100644 index 0000000..3c58369 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.cs new file mode 100644 index 0000000..a6656bb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceManager.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceManager.cs.meta new file mode 100644 index 0000000..87431e3 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceMode.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceMode.cs new file mode 100644 index 0000000..5499382 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceMode.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceMode.cs.meta new file mode 100644 index 0000000..c73155f --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourcePackVersionList.Resource.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourcePackVersionList.Resource.cs new file mode 100644 index 0000000..ca09125 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourcePackVersionList.Resource.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourcePackVersionList.Resource.cs.meta new file mode 100644 index 0000000..8b5915e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourcePackVersionList.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourcePackVersionList.cs new file mode 100644 index 0000000..ef89148 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourcePackVersionList.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourcePackVersionList.cs.meta new file mode 100644 index 0000000..332a0ad --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourcePackVersionListSerializer.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourcePackVersionListSerializer.cs new file mode 100644 index 0000000..539b8d7 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourcePackVersionListSerializer.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourcePackVersionListSerializer.cs.meta new file mode 100644 index 0000000..9e749e4 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceUpdateAllCompleteEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceUpdateAllCompleteEventArgs.cs new file mode 100644 index 0000000..1be8522 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceUpdateAllCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceUpdateAllCompleteEventArgs.cs.meta new file mode 100644 index 0000000..ad52bff --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceUpdateChangedEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceUpdateChangedEventArgs.cs new file mode 100644 index 0000000..4c99008 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceUpdateChangedEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceUpdateChangedEventArgs.cs.meta new file mode 100644 index 0000000..621bb33 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceUpdateFailureEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceUpdateFailureEventArgs.cs new file mode 100644 index 0000000..544e884 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceUpdateFailureEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceUpdateFailureEventArgs.cs.meta new file mode 100644 index 0000000..20a94fd --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceUpdateStartEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceUpdateStartEventArgs.cs new file mode 100644 index 0000000..0f4d9ae --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceUpdateStartEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceUpdateStartEventArgs.cs.meta new file mode 100644 index 0000000..25c38e3 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceUpdateSuccessEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceUpdateSuccessEventArgs.cs new file mode 100644 index 0000000..3894a5c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceUpdateSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceUpdateSuccessEventArgs.cs.meta new file mode 100644 index 0000000..dbdc29d --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceVerifyFailureEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceVerifyFailureEventArgs.cs new file mode 100644 index 0000000..efaaef1 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceVerifyFailureEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceVerifyFailureEventArgs.cs.meta new file mode 100644 index 0000000..249b6ba --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceVerifyStartEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceVerifyStartEventArgs.cs new file mode 100644 index 0000000..9c3e3bd --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceVerifyStartEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceVerifyStartEventArgs.cs.meta new file mode 100644 index 0000000..f6b3361 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceVerifySuccessEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceVerifySuccessEventArgs.cs new file mode 100644 index 0000000..4557f8a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/ResourceVerifySuccessEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/ResourceVerifySuccessEventArgs.cs.meta new file mode 100644 index 0000000..5c07f10 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UnloadSceneCallbacks.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UnloadSceneCallbacks.cs new file mode 100644 index 0000000..24bc510 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UnloadSceneCallbacks.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UnloadSceneCallbacks.cs.meta new file mode 100644 index 0000000..fe3cefd --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UnloadSceneFailureCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UnloadSceneFailureCallback.cs new file mode 100644 index 0000000..5c62a76 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UnloadSceneFailureCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UnloadSceneFailureCallback.cs.meta new file mode 100644 index 0000000..c6ead2d --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UnloadSceneSuccessCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UnloadSceneSuccessCallback.cs new file mode 100644 index 0000000..4337db1 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UnloadSceneSuccessCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UnloadSceneSuccessCallback.cs.meta new file mode 100644 index 0000000..7452ee1 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdatableVersionList.Asset.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdatableVersionList.Asset.cs new file mode 100644 index 0000000..89b976e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdatableVersionList.Asset.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdatableVersionList.Asset.cs.meta new file mode 100644 index 0000000..fbcf37f --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdatableVersionList.FileSystem.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdatableVersionList.FileSystem.cs new file mode 100644 index 0000000..bd28196 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdatableVersionList.FileSystem.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdatableVersionList.FileSystem.cs.meta new file mode 100644 index 0000000..1556cd9 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdatableVersionList.Resource.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdatableVersionList.Resource.cs new file mode 100644 index 0000000..b4eceaf --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdatableVersionList.Resource.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdatableVersionList.Resource.cs.meta new file mode 100644 index 0000000..84f3ba3 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdatableVersionList.ResourceGroup.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdatableVersionList.ResourceGroup.cs new file mode 100644 index 0000000..b0df9f8 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdatableVersionList.ResourceGroup.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdatableVersionList.ResourceGroup.cs.meta new file mode 100644 index 0000000..71ef3c2 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdatableVersionList.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdatableVersionList.cs new file mode 100644 index 0000000..e8f908d --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdatableVersionList.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdatableVersionList.cs.meta new file mode 100644 index 0000000..09140fb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdatableVersionListSerializer.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdatableVersionListSerializer.cs new file mode 100644 index 0000000..2ea4bbc --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdatableVersionListSerializer.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdatableVersionListSerializer.cs.meta new file mode 100644 index 0000000..ca15d71 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdateResourcesCompleteCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdateResourcesCompleteCallback.cs new file mode 100644 index 0000000..5c26ce5 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdateResourcesCompleteCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdateResourcesCompleteCallback.cs.meta new file mode 100644 index 0000000..c8b730c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdateVersionListCallbacks.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdateVersionListCallbacks.cs new file mode 100644 index 0000000..89d9f5e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdateVersionListCallbacks.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdateVersionListCallbacks.cs.meta new file mode 100644 index 0000000..4619be7 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdateVersionListFailureCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdateVersionListFailureCallback.cs new file mode 100644 index 0000000..e2f32ba --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdateVersionListFailureCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdateVersionListFailureCallback.cs.meta new file mode 100644 index 0000000..0f08aba --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdateVersionListSuccessCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdateVersionListSuccessCallback.cs new file mode 100644 index 0000000..01cc3ff --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/UpdateVersionListSuccessCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/UpdateVersionListSuccessCallback.cs.meta new file mode 100644 index 0000000..12a5a50 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/VerifyResourcesCompleteCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/VerifyResourcesCompleteCallback.cs new file mode 100644 index 0000000..0202418 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/GameFramework/VerifyResourcesCompleteCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/VerifyResourcesCompleteCallback.cs.meta new file mode 100644 index 0000000..8ff6e96 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/GameFramework/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.resourceloader/Runtime/UnityGameFramework.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework.meta new file mode 100644 index 0000000..a8c1bff --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 82030b5545d53814c958776e6973a62b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.LocalVersionListDeserializeCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.LocalVersionListDeserializeCallback.cs new file mode 100644 index 0000000..bdafd50 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.LocalVersionListDeserializeCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.LocalVersionListDeserializeCallback.cs.meta new file mode 100644 index 0000000..c57ed16 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.LocalVersionListSerializeCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.LocalVersionListSerializeCallback.cs new file mode 100644 index 0000000..faabcc5 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.LocalVersionListSerializeCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.LocalVersionListSerializeCallback.cs.meta new file mode 100644 index 0000000..f9df195 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.PackageVersionListDeserializeCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.PackageVersionListDeserializeCallback.cs new file mode 100644 index 0000000..665a758 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.PackageVersionListDeserializeCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.PackageVersionListDeserializeCallback.cs.meta new file mode 100644 index 0000000..9d5ad27 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.PackageVersionListSerializeCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.PackageVersionListSerializeCallback.cs new file mode 100644 index 0000000..f07b3fd --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.PackageVersionListSerializeCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.PackageVersionListSerializeCallback.cs.meta new file mode 100644 index 0000000..39b29ad --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.ResourcePackVersionListDeserializeCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.ResourcePackVersionListDeserializeCallback.cs new file mode 100644 index 0000000..a95bceb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.ResourcePackVersionListDeserializeCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.ResourcePackVersionListDeserializeCallback.cs.meta new file mode 100644 index 0000000..45413f9 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.ResourcePackVersionListSerializeCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.ResourcePackVersionListSerializeCallback.cs new file mode 100644 index 0000000..b2514fb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.ResourcePackVersionListSerializeCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.ResourcePackVersionListSerializeCallback.cs.meta new file mode 100644 index 0000000..415e921 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback.cs new file mode 100644 index 0000000..91d05a4 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.UpdatableVersionListDeserializeCallback.cs.meta new file mode 100644 index 0000000..91ac6ff --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback.cs new file mode 100644 index 0000000..bc7782a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.UpdatableVersionListSerializeCallback.cs.meta new file mode 100644 index 0000000..b5a77e7 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback.cs new file mode 100644 index 0000000..025122c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.UpdatableVersionListTryGetValueCallback.cs.meta new file mode 100644 index 0000000..47c9a4d --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.cs new file mode 100644 index 0000000..6f9279d --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/BuiltinVersionListSerializer.cs.meta new file mode 100644 index 0000000..68a5296 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/DefaultLoadResourceAgentHelper.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/DefaultLoadResourceAgentHelper.cs new file mode 100644 index 0000000..4d98e76 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/DefaultLoadResourceAgentHelper.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/DefaultLoadResourceAgentHelper.cs.meta new file mode 100644 index 0000000..91c066e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/DefaultResourceHelper.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/DefaultResourceHelper.cs new file mode 100644 index 0000000..e90f950 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/DefaultResourceHelper.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/DefaultResourceHelper.cs.meta new file mode 100644 index 0000000..0cbaefd --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/EditorResourceComponent.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/EditorResourceComponent.cs new file mode 100644 index 0000000..019115e --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/EditorResourceComponent.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/EditorResourceComponent.cs.meta new file mode 100644 index 0000000..9d5df4b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/LoadResourceAgentHelperBase.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/LoadResourceAgentHelperBase.cs new file mode 100644 index 0000000..2a7d788 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/LoadResourceAgentHelperBase.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/LoadResourceAgentHelperBase.cs.meta new file mode 100644 index 0000000..8a8bfa0 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ReadWritePathType.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ReadWritePathType.cs new file mode 100644 index 0000000..5f41bf4 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ReadWritePathType.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ReadWritePathType.cs.meta new file mode 100644 index 0000000..d88efcd --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceApplyFailureEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceApplyFailureEventArgs.cs new file mode 100644 index 0000000..1052e48 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceApplyFailureEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceApplyFailureEventArgs.cs.meta new file mode 100644 index 0000000..d51598d --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceApplyStartEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceApplyStartEventArgs.cs new file mode 100644 index 0000000..3d8775b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceApplyStartEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceApplyStartEventArgs.cs.meta new file mode 100644 index 0000000..3dad449 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceApplySuccessEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceApplySuccessEventArgs.cs new file mode 100644 index 0000000..858d046 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceApplySuccessEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceApplySuccessEventArgs.cs.meta new file mode 100644 index 0000000..a4286d0 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceComponent.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceComponent.cs new file mode 100644 index 0000000..ae3612d --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceComponent.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceComponent.cs.meta new file mode 100644 index 0000000..8b99b82 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceHelperBase.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceHelperBase.cs new file mode 100644 index 0000000..df016bf --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceHelperBase.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceHelperBase.cs.meta new file mode 100644 index 0000000..d5bb43b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceUpdateAllCompleteEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceUpdateAllCompleteEventArgs.cs new file mode 100644 index 0000000..219c0a2 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceUpdateAllCompleteEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceUpdateAllCompleteEventArgs.cs.meta new file mode 100644 index 0000000..76f67ac --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceUpdateChangedEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceUpdateChangedEventArgs.cs new file mode 100644 index 0000000..f117e3b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceUpdateChangedEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceUpdateChangedEventArgs.cs.meta new file mode 100644 index 0000000..c4fffdb --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceUpdateFailureEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceUpdateFailureEventArgs.cs new file mode 100644 index 0000000..27f5757 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceUpdateFailureEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceUpdateFailureEventArgs.cs.meta new file mode 100644 index 0000000..36fddcf --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceUpdateStartEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceUpdateStartEventArgs.cs new file mode 100644 index 0000000..14f191d --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceUpdateStartEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceUpdateStartEventArgs.cs.meta new file mode 100644 index 0000000..2461868 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceUpdateSuccessEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceUpdateSuccessEventArgs.cs new file mode 100644 index 0000000..8438b3d --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceUpdateSuccessEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceUpdateSuccessEventArgs.cs.meta new file mode 100644 index 0000000..2d27644 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceVerifyFailureEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceVerifyFailureEventArgs.cs new file mode 100644 index 0000000..326a22b --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceVerifyFailureEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceVerifyFailureEventArgs.cs.meta new file mode 100644 index 0000000..98a87dc --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceVerifyStartEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceVerifyStartEventArgs.cs new file mode 100644 index 0000000..9879f0a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceVerifyStartEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceVerifyStartEventArgs.cs.meta new file mode 100644 index 0000000..1def453 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceVerifySuccessEventArgs.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceVerifySuccessEventArgs.cs new file mode 100644 index 0000000..e90ac8a --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/ResourceVerifySuccessEventArgs.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/ResourceVerifySuccessEventArgs.cs.meta new file mode 100644 index 0000000..d27f4c5 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/SceneAsset.cs b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/SceneAsset.cs new file mode 100644 index 0000000..c926b6f --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/Runtime/UnityGameFramework/SceneAsset.cs.meta b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/SceneAsset.cs.meta new file mode 100644 index 0000000..4f03827 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/Runtime/UnityGameFramework/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.resourceloader/package.json b/Packages/com.bywaystudios.resourceloader/package.json new file mode 100644 index 0000000..b36968c --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/package.json @@ -0,0 +1,6 @@ +{ + "name": "com.bywaystudios.resourceloader", + "displayName": "ResourceLoader", + "version": "0.1.0", + "description": "To Load Resource from AssetBundles" +} \ No newline at end of file diff --git a/Packages/com.bywaystudios.resourceloader/package.json.meta b/Packages/com.bywaystudios.resourceloader/package.json.meta new file mode 100644 index 0000000..7a55b78 --- /dev/null +++ b/Packages/com.bywaystudios.resourceloader/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: be1bc1c0829599f45a9315a010d2e83e +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/manifest.json b/Packages/manifest.json new file mode 100644 index 0000000..5106b7d --- /dev/null +++ b/Packages/manifest.json @@ -0,0 +1,38 @@ +{ + "dependencies": { + "com.unity.asset-store-validation": "0.6.0", + "com.unity.feature.development": "1.0.1", + "com.unity.upm.develop": "0.5.3-exp.1", + "com.unity.modules.ai": "1.0.0", + "com.unity.modules.androidjni": "1.0.0", + "com.unity.modules.animation": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.cloth": "1.0.0", + "com.unity.modules.director": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.particlesystem": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.physics2d": "1.0.0", + "com.unity.modules.screencapture": "1.0.0", + "com.unity.modules.terrain": "1.0.0", + "com.unity.modules.terrainphysics": "1.0.0", + "com.unity.modules.tilemap": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.uielements": "1.0.0", + "com.unity.modules.umbra": "1.0.0", + "com.unity.modules.unityanalytics": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.unitywebrequesttexture": "1.0.0", + "com.unity.modules.unitywebrequestwww": "1.0.0", + "com.unity.modules.vehicles": "1.0.0", + "com.unity.modules.video": "1.0.0", + "com.unity.modules.vr": "1.0.0", + "com.unity.modules.wind": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } +} diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json new file mode 100644 index 0000000..f53cd88 --- /dev/null +++ b/Packages/packages-lock.json @@ -0,0 +1,368 @@ +{ + "dependencies": { + "com.bywaystudios.resourceloader": { + "version": "file:com.bywaystudios.resourceloader", + "depth": 0, + "source": "embedded", + "dependencies": {} + }, + "com.unity.asset-store-validation": { + "version": "0.6.0", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.nuget.newtonsoft-json": "2.0.2" + }, + "url": "https://packages.unity.com" + }, + "com.unity.editorcoroutines": { + "version": "1.0.0", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.ext.nunit": { + "version": "1.0.6", + "depth": 2, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.feature.development": { + "version": "1.0.1", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.ide.visualstudio": "2.0.22", + "com.unity.ide.rider": "3.0.36", + "com.unity.ide.vscode": "1.2.5", + "com.unity.editorcoroutines": "1.0.0", + "com.unity.performance.profile-analyzer": "1.2.3", + "com.unity.test-framework": "1.1.33", + "com.unity.testtools.codecoverage": "1.2.6" + } + }, + "com.unity.ide.rider": { + "version": "3.0.36", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.ext.nunit": "1.0.6" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ide.visualstudio": { + "version": "2.0.22", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.1.9" + }, + "url": "https://packages.unity.com" + }, + "com.unity.ide.vscode": { + "version": "1.2.5", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.nuget.newtonsoft-json": { + "version": "3.2.1", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.performance.profile-analyzer": { + "version": "1.2.3", + "depth": 1, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.settings-manager": { + "version": "2.1.0", + "depth": 2, + "source": "registry", + "dependencies": {}, + "url": "https://packages.unity.com" + }, + "com.unity.test-framework": { + "version": "1.1.33", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.ext.nunit": "1.0.6", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + }, + "url": "https://packages.unity.com" + }, + "com.unity.testtools.codecoverage": { + "version": "1.2.6", + "depth": 1, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.0.16", + "com.unity.settings-manager": "1.0.1" + }, + "url": "https://packages.unity.com" + }, + "com.unity.upm.develop": { + "version": "0.5.3-exp.1", + "depth": 0, + "source": "registry", + "dependencies": { + "com.unity.test-framework": "1.1.20", + "com.unity.nuget.newtonsoft-json": "2.0.2", + "com.unity.asset-store-validation": "0.1.3" + }, + "url": "https://packages.unity.com" + }, + "com.unity.modules.ai": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.androidjni": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.animation": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.assetbundle": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.audio": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.cloth": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + } + }, + "com.unity.modules.director": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.animation": "1.0.0" + } + }, + "com.unity.modules.imageconversion": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.imgui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.jsonserialize": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.particlesystem": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.physics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.physics2d": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.screencapture": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.subsystems": { + "version": "1.0.0", + "depth": 1, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.terrain": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.terrainphysics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.terrain": "1.0.0" + } + }, + "com.unity.modules.tilemap": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics2d": "1.0.0" + } + }, + "com.unity.modules.ui": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.uielements": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.imgui": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.umbra": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unityanalytics": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0" + } + }, + "com.unity.modules.unitywebrequest": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.unitywebrequestassetbundle": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } + }, + "com.unity.modules.unitywebrequestaudio": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.audio": "1.0.0" + } + }, + "com.unity.modules.unitywebrequesttexture": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.unitywebrequestwww": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.unitywebrequest": "1.0.0", + "com.unity.modules.unitywebrequestassetbundle": "1.0.0", + "com.unity.modules.unitywebrequestaudio": "1.0.0", + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.assetbundle": "1.0.0", + "com.unity.modules.imageconversion": "1.0.0" + } + }, + "com.unity.modules.vehicles": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0" + } + }, + "com.unity.modules.video": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.audio": "1.0.0", + "com.unity.modules.ui": "1.0.0", + "com.unity.modules.unitywebrequest": "1.0.0" + } + }, + "com.unity.modules.vr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.xr": "1.0.0" + } + }, + "com.unity.modules.wind": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": {} + }, + "com.unity.modules.xr": { + "version": "1.0.0", + "depth": 0, + "source": "builtin", + "dependencies": { + "com.unity.modules.physics": "1.0.0", + "com.unity.modules.jsonserialize": "1.0.0", + "com.unity.modules.subsystems": "1.0.0" + } + } + } +} diff --git a/ProjectSettings/AudioManager.asset b/ProjectSettings/AudioManager.asset new file mode 100644 index 0000000..07ebfb0 --- /dev/null +++ b/ProjectSettings/AudioManager.asset @@ -0,0 +1,19 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!11 &1 +AudioManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Volume: 1 + Rolloff Scale: 1 + Doppler Factor: 1 + Default Speaker Mode: 2 + m_SampleRate: 0 + m_DSPBufferSize: 1024 + m_VirtualVoiceCount: 512 + m_RealVoiceCount: 32 + m_SpatializerPlugin: + m_AmbisonicDecoderPlugin: + m_DisableAudio: 0 + m_VirtualizeEffects: 1 + m_RequestedDSPBufferSize: 1024 diff --git a/ProjectSettings/ClusterInputManager.asset b/ProjectSettings/ClusterInputManager.asset new file mode 100644 index 0000000..e7886b2 --- /dev/null +++ b/ProjectSettings/ClusterInputManager.asset @@ -0,0 +1,6 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!236 &1 +ClusterInputManager: + m_ObjectHideFlags: 0 + m_Inputs: [] diff --git a/ProjectSettings/DynamicsManager.asset b/ProjectSettings/DynamicsManager.asset new file mode 100644 index 0000000..cdc1f3e --- /dev/null +++ b/ProjectSettings/DynamicsManager.asset @@ -0,0 +1,34 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!55 &1 +PhysicsManager: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_Gravity: {x: 0, y: -9.81, z: 0} + m_DefaultMaterial: {fileID: 0} + m_BounceThreshold: 2 + m_SleepThreshold: 0.005 + m_DefaultContactOffset: 0.01 + m_DefaultSolverIterations: 6 + m_DefaultSolverVelocityIterations: 1 + m_QueriesHitBackfaces: 0 + m_QueriesHitTriggers: 1 + m_EnableAdaptiveForce: 0 + m_ClothInterCollisionDistance: 0 + m_ClothInterCollisionStiffness: 0 + m_ContactsGeneration: 1 + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff + m_AutoSimulation: 1 + m_AutoSyncTransforms: 0 + m_ReuseCollisionCallbacks: 1 + m_ClothInterCollisionSettingsToggle: 0 + m_ContactPairsMode: 0 + m_BroadphaseType: 0 + m_WorldBounds: + m_Center: {x: 0, y: 0, z: 0} + m_Extent: {x: 250, y: 250, z: 250} + m_WorldSubdivisions: 8 + m_FrictionType: 0 + m_EnableEnhancedDeterminism: 0 + m_EnableUnifiedHeightmaps: 1 + m_DefaultMaxAngluarSpeed: 7 diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset new file mode 100644 index 0000000..0147887 --- /dev/null +++ b/ProjectSettings/EditorBuildSettings.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1045 &1 +EditorBuildSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Scenes: [] + m_configObjects: {} diff --git a/ProjectSettings/EditorSettings.asset b/ProjectSettings/EditorSettings.asset new file mode 100644 index 0000000..1e44a0a --- /dev/null +++ b/ProjectSettings/EditorSettings.asset @@ -0,0 +1,30 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!159 &1 +EditorSettings: + m_ObjectHideFlags: 0 + serializedVersion: 11 + m_ExternalVersionControlSupport: Visible Meta Files + m_SerializationMode: 2 + m_LineEndingsForNewScripts: 0 + m_DefaultBehaviorMode: 0 + m_PrefabRegularEnvironment: {fileID: 0} + m_PrefabUIEnvironment: {fileID: 0} + m_SpritePackerMode: 0 + m_SpritePackerPaddingPower: 1 + m_EtcTextureCompressorBehavior: 1 + m_EtcTextureFastCompressor: 1 + m_EtcTextureNormalCompressor: 2 + m_EtcTextureBestCompressor: 4 + m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp;asmref + m_ProjectGenerationRootNamespace: + m_CollabEditorSettings: + inProgressEnabled: 1 + m_EnableTextureStreamingInEditMode: 1 + m_EnableTextureStreamingInPlayMode: 1 + m_AsyncShaderCompilation: 1 + m_EnterPlayModeOptionsEnabled: 0 + m_EnterPlayModeOptions: 3 + m_ShowLightmapResolutionOverlay: 1 + m_UseLegacyProbeSampleCount: 0 + m_SerializeInlineMappingsOnOneLine: 1 diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset new file mode 100644 index 0000000..43369e3 --- /dev/null +++ b/ProjectSettings/GraphicsSettings.asset @@ -0,0 +1,63 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!30 &1 +GraphicsSettings: + m_ObjectHideFlags: 0 + serializedVersion: 13 + m_Deferred: + m_Mode: 1 + m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} + m_DeferredReflections: + m_Mode: 1 + m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} + m_ScreenSpaceShadows: + m_Mode: 1 + m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} + m_LegacyDeferred: + m_Mode: 1 + m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} + m_DepthNormals: + m_Mode: 1 + m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} + m_MotionVectors: + m_Mode: 1 + m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} + m_LightHalo: + m_Mode: 1 + m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} + m_LensFlare: + m_Mode: 1 + m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} + m_AlwaysIncludedShaders: + - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} + m_PreloadedShaders: [] + m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, + type: 0} + m_CustomRenderPipeline: {fileID: 0} + m_TransparencySortMode: 0 + m_TransparencySortAxis: {x: 0, y: 0, z: 1} + m_DefaultRenderingPath: 1 + m_DefaultMobileRenderingPath: 1 + m_TierSettings: [] + m_LightmapStripping: 0 + m_FogStripping: 0 + m_InstancingStripping: 0 + m_LightmapKeepPlain: 1 + m_LightmapKeepDirCombined: 1 + m_LightmapKeepDynamicPlain: 1 + m_LightmapKeepDynamicDirCombined: 1 + m_LightmapKeepShadowMask: 1 + m_LightmapKeepSubtractive: 1 + m_FogKeepLinear: 1 + m_FogKeepExp: 1 + m_FogKeepExp2: 1 + m_AlbedoSwatchInfos: [] + m_LightsUseLinearIntensity: 0 + m_LightsUseColorTemperature: 0 + m_LogWhenShaderIsCompiled: 0 + m_AllowEnlightenSupportForUpgradedProject: 0 diff --git a/ProjectSettings/InputManager.asset b/ProjectSettings/InputManager.asset new file mode 100644 index 0000000..17c8f53 --- /dev/null +++ b/ProjectSettings/InputManager.asset @@ -0,0 +1,295 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!13 &1 +InputManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Axes: + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: left + positiveButton: right + altNegativeButton: a + altPositiveButton: d + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: down + positiveButton: up + altNegativeButton: s + altPositiveButton: w + gravity: 3 + dead: 0.001 + sensitivity: 3 + snap: 1 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left ctrl + altNegativeButton: + altPositiveButton: mouse 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left alt + altNegativeButton: + altPositiveButton: mouse 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: left shift + altNegativeButton: + altPositiveButton: mouse 2 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: space + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse X + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse Y + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Mouse ScrollWheel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0 + sensitivity: 0.1 + snap: 0 + invert: 0 + type: 1 + axis: 2 + joyNum: 0 + - serializedVersion: 3 + m_Name: Horizontal + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 0 + type: 2 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Vertical + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: + altNegativeButton: + altPositiveButton: + gravity: 0 + dead: 0.19 + sensitivity: 1 + snap: 0 + invert: 1 + type: 2 + axis: 1 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire1 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 0 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire2 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 1 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Fire3 + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 2 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Jump + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: joystick button 3 + altNegativeButton: + altPositiveButton: + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: return + altNegativeButton: + altPositiveButton: joystick button 0 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Submit + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: enter + altNegativeButton: + altPositiveButton: space + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 + - serializedVersion: 3 + m_Name: Cancel + descriptiveName: + descriptiveNegativeName: + negativeButton: + positiveButton: escape + altNegativeButton: + altPositiveButton: joystick button 1 + gravity: 1000 + dead: 0.001 + sensitivity: 1000 + snap: 0 + invert: 0 + type: 0 + axis: 0 + joyNum: 0 diff --git a/ProjectSettings/MemorySettings.asset b/ProjectSettings/MemorySettings.asset new file mode 100644 index 0000000..5b5face --- /dev/null +++ b/ProjectSettings/MemorySettings.asset @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!387306366 &1 +MemorySettings: + m_ObjectHideFlags: 0 + m_EditorMemorySettings: + m_MainAllocatorBlockSize: -1 + m_ThreadAllocatorBlockSize: -1 + m_MainGfxBlockSize: -1 + m_ThreadGfxBlockSize: -1 + m_CacheBlockSize: -1 + m_TypetreeBlockSize: -1 + m_ProfilerBlockSize: -1 + m_ProfilerEditorBlockSize: -1 + m_BucketAllocatorGranularity: -1 + m_BucketAllocatorBucketsCount: -1 + m_BucketAllocatorBlockSize: -1 + m_BucketAllocatorBlockCount: -1 + m_ProfilerBucketAllocatorGranularity: -1 + m_ProfilerBucketAllocatorBucketsCount: -1 + m_ProfilerBucketAllocatorBlockSize: -1 + m_ProfilerBucketAllocatorBlockCount: -1 + m_TempAllocatorSizeMain: -1 + m_JobTempAllocatorBlockSize: -1 + m_BackgroundJobTempAllocatorBlockSize: -1 + m_JobTempAllocatorReducedBlockSize: -1 + m_TempAllocatorSizeGIBakingWorker: -1 + m_TempAllocatorSizeNavMeshWorker: -1 + m_TempAllocatorSizeAudioWorker: -1 + m_TempAllocatorSizeCloudWorker: -1 + m_TempAllocatorSizeGfx: -1 + m_TempAllocatorSizeJobWorker: -1 + m_TempAllocatorSizeBackgroundWorker: -1 + m_TempAllocatorSizePreloadManager: -1 + m_PlatformMemorySettings: {} diff --git a/ProjectSettings/NavMeshAreas.asset b/ProjectSettings/NavMeshAreas.asset new file mode 100644 index 0000000..3b0b7c3 --- /dev/null +++ b/ProjectSettings/NavMeshAreas.asset @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!126 &1 +NavMeshProjectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + areas: + - name: Walkable + cost: 1 + - name: Not Walkable + cost: 1 + - name: Jump + cost: 2 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + - name: + cost: 1 + m_LastAgentTypeID: -887442657 + m_Settings: + - serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.75 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + debug: + m_Flags: 0 + m_SettingNames: + - Humanoid diff --git a/ProjectSettings/PackageManagerSettings.asset b/ProjectSettings/PackageManagerSettings.asset new file mode 100644 index 0000000..112a053 --- /dev/null +++ b/ProjectSettings/PackageManagerSettings.asset @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 61 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_EnablePreReleasePackages: 0 + m_EnablePackageDependencies: 0 + m_AdvancedSettingsExpanded: 1 + m_ScopedRegistriesSettingsExpanded: 1 + m_SeeAllPackageVersions: 0 + oneTimeWarningShown: 0 + m_Registries: + - m_Id: main + m_Name: + m_Url: https://packages.unity.com + m_Scopes: [] + m_IsDefault: 1 + m_Capabilities: 7 + m_UserSelectedRegistryName: + m_UserAddingNewScopedRegistry: 0 + m_RegistryInfoDraft: + m_Modified: 0 + m_ErrorMessage: + m_UserModificationsInstanceId: -830 + m_OriginalInstanceId: -832 + m_LoadAssets: 0 diff --git a/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json new file mode 100644 index 0000000..3c7b4c1 --- /dev/null +++ b/ProjectSettings/Packages/com.unity.testtools.codecoverage/Settings.json @@ -0,0 +1,5 @@ +{ + "m_Dictionary": { + "m_DictionaryValues": [] + } +} \ No newline at end of file diff --git a/ProjectSettings/Physics2DSettings.asset b/ProjectSettings/Physics2DSettings.asset new file mode 100644 index 0000000..47880b1 --- /dev/null +++ b/ProjectSettings/Physics2DSettings.asset @@ -0,0 +1,56 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!19 &1 +Physics2DSettings: + m_ObjectHideFlags: 0 + serializedVersion: 4 + m_Gravity: {x: 0, y: -9.81} + m_DefaultMaterial: {fileID: 0} + m_VelocityIterations: 8 + m_PositionIterations: 3 + m_VelocityThreshold: 1 + m_MaxLinearCorrection: 0.2 + m_MaxAngularCorrection: 8 + m_MaxTranslationSpeed: 100 + m_MaxRotationSpeed: 360 + m_BaumgarteScale: 0.2 + m_BaumgarteTimeOfImpactScale: 0.75 + m_TimeToSleep: 0.5 + m_LinearSleepTolerance: 0.01 + m_AngularSleepTolerance: 2 + m_DefaultContactOffset: 0.01 + m_JobOptions: + serializedVersion: 2 + useMultithreading: 0 + useConsistencySorting: 0 + m_InterpolationPosesPerJob: 100 + m_NewContactsPerJob: 30 + m_CollideContactsPerJob: 100 + m_ClearFlagsPerJob: 200 + m_ClearBodyForcesPerJob: 200 + m_SyncDiscreteFixturesPerJob: 50 + m_SyncContinuousFixturesPerJob: 50 + m_FindNearestContactsPerJob: 100 + m_UpdateTriggerContactsPerJob: 100 + m_IslandSolverCostThreshold: 100 + m_IslandSolverBodyCostScale: 1 + m_IslandSolverContactCostScale: 10 + m_IslandSolverJointCostScale: 10 + m_IslandSolverBodiesPerJob: 50 + m_IslandSolverContactsPerJob: 50 + m_AutoSimulation: 1 + m_QueriesHitTriggers: 1 + m_QueriesStartInColliders: 1 + m_CallbacksOnDisable: 1 + m_ReuseCollisionCallbacks: 1 + m_AutoSyncTransforms: 0 + m_AlwaysShowColliders: 0 + m_ShowColliderSleep: 1 + m_ShowColliderContacts: 0 + m_ShowColliderAABB: 0 + m_ContactArrowScale: 0.2 + m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} + m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} + m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} + m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} + m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff diff --git a/ProjectSettings/PresetManager.asset b/ProjectSettings/PresetManager.asset new file mode 100644 index 0000000..67a94da --- /dev/null +++ b/ProjectSettings/PresetManager.asset @@ -0,0 +1,7 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1386491679 &1 +PresetManager: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_DefaultPresets: {} diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset new file mode 100644 index 0000000..aca1400 --- /dev/null +++ b/ProjectSettings/ProjectSettings.asset @@ -0,0 +1,864 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!129 &1 +PlayerSettings: + m_ObjectHideFlags: 0 + serializedVersion: 26 + productGUID: 2d3c6e7a81db8c14f8d725a38940fe89 + AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 + defaultScreenOrientation: 4 + targetDevice: 2 + useOnDemandResources: 0 + accelerometerFrequency: 60 + companyName: DefaultCompany + productName: ResourceLoaderPackage + defaultCursor: {fileID: 0} + cursorHotspot: {x: 0, y: 0} + m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} + m_ShowUnitySplashScreen: 1 + m_ShowUnitySplashLogo: 1 + m_SplashScreenOverlayOpacity: 1 + m_SplashScreenAnimation: 1 + m_SplashScreenLogoStyle: 1 + m_SplashScreenDrawMode: 0 + m_SplashScreenBackgroundAnimationZoom: 1 + m_SplashScreenLogoAnimationZoom: 1 + m_SplashScreenBackgroundLandscapeAspect: 1 + m_SplashScreenBackgroundPortraitAspect: 1 + m_SplashScreenBackgroundLandscapeUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenBackgroundPortraitUvs: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + m_SplashScreenLogos: [] + m_VirtualRealitySplashScreen: {fileID: 0} + m_HolographicTrackingLossScreen: {fileID: 0} + defaultScreenWidth: 1920 + defaultScreenHeight: 1080 + defaultScreenWidthWeb: 960 + defaultScreenHeightWeb: 600 + m_StereoRenderingPath: 0 + m_ActiveColorSpace: 1 + unsupportedMSAAFallback: 0 + m_SpriteBatchVertexThreshold: 300 + m_MTRendering: 1 + mipStripping: 0 + numberOfMipsStripped: 0 + numberOfMipsStrippedPerMipmapLimitGroup: {} + m_StackTraceTypes: 010000000100000001000000010000000100000001000000 + iosShowActivityIndicatorOnLoading: -1 + androidShowActivityIndicatorOnLoading: -1 + iosUseCustomAppBackgroundBehavior: 0 + allowedAutorotateToPortrait: 1 + allowedAutorotateToPortraitUpsideDown: 1 + allowedAutorotateToLandscapeRight: 1 + allowedAutorotateToLandscapeLeft: 1 + useOSAutorotation: 1 + use32BitDisplayBuffer: 1 + preserveFramebufferAlpha: 0 + disableDepthAndStencilBuffers: 0 + androidStartInFullscreen: 1 + androidRenderOutsideSafeArea: 1 + androidUseSwappy: 1 + androidBlitType: 0 + androidResizableWindow: 0 + androidDefaultWindowWidth: 1920 + androidDefaultWindowHeight: 1080 + androidMinimumWindowWidth: 400 + androidMinimumWindowHeight: 300 + androidFullscreenMode: 1 + androidAutoRotationBehavior: 1 + androidPredictiveBackSupport: 1 + defaultIsNativeResolution: 1 + macRetinaSupport: 1 + runInBackground: 1 + captureSingleScreen: 0 + muteOtherAudioSources: 0 + Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + audioSpatialExperience: 0 + deferSystemGesturesMode: 0 + hideHomeButton: 0 + submitAnalytics: 1 + usePlayerLog: 1 + dedicatedServerOptimizations: 0 + bakeCollisionMeshes: 0 + forceSingleInstance: 0 + useFlipModelSwapchain: 1 + resizableWindow: 0 + useMacAppStoreValidation: 0 + macAppStoreCategory: public.app-category.games + gpuSkinning: 1 + xboxPIXTextureCapture: 0 + xboxEnableAvatar: 0 + xboxEnableKinect: 0 + xboxEnableKinectAutoTracking: 0 + xboxEnableFitness: 0 + visibleInBackground: 1 + allowFullscreenSwitch: 1 + fullscreenMode: 1 + xboxSpeechDB: 0 + xboxEnableHeadOrientation: 0 + xboxEnableGuest: 0 + xboxEnablePIXSampling: 0 + metalFramebufferOnly: 0 + xboxOneResolution: 0 + xboxOneSResolution: 0 + xboxOneXResolution: 3 + xboxOneMonoLoggingLevel: 0 + xboxOneLoggingLevel: 1 + xboxOneDisableEsram: 0 + xboxOneEnableTypeOptimization: 0 + xboxOnePresentImmediateThreshold: 0 + switchQueueCommandMemory: 0 + switchQueueControlMemory: 16384 + switchQueueComputeMemory: 262144 + switchNVNShaderPoolsGranularity: 33554432 + switchNVNDefaultPoolsGranularity: 16777216 + switchNVNOtherPoolsGranularity: 16777216 + switchGpuScratchPoolGranularity: 2097152 + switchAllowGpuScratchShrinking: 0 + switchNVNMaxPublicTextureIDCount: 0 + switchNVNMaxPublicSamplerIDCount: 0 + switchNVNGraphicsFirmwareMemory: 32 + switchMaxWorkerMultiple: 8 + stadiaPresentMode: 0 + stadiaTargetFramerate: 0 + vulkanNumSwapchainBuffers: 3 + vulkanEnableSetSRGBWrite: 0 + vulkanEnablePreTransform: 1 + vulkanEnableLateAcquireNextImage: 0 + vulkanEnableCommandBufferRecycling: 1 + loadStoreDebugModeEnabled: 0 + visionOSBundleVersion: 1.0 + tvOSBundleVersion: 1.0 + bundleVersion: 0.1 + preloadedAssets: [] + metroInputSource: 0 + wsaTransparentSwapchain: 0 + m_HolographicPauseOnTrackingLoss: 1 + xboxOneDisableKinectGpuReservation: 1 + xboxOneEnable7thCore: 1 + vrSettings: + enable360StereoCapture: 0 + isWsaHolographicRemotingEnabled: 0 + enableFrameTimingStats: 0 + enableOpenGLProfilerGPURecorders: 1 + allowHDRDisplaySupport: 0 + useHDRDisplay: 0 + hdrBitDepth: 0 + m_ColorGamuts: 00000000 + targetPixelDensity: 30 + resolutionScalingMode: 0 + resetResolutionOnWindowResize: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.1 + applicationIdentifier: {} + buildNumber: + Standalone: 0 + VisionOS: 0 + iPhone: 0 + tvOS: 0 + overrideDefaultApplicationIdentifier: 0 + AndroidBundleVersionCode: 1 + AndroidMinSdkVersion: 22 + AndroidTargetSdkVersion: 0 + AndroidPreferredInstallLocation: 1 + aotOptions: + stripEngineCode: 1 + iPhoneStrippingLevel: 0 + iPhoneScriptCallOptimization: 0 + ForceInternetPermission: 0 + ForceSDCardPermission: 0 + CreateWallpaper: 0 + APKExpansionFiles: 0 + keepLoadedShadersAlive: 0 + StripUnusedMeshComponents: 1 + strictShaderVariantMatching: 0 + VertexChannelCompressionMask: 4054 + iPhoneSdkVersion: 988 + iOSSimulatorArchitecture: 0 + iOSTargetOSVersionString: 12.0 + tvOSSdkVersion: 0 + tvOSSimulatorArchitecture: 0 + tvOSRequireExtendedGameController: 0 + tvOSTargetOSVersionString: 12.0 + VisionOSSdkVersion: 0 + VisionOSTargetOSVersionString: 1.0 + uIPrerenderedIcon: 0 + uIRequiresPersistentWiFi: 0 + uIRequiresFullScreen: 1 + uIStatusBarHidden: 1 + uIExitOnSuspend: 0 + uIStatusBarStyle: 0 + appleTVSplashScreen: {fileID: 0} + appleTVSplashScreen2x: {fileID: 0} + tvOSSmallIconLayers: [] + tvOSSmallIconLayers2x: [] + tvOSLargeIconLayers: [] + tvOSLargeIconLayers2x: [] + tvOSTopShelfImageLayers: [] + tvOSTopShelfImageLayers2x: [] + tvOSTopShelfImageWideLayers: [] + tvOSTopShelfImageWideLayers2x: [] + iOSLaunchScreenType: 0 + iOSLaunchScreenPortrait: {fileID: 0} + iOSLaunchScreenLandscape: {fileID: 0} + iOSLaunchScreenBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreenFillPct: 100 + iOSLaunchScreenSize: 100 + iOSLaunchScreenCustomXibPath: + iOSLaunchScreeniPadType: 0 + iOSLaunchScreeniPadImage: {fileID: 0} + iOSLaunchScreeniPadBackgroundColor: + serializedVersion: 2 + rgba: 0 + iOSLaunchScreeniPadFillPct: 100 + iOSLaunchScreeniPadSize: 100 + iOSLaunchScreeniPadCustomXibPath: + iOSLaunchScreenCustomStoryboardPath: + iOSLaunchScreeniPadCustomStoryboardPath: + iOSDeviceRequirements: [] + iOSURLSchemes: [] + macOSURLSchemes: [] + iOSBackgroundModes: 0 + iOSMetalForceHardShadows: 0 + metalEditorSupport: 1 + metalAPIValidation: 1 + metalCompileShaderBinary: 0 + iOSRenderExtraFrameOnPause: 0 + iosCopyPluginsCodeInsteadOfSymlink: 0 + appleDeveloperTeamID: + iOSManualSigningProvisioningProfileID: + tvOSManualSigningProvisioningProfileID: + VisionOSManualSigningProvisioningProfileID: + iOSManualSigningProvisioningProfileType: 0 + tvOSManualSigningProvisioningProfileType: 0 + VisionOSManualSigningProvisioningProfileType: 0 + appleEnableAutomaticSigning: 0 + iOSRequireARKit: 0 + iOSAutomaticallyDetectAndAddCapabilities: 1 + appleEnableProMotion: 0 + shaderPrecisionModel: 0 + clonedFromGUID: c0afd0d1d80e3634a9dac47e8a0426ea + templatePackageId: com.unity.template.3d@8.1.3 + templateDefaultScene: Assets/Scenes/SampleScene.unity + useCustomMainManifest: 0 + useCustomLauncherManifest: 0 + useCustomMainGradleTemplate: 0 + useCustomLauncherGradleManifest: 0 + useCustomBaseGradleTemplate: 0 + useCustomGradlePropertiesTemplate: 0 + useCustomGradleSettingsTemplate: 0 + useCustomProguardFile: 0 + AndroidTargetArchitectures: 1 + AndroidTargetDevices: 0 + AndroidSplashScreenScale: 0 + androidSplashScreen: {fileID: 0} + AndroidKeystoreName: + AndroidKeyaliasName: + AndroidEnableArmv9SecurityFeatures: 0 + AndroidBuildApkPerCpuArchitecture: 0 + AndroidTVCompatibility: 0 + AndroidIsGame: 1 + AndroidEnableTango: 0 + androidEnableBanner: 1 + androidUseLowAccuracyLocation: 0 + androidUseCustomKeystore: 0 + m_AndroidBanners: + - width: 320 + height: 180 + banner: {fileID: 0} + androidGamepadSupportLevel: 0 + chromeosInputEmulation: 1 + AndroidMinifyRelease: 0 + AndroidMinifyDebug: 0 + AndroidValidateAppBundleSize: 1 + AndroidAppBundleSizeToValidate: 150 + m_BuildTargetIcons: [] + m_BuildTargetPlatformIcons: + - m_BuildTarget: Android + m_Icons: + - m_Textures: [] + m_Width: 432 + m_Height: 432 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 324 + m_Height: 324 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 216 + m_Height: 216 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 162 + m_Height: 162 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 108 + m_Height: 108 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 81 + m_Height: 81 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 0 + m_SubKind: + m_BuildTargetBatching: + - m_BuildTarget: Standalone + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: tvOS + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: Android + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: iPhone + m_StaticBatching: 1 + m_DynamicBatching: 0 + - m_BuildTarget: WebGL + m_StaticBatching: 0 + m_DynamicBatching: 0 + m_BuildTargetShaderSettings: [] + m_BuildTargetGraphicsJobs: + - m_BuildTarget: MacStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: Switch + m_GraphicsJobs: 1 + - m_BuildTarget: MetroSupport + m_GraphicsJobs: 1 + - m_BuildTarget: AppleTVSupport + m_GraphicsJobs: 0 + - m_BuildTarget: BJMSupport + m_GraphicsJobs: 1 + - m_BuildTarget: LinuxStandaloneSupport + m_GraphicsJobs: 1 + - m_BuildTarget: PS4Player + m_GraphicsJobs: 1 + - m_BuildTarget: iOSSupport + m_GraphicsJobs: 0 + - m_BuildTarget: WindowsStandaloneSupport + m_GraphicsJobs: 1 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobs: 1 + - m_BuildTarget: LuminSupport + m_GraphicsJobs: 0 + - m_BuildTarget: AndroidPlayer + m_GraphicsJobs: 0 + - m_BuildTarget: WebGLSupport + m_GraphicsJobs: 0 + m_BuildTargetGraphicsJobMode: + - m_BuildTarget: PS4Player + m_GraphicsJobMode: 0 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobMode: 0 + m_BuildTargetGraphicsAPIs: + - m_BuildTarget: AndroidPlayer + m_APIs: 150000000b000000 + m_Automatic: 1 + - m_BuildTarget: iOSSupport + m_APIs: 10000000 + m_Automatic: 1 + - m_BuildTarget: AppleTVSupport + m_APIs: 10000000 + m_Automatic: 1 + - m_BuildTarget: WebGLSupport + m_APIs: 0b000000 + m_Automatic: 1 + m_BuildTargetVRSettings: + - m_BuildTarget: Standalone + m_Enabled: 0 + m_Devices: + - Oculus + - OpenVR + m_DefaultShaderChunkSizeInMB: 16 + m_DefaultShaderChunkCount: 0 + openGLRequireES31: 0 + openGLRequireES31AEP: 0 + openGLRequireES32: 0 + m_TemplateCustomTags: {} + mobileMTRendering: + Android: 1 + iPhone: 1 + tvOS: 1 + m_BuildTargetGroupLightmapEncodingQuality: + - m_BuildTarget: Android + m_EncodingQuality: 1 + - m_BuildTarget: iPhone + m_EncodingQuality: 1 + - m_BuildTarget: tvOS + m_EncodingQuality: 1 + m_BuildTargetGroupHDRCubemapEncodingQuality: + - m_BuildTarget: Android + m_EncodingQuality: 1 + - m_BuildTarget: iPhone + m_EncodingQuality: 1 + - m_BuildTarget: tvOS + m_EncodingQuality: 1 + m_BuildTargetGroupLightmapSettings: [] + m_BuildTargetGroupLoadStoreDebugModeSettings: [] + m_BuildTargetNormalMapEncoding: + - m_BuildTarget: Android + m_Encoding: 1 + - m_BuildTarget: iPhone + m_Encoding: 1 + - m_BuildTarget: tvOS + m_Encoding: 1 + m_BuildTargetDefaultTextureCompressionFormat: + - m_BuildTarget: Android + m_Format: 3 + playModeTestRunnerEnabled: 0 + runPlayModeTestAsEditModeTest: 0 + actionOnDotNetUnhandledException: 1 + enableInternalProfiler: 0 + logObjCUncaughtExceptions: 1 + enableCrashReportAPI: 0 + cameraUsageDescription: + locationUsageDescription: + microphoneUsageDescription: + bluetoothUsageDescription: + macOSTargetOSVersion: 10.13.0 + switchNMETAOverride: + switchNetLibKey: + switchSocketMemoryPoolSize: 6144 + switchSocketAllocatorPoolSize: 128 + switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 + switchUseCPUProfiler: 0 + switchEnableFileSystemTrace: 0 + switchLTOSetting: 0 + switchApplicationID: 0x01004b9000490000 + switchNSODependencies: + switchCompilerFlags: + switchTitleNames_0: + switchTitleNames_1: + switchTitleNames_2: + switchTitleNames_3: + switchTitleNames_4: + switchTitleNames_5: + switchTitleNames_6: + switchTitleNames_7: + switchTitleNames_8: + switchTitleNames_9: + switchTitleNames_10: + switchTitleNames_11: + switchTitleNames_12: + switchTitleNames_13: + switchTitleNames_14: + switchTitleNames_15: + switchPublisherNames_0: + switchPublisherNames_1: + switchPublisherNames_2: + switchPublisherNames_3: + switchPublisherNames_4: + switchPublisherNames_5: + switchPublisherNames_6: + switchPublisherNames_7: + switchPublisherNames_8: + switchPublisherNames_9: + switchPublisherNames_10: + switchPublisherNames_11: + switchPublisherNames_12: + switchPublisherNames_13: + switchPublisherNames_14: + switchPublisherNames_15: + switchIcons_0: {fileID: 0} + switchIcons_1: {fileID: 0} + switchIcons_2: {fileID: 0} + switchIcons_3: {fileID: 0} + switchIcons_4: {fileID: 0} + switchIcons_5: {fileID: 0} + switchIcons_6: {fileID: 0} + switchIcons_7: {fileID: 0} + switchIcons_8: {fileID: 0} + switchIcons_9: {fileID: 0} + switchIcons_10: {fileID: 0} + switchIcons_11: {fileID: 0} + switchIcons_12: {fileID: 0} + switchIcons_13: {fileID: 0} + switchIcons_14: {fileID: 0} + switchIcons_15: {fileID: 0} + switchSmallIcons_0: {fileID: 0} + switchSmallIcons_1: {fileID: 0} + switchSmallIcons_2: {fileID: 0} + switchSmallIcons_3: {fileID: 0} + switchSmallIcons_4: {fileID: 0} + switchSmallIcons_5: {fileID: 0} + switchSmallIcons_6: {fileID: 0} + switchSmallIcons_7: {fileID: 0} + switchSmallIcons_8: {fileID: 0} + switchSmallIcons_9: {fileID: 0} + switchSmallIcons_10: {fileID: 0} + switchSmallIcons_11: {fileID: 0} + switchSmallIcons_12: {fileID: 0} + switchSmallIcons_13: {fileID: 0} + switchSmallIcons_14: {fileID: 0} + switchSmallIcons_15: {fileID: 0} + switchManualHTML: + switchAccessibleURLs: + switchLegalInformation: + switchMainThreadStackSize: 1048576 + switchPresenceGroupId: + switchLogoHandling: 0 + switchReleaseVersion: 0 + switchDisplayVersion: 1.0.0 + switchStartupUserAccount: 0 + switchSupportedLanguagesMask: 0 + switchLogoType: 0 + switchApplicationErrorCodeCategory: + switchUserAccountSaveDataSize: 0 + switchUserAccountSaveDataJournalSize: 0 + switchApplicationAttribute: 0 + switchCardSpecSize: -1 + switchCardSpecClock: -1 + switchRatingsMask: 0 + switchRatingsInt_0: 0 + switchRatingsInt_1: 0 + switchRatingsInt_2: 0 + switchRatingsInt_3: 0 + switchRatingsInt_4: 0 + switchRatingsInt_5: 0 + switchRatingsInt_6: 0 + switchRatingsInt_7: 0 + switchRatingsInt_8: 0 + switchRatingsInt_9: 0 + switchRatingsInt_10: 0 + switchRatingsInt_11: 0 + switchRatingsInt_12: 0 + switchLocalCommunicationIds_0: + switchLocalCommunicationIds_1: + switchLocalCommunicationIds_2: + switchLocalCommunicationIds_3: + switchLocalCommunicationIds_4: + switchLocalCommunicationIds_5: + switchLocalCommunicationIds_6: + switchLocalCommunicationIds_7: + switchParentalControl: 0 + switchAllowsScreenshot: 1 + switchAllowsVideoCapturing: 1 + switchAllowsRuntimeAddOnContentInstall: 0 + switchDataLossConfirmation: 0 + switchUserAccountLockEnabled: 0 + switchSystemResourceMemory: 16777216 + switchSupportedNpadStyles: 22 + switchNativeFsCacheSize: 32 + switchIsHoldTypeHorizontal: 0 + switchSupportedNpadCount: 8 + switchEnableTouchScreen: 1 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchDisableHTCSPlayerConnection: 0 + switchUseNewStyleFilepaths: 1 + switchUseLegacyFmodPriorities: 0 + switchUseMicroSleepForYield: 1 + switchEnableRamDiskSupport: 0 + switchMicroSleepForYieldTime: 25 + switchRamDiskSpaceSize: 12 + ps4NPAgeRating: 12 + ps4NPTitleSecret: + ps4NPTrophyPackPath: + ps4ParentalLevel: 11 + ps4ContentID: ED1633-NPXX51362_00-0000000000000000 + ps4Category: 0 + ps4MasterVersion: 01.00 + ps4AppVersion: 01.00 + ps4AppType: 0 + ps4ParamSfxPath: + ps4VideoOutPixelFormat: 0 + ps4VideoOutInitialWidth: 1920 + ps4VideoOutBaseModeInitialWidth: 1920 + ps4VideoOutReprojectionRate: 60 + ps4PronunciationXMLPath: + ps4PronunciationSIGPath: + ps4BackgroundImagePath: + ps4StartupImagePath: + ps4StartupImagesFolder: + ps4IconImagesFolder: + ps4SaveDataImagePath: + ps4SdkOverride: + ps4BGMPath: + ps4ShareFilePath: + ps4ShareOverlayImagePath: + ps4PrivacyGuardImagePath: + ps4ExtraSceSysFile: + ps4NPtitleDatPath: + ps4RemotePlayKeyAssignment: -1 + ps4RemotePlayKeyMappingDir: + ps4PlayTogetherPlayerCount: 0 + ps4EnterButtonAssignment: 1 + ps4ApplicationParam1: 0 + ps4ApplicationParam2: 0 + ps4ApplicationParam3: 0 + ps4ApplicationParam4: 0 + ps4DownloadDataSize: 0 + ps4GarlicHeapSize: 2048 + ps4ProGarlicHeapSize: 2560 + playerPrefsMaxSize: 32768 + ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ + ps4pnSessions: 1 + ps4pnPresence: 1 + ps4pnFriends: 1 + ps4pnGameCustomData: 1 + playerPrefsSupport: 0 + enableApplicationExit: 0 + resetTempFolder: 1 + restrictedAudioUsageRights: 0 + ps4UseResolutionFallback: 0 + ps4ReprojectionSupport: 0 + ps4UseAudio3dBackend: 0 + ps4UseLowGarlicFragmentationMode: 1 + ps4SocialScreenEnabled: 0 + ps4ScriptOptimizationLevel: 0 + ps4Audio3dVirtualSpeakerCount: 14 + ps4attribCpuUsage: 0 + ps4PatchPkgPath: + ps4PatchLatestPkgPath: + ps4PatchChangeinfoPath: + ps4PatchDayOne: 0 + ps4attribUserManagement: 0 + ps4attribMoveSupport: 0 + ps4attrib3DSupport: 0 + ps4attribShareSupport: 0 + ps4attribExclusiveVR: 0 + ps4disableAutoHideSplash: 0 + ps4videoRecordingFeaturesUsed: 0 + ps4contentSearchFeaturesUsed: 0 + ps4CompatibilityPS5: 0 + ps4AllowPS5Detection: 0 + ps4GPU800MHz: 1 + ps4attribEyeToEyeDistanceSettingVR: 0 + ps4IncludedModules: [] + ps4attribVROutputEnabled: 0 + monoEnv: + splashScreenBackgroundSourceLandscape: {fileID: 0} + splashScreenBackgroundSourcePortrait: {fileID: 0} + blurSplashScreenBackground: 1 + spritePackerPolicy: + webGLMemorySize: 16 + webGLExceptionSupport: 1 + webGLNameFilesAsHashes: 0 + webGLShowDiagnostics: 0 + webGLDataCaching: 1 + webGLDebugSymbols: 0 + webGLEmscriptenArgs: + webGLModulesDirectory: + webGLTemplate: APPLICATION:Default + webGLAnalyzeBuildSize: 0 + webGLUseEmbeddedResources: 0 + webGLCompressionFormat: 1 + webGLWasmArithmeticExceptions: 0 + webGLLinkerTarget: 1 + webGLThreadsSupport: 0 + webGLDecompressionFallback: 0 + webGLInitialMemorySize: 32 + webGLMaximumMemorySize: 2048 + webGLMemoryGrowthMode: 2 + webGLMemoryLinearGrowthStep: 16 + webGLMemoryGeometricGrowthStep: 0.2 + webGLMemoryGeometricGrowthCap: 96 + webGLPowerPreference: 2 + scriptingDefineSymbols: {} + additionalCompilerArguments: {} + platformArchitecture: {} + scriptingBackend: {} + il2cppCompilerConfiguration: {} + il2cppCodeGeneration: {} + managedStrippingLevel: + EmbeddedLinux: 1 + GameCoreScarlett: 1 + GameCoreXboxOne: 1 + Nintendo Switch: 1 + PS4: 1 + PS5: 1 + QNX: 1 + Stadia: 1 + VisionOS: 1 + WebGL: 1 + Windows Store Apps: 1 + XboxOne: 1 + iPhone: 1 + tvOS: 1 + incrementalIl2cppBuild: {} + suppressCommonWarnings: 1 + allowUnsafeCode: 0 + useDeterministicCompilation: 1 + additionalIl2CppArgs: + scriptingRuntimeVersion: 1 + gcIncremental: 1 + gcWBarrierValidation: 0 + apiCompatibilityLevelPerPlatform: {} + m_RenderingPath: 1 + m_MobileRenderingPath: 1 + metroPackageName: ResourceLoaderPackage + metroPackageVersion: + metroCertificatePath: + metroCertificatePassword: + metroCertificateSubject: + metroCertificateIssuer: + metroCertificateNotAfter: 0000000000000000 + metroApplicationDescription: ResourceLoaderPackage + wsaImages: {} + metroTileShortName: + metroTileShowName: 0 + metroMediumTileShowName: 0 + metroLargeTileShowName: 0 + metroWideTileShowName: 0 + metroSupportStreamingInstall: 0 + metroLastRequiredScene: 0 + metroDefaultTileSize: 1 + metroTileForegroundText: 2 + metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} + metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, a: 1} + metroSplashScreenUseBackgroundColor: 0 + syncCapabilities: 0 + platformCapabilities: {} + metroTargetDeviceFamilies: {} + metroFTAName: + metroFTAFileTypes: [] + metroProtocolName: + vcxProjDefaultLanguage: + XboxOneProductId: + XboxOneUpdateKey: + XboxOneSandboxId: + XboxOneContentId: + XboxOneTitleId: + XboxOneSCId: + XboxOneGameOsOverridePath: + XboxOnePackagingOverridePath: + XboxOneAppManifestOverridePath: + XboxOneVersion: 1.0.0.0 + XboxOnePackageEncryption: 0 + XboxOnePackageUpdateGranularity: 2 + XboxOneDescription: + XboxOneLanguage: + - enus + XboxOneCapability: [] + XboxOneGameRating: {} + XboxOneIsContentPackage: 0 + XboxOneEnhancedXboxCompatibilityMode: 0 + XboxOneEnableGPUVariability: 1 + XboxOneSockets: {} + XboxOneSplashScreen: {fileID: 0} + XboxOneAllowedProductIds: [] + XboxOnePersistentLocalStorageSize: 0 + XboxOneXTitleMemory: 8 + XboxOneOverrideIdentityName: + XboxOneOverrideIdentityPublisher: + vrEditorSettings: {} + cloudServicesEnabled: + UNet: 1 + luminIcon: + m_Name: + m_ModelFolderPath: + m_PortalFolderPath: + luminCert: + m_CertPath: + m_SignPackage: 1 + luminIsChannelApp: 0 + luminVersion: + m_VersionCode: 1 + m_VersionName: + hmiPlayerDataPath: + hmiForceSRGBBlit: 1 + embeddedLinuxEnableGamepadInput: 1 + hmiLogStartupTiming: 0 + hmiCpuConfiguration: + apiCompatibilityLevel: 6 + activeInputHandler: 0 + windowsGamepadBackendHint: 0 + cloudProjectId: + framebufferDepthMemorylessMode: 0 + qualitySettingsNames: [] + projectName: + organizationId: + cloudEnabled: 0 + legacyClampBlendShapeWeights: 0 + hmiLoadingImage: {fileID: 0} + platformRequiresReadableAssets: 0 + virtualTexturingSupportEnabled: 0 + insecureHttpOption: 0 diff --git a/ProjectSettings/ProjectVersion.txt b/ProjectSettings/ProjectVersion.txt new file mode 100644 index 0000000..587f809 --- /dev/null +++ b/ProjectSettings/ProjectVersion.txt @@ -0,0 +1,2 @@ +m_EditorVersion: 2022.3.62f3 +m_EditorVersionWithRevision: 2022.3.62f3 (96770f904ca7) diff --git a/ProjectSettings/QualitySettings.asset b/ProjectSettings/QualitySettings.asset new file mode 100644 index 0000000..36c0dad --- /dev/null +++ b/ProjectSettings/QualitySettings.asset @@ -0,0 +1,234 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!47 &1 +QualitySettings: + m_ObjectHideFlags: 0 + serializedVersion: 5 + m_CurrentQuality: 5 + m_QualitySettings: + - serializedVersion: 2 + name: Very Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 15 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 1 + textureQuality: 1 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.3 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 4 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Low + pixelLightCount: 0 + shadows: 0 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 0 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 0 + lodBias: 0.4 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 16 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Medium + pixelLightCount: 1 + shadows: 1 + shadowResolution: 0 + shadowProjection: 1 + shadowCascades: 1 + shadowDistance: 20 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 0 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 0 + realtimeReflectionProbes: 0 + billboardsFaceCameraPosition: 0 + vSyncCount: 1 + lodBias: 0.7 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 64 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: High + pixelLightCount: 2 + shadows: 2 + shadowResolution: 1 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 40 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 2 + textureQuality: 0 + anisotropicTextures: 1 + antiAliasing: 0 + softParticles: 0 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 256 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Very High + pixelLightCount: 3 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 2 + shadowDistance: 70 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 1.5 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 1024 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + - serializedVersion: 2 + name: Ultra + pixelLightCount: 4 + shadows: 2 + shadowResolution: 2 + shadowProjection: 1 + shadowCascades: 4 + shadowDistance: 150 + shadowNearPlaneOffset: 3 + shadowCascade2Split: 0.33333334 + shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} + shadowmaskMode: 1 + blendWeights: 4 + textureQuality: 0 + anisotropicTextures: 2 + antiAliasing: 2 + softParticles: 1 + softVegetation: 1 + realtimeReflectionProbes: 1 + billboardsFaceCameraPosition: 1 + vSyncCount: 1 + lodBias: 2 + maximumLODLevel: 0 + streamingMipmapsActive: 0 + streamingMipmapsAddAllCameras: 1 + streamingMipmapsMemoryBudget: 512 + streamingMipmapsRenderersPerFrame: 512 + streamingMipmapsMaxLevelReduction: 2 + streamingMipmapsMaxFileIORequests: 1024 + particleRaycastBudget: 4096 + asyncUploadTimeSlice: 2 + asyncUploadBufferSize: 16 + asyncUploadPersistentBuffer: 1 + resolutionScalingFixedDPIFactor: 1 + excludedTargetPlatforms: [] + m_PerPlatformDefaultQuality: + Android: 2 + Lumin: 5 + GameCoreScarlett: 5 + GameCoreXboxOne: 5 + Nintendo 3DS: 5 + Nintendo Switch: 5 + PS4: 5 + PS5: 5 + Stadia: 5 + Standalone: 5 + WebGL: 3 + Windows Store Apps: 5 + XboxOne: 5 + iPhone: 2 + tvOS: 2 diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset new file mode 100644 index 0000000..1c92a78 --- /dev/null +++ b/ProjectSettings/TagManager.asset @@ -0,0 +1,43 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!78 &1 +TagManager: + serializedVersion: 2 + tags: [] + layers: + - Default + - TransparentFX + - Ignore Raycast + - + - Water + - UI + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + m_SortingLayers: + - name: Default + uniqueID: 0 + locked: 0 diff --git a/ProjectSettings/TimeManager.asset b/ProjectSettings/TimeManager.asset new file mode 100644 index 0000000..558a017 --- /dev/null +++ b/ProjectSettings/TimeManager.asset @@ -0,0 +1,9 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!5 &1 +TimeManager: + m_ObjectHideFlags: 0 + Fixed Timestep: 0.02 + Maximum Allowed Timestep: 0.33333334 + m_TimeScale: 1 + Maximum Particle Timestep: 0.03 diff --git a/ProjectSettings/UnityConnectSettings.asset b/ProjectSettings/UnityConnectSettings.asset new file mode 100644 index 0000000..a88bee0 --- /dev/null +++ b/ProjectSettings/UnityConnectSettings.asset @@ -0,0 +1,36 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!310 &1 +UnityConnectSettings: + m_ObjectHideFlags: 0 + serializedVersion: 1 + m_Enabled: 0 + m_TestMode: 0 + m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events + m_EventUrl: https://cdp.cloud.unity3d.com/v1/events + m_ConfigUrl: https://config.uca.cloud.unity3d.com + m_DashboardUrl: https://dashboard.unity3d.com + m_TestInitMode: 0 + CrashReportingSettings: + m_EventUrl: https://perf-events.cloud.unity3d.com + m_Enabled: 0 + m_LogBufferSize: 10 + m_CaptureEditorExceptions: 1 + UnityPurchasingSettings: + m_Enabled: 0 + m_TestMode: 0 + UnityAnalyticsSettings: + m_Enabled: 0 + m_TestMode: 0 + m_InitializeOnStartup: 1 + m_PackageRequiringCoreStatsPresent: 0 + UnityAdsSettings: + m_Enabled: 0 + m_InitializeOnStartup: 1 + m_TestMode: 0 + m_IosGameId: + m_AndroidGameId: + m_GameIds: {} + m_GameId: + PerformanceReportingSettings: + m_Enabled: 0 diff --git a/ProjectSettings/VFXManager.asset b/ProjectSettings/VFXManager.asset new file mode 100644 index 0000000..3a95c98 --- /dev/null +++ b/ProjectSettings/VFXManager.asset @@ -0,0 +1,12 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!937362698 &1 +VFXManager: + m_ObjectHideFlags: 0 + m_IndirectShader: {fileID: 0} + m_CopyBufferShader: {fileID: 0} + m_SortShader: {fileID: 0} + m_StripUpdateShader: {fileID: 0} + m_RenderPipeSettingsPath: + m_FixedTimeStep: 0.016666668 + m_MaxDeltaTime: 0.05 diff --git a/ProjectSettings/VersionControlSettings.asset b/ProjectSettings/VersionControlSettings.asset new file mode 100644 index 0000000..dca2881 --- /dev/null +++ b/ProjectSettings/VersionControlSettings.asset @@ -0,0 +1,8 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!890905787 &1 +VersionControlSettings: + m_ObjectHideFlags: 0 + m_Mode: Visible Meta Files + m_CollabEditorSettings: + inProgressEnabled: 1 diff --git a/ProjectSettings/XRSettings.asset b/ProjectSettings/XRSettings.asset new file mode 100644 index 0000000..482590c --- /dev/null +++ b/ProjectSettings/XRSettings.asset @@ -0,0 +1,10 @@ +{ + "m_SettingKeys": [ + "VR Device Disabled", + "VR Device User Alert" + ], + "m_SettingValues": [ + "False", + "False" + ] +} \ No newline at end of file