Initial Package with errors

This commit is contained in:
wsycarlos 2025-12-28 23:11:56 +08:00
commit a7623cd55a
387 changed files with 34586 additions and 0 deletions

106
.gitignore vendored Normal file
View File

@ -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

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: da7bdb8bfa22af447854131661c3f140
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ceb5850fa4b1da54f8485d145ce1f7fb
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fd9595fe20f16b6418ee574335afadca
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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,
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 53e74863b20de0742bad85898d617db6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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<Resource> m_DependencyResources;
private List<Asset> m_DependencyAssets;
private List<string> m_ScatteredDependencyAssetNames;
public DependencyData()
{
m_DependencyResources = new List<Resource>();
m_DependencyAssets = new List<Asset>();
m_ScatteredDependencyAssetNames = new List<string>();
}
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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 325edc30663628f4a917226eeee0b733
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 资源分析器。
/// </summary>
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<ResourceAnalyzer>("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 ?? "<None>");
EditorGUILayout.LabelField("Resource Name", m_SelectedAssetName == null ? "<None>" : 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<string>(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<string>(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 ?? "<None>");
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<string>(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<string>(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<string>(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<string>(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();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2e7971f49bcdc654fb34a9fdaa2a6d29
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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<string> hosts = new HashSet<string>();
foreach (Stamp stamp in m_Stamps)
{
hosts.Add(stamp.HostAssetName);
}
List<string[]> results = new List<string[]>();
foreach (string host in hosts)
{
LinkedList<string> route = new LinkedList<string>();
HashSet<string> visited = new HashSet<string>();
if (Check(host, route, visited))
{
results.Add(route.ToArray());
}
}
return results.ToArray();
}
private bool Check(string host, LinkedList<string> route, HashSet<string> 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;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 97329d75bce6b634282bf05ff3453fba
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 15cf99f0cd968de4e876c49401fa5294
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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<string, DependencyData> m_DependencyDatas;
private readonly Dictionary<string, List<Asset>> m_ScatteredAssets;
private readonly List<string[]> m_CircularDependencyDatas;
private readonly HashSet<Stamp> 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<string, DependencyData>(StringComparer.Ordinal);
m_ScatteredAssets = new Dictionary<string, List<Asset>>(StringComparer.Ordinal);
m_AnalyzedStamps = new HashSet<Stamp>();
m_CircularDependencyDatas = new List<string[]>();
}
public event GameFrameworkAction<int, int> OnLoadingResource = null;
public event GameFrameworkAction<int, int> OnLoadingAsset = null;
public event GameFrameworkAction OnLoadCompleted = null;
public event GameFrameworkAction<int, int> 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<string> 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<Asset> 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<string> 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<Asset> scatteredAssets = null;
if (!m_ScatteredAssets.TryGetValue(dependencyAssetName, out scatteredAssets))
{
scatteredAssets = new List<Asset>();
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<string> filteredAssetNames = GetFilteredAssetNames(filter);
IEnumerable<KeyValuePair<string, DependencyData>> filteredResult = m_DependencyDatas.Where(pair => filteredAssetNames.Contains(pair.Key));
IEnumerable<KeyValuePair<string, DependencyData>> 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<string> filterAssetNames = GetFilteredAssetNames(filter);
IEnumerable<KeyValuePair<string, List<Asset>>> filteredResult = m_ScatteredAssets.Where(pair => filterAssetNames.Contains(pair.Key) && pair.Value.Count > 1);
IEnumerable<KeyValuePair<string, List<Asset>>> 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<Asset> assets = null;
if (m_ScatteredAssets.TryGetValue(scatteredAssetName, out assets))
{
return assets.ToArray();
}
return null;
}
public string[][] GetCircularDependencyDatas()
{
return m_CircularDependencyDatas.ToArray();
}
private HashSet<string> GetFilteredAssetNames(string filter)
{
string[] filterAssetGuids = AssetDatabase.FindAssets(filter);
HashSet<string> filterAssetNames = new HashSet<string>();
foreach (string filterAssetGuid in filterAssetGuids)
{
filterAssetNames.Add(AssetDatabase.GUIDToAssetPath(filterAssetGuid));
}
return filterAssetNames;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f05a10a252bec6c44b19b0cf7c105ff3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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,
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2d9068195c1bd334d8dfb4211ad27f7b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2dd745915ad459e4c9d5aef04e1dfeea
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 对 AssetBundle 应用的压缩算法类型。
/// </summary>
public enum AssetBundleCompressionType : byte
{
/// <summary>
/// 不使用压缩算法。
/// </summary>
Uncompressed = 0,
/// <summary>
/// 使用 LZ4 压缩算法。
/// </summary>
LZ4,
/// <summary>
/// 使用 LZMA 压缩算法。
/// </summary>
LZMA
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 690743de30449bf46aa333e5117930d1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 生成资源事件处理函数。
/// </summary>
public interface IBuildEventHandler
{
/// <summary>
/// 获取当某个平台生成失败时,是否继续生成下一个平台。
/// </summary>
bool ContinueOnFailure
{
get;
}
/// <summary>
/// 所有平台生成开始前的预处理事件。
/// </summary>
/// <param name="productName">产品名称。</param>
/// <param name="companyName">公司名称。</param>
/// <param name="gameIdentifier">游戏识别号。</param>
/// <param name="gameFrameworkVersion">游戏框架版本。</param>
/// <param name="unityVersion">Unity 版本。</param>
/// <param name="applicableGameVersion">适用游戏版本。</param>
/// <param name="internalResourceVersion">内部资源版本。</param>
/// <param name="platforms">生成的目标平台。</param>
/// <param name="assetBundleCompression">AssetBundle 压缩类型。</param>
/// <param name="compressionHelperTypeName">压缩解压缩辅助器类型名称。</param>
/// <param name="additionalCompressionSelected">是否进行再压缩以降低传输开销。</param>
/// <param name="forceRebuildAssetBundleSelected">是否强制重新构建 AssetBundle。</param>
/// <param name="buildEventHandlerTypeName">生成资源事件处理函数名称。</param>
/// <param name="outputDirectory">生成目录。</param>
/// <param name="buildAssetBundleOptions">AssetBundle 生成选项。</param>
/// <param name="workingPath">生成时的工作路径。</param>
/// <param name="outputPackageSelected">是否生成单机模式所需的文件。</param>
/// <param name="outputPackagePath">为单机模式生成的文件存放于此路径。若游戏是单机游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。</param>
/// <param name="outputFullSelected">是否生成可更新模式所需的远程文件。</param>
/// <param name="outputFullPath">为可更新模式生成的远程文件存放于此路径。若游戏是网络游戏,生成结束后应将此目录上传至 Web 服务器,供玩家下载用。</param>
/// <param name="outputPackedSelected">是否生成可更新模式所需的本地文件。</param>
/// <param name="outputPackedPath">为可更新模式生成的本地文件存放于此路径。若游戏是网络游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。</param>
/// <param name="buildReportPath">生成报告路径。</param>
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);
/// <summary>
/// 某个平台生成开始前的预处理事件。
/// </summary>
/// <param name="platform">生成平台。</param>
/// <param name="workingPath">生成时的工作路径。</param>
/// <param name="outputPackageSelected">是否生成单机模式所需的文件。</param>
/// <param name="outputPackagePath">为单机模式生成的文件存放于此路径。若游戏是单机游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。</param>
/// <param name="outputFullSelected">是否生成可更新模式所需的远程文件。</param>
/// <param name="outputFullPath">为可更新模式生成的远程文件存放于此路径。若游戏是网络游戏,生成结束后应将此目录上传至 Web 服务器,供玩家下载用。</param>
/// <param name="outputPackedSelected">是否生成可更新模式所需的本地文件。</param>
/// <param name="outputPackedPath">为可更新模式生成的本地文件存放于此路径。若游戏是网络游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。</param>
void OnPreprocessPlatform(Platform platform, string workingPath, bool outputPackageSelected, string outputPackagePath, bool outputFullSelected, string outputFullPath, bool outputPackedSelected, string outputPackedPath);
/// <summary>
/// 某个平台生成 AssetBundle 完成事件。
/// </summary>
/// <param name="platform">生成平台。</param>
/// <param name="workingPath">生成时的工作路径。</param>
/// <param name="outputPackageSelected">是否生成单机模式所需的文件。</param>
/// <param name="outputPackagePath">为单机模式生成的文件存放于此路径。若游戏是单机游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。</param>
/// <param name="outputFullSelected">是否生成可更新模式所需的远程文件。</param>
/// <param name="outputFullPath">为可更新模式生成的远程文件存放于此路径。若游戏是网络游戏,生成结束后应将此目录上传至 Web 服务器,供玩家下载用。</param>
/// <param name="outputPackedSelected">是否生成可更新模式所需的本地文件。</param>
/// <param name="outputPackedPath">为可更新模式生成的本地文件存放于此路径。若游戏是网络游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。</param>
/// <param name="assetBundleManifest">AssetBundle 的描述文件。</param>
void OnBuildAssetBundlesComplete(Platform platform, string workingPath, bool outputPackageSelected, string outputPackagePath, bool outputFullSelected, string outputFullPath, bool outputPackedSelected, string outputPackedPath, AssetBundleManifest assetBundleManifest);
/// <summary>
/// 某个平台可更新模式版本列表文件的输出事件。
/// </summary>
/// <param name="platform">生成平台。</param>
/// <param name="versionListPath">可更新模式版本列表文件的路径。</param>
/// <param name="versionListLength">可更新模式版本列表文件的长度。</param>
/// <param name="versionListHashCode">可更新模式版本列表文件的校验值。</param>
/// <param name="versionListCompressedLength">可更新模式版本列表文件压缩后的长度。</param>
/// <param name="versionListCompressedHashCode">可更新模式版本列表文件压缩后的校验值。</param>
void OnOutputUpdatableVersionListData(Platform platform, string versionListPath, int versionListLength, int versionListHashCode, int versionListCompressedLength, int versionListCompressedHashCode);
/// <summary>
/// 某个平台生成结束后的后处理事件。
/// </summary>
/// <param name="platform">生成平台。</param>
/// <param name="workingPath">生成时的工作路径。</param>
/// <param name="outputPackageSelected">是否生成单机模式所需的文件。</param>
/// <param name="outputPackagePath">为单机模式生成的文件存放于此路径。若游戏是单机游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。</param>
/// <param name="outputFullSelected">是否生成可更新模式所需的远程文件。</param>
/// <param name="outputFullPath">为可更新模式生成的远程文件存放于此路径。若游戏是网络游戏,生成结束后应将此目录上传至 Web 服务器,供玩家下载用。</param>
/// <param name="outputPackedSelected">是否生成可更新模式所需的本地文件。</param>
/// <param name="outputPackedPath">为可更新模式生成的本地文件存放于此路径。若游戏是网络游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。</param>
/// <param name="isSuccess">是否生成成功。</param>
void OnPostprocessPlatform(Platform platform, string workingPath, bool outputPackageSelected, string outputPackagePath, bool outputFullSelected, string outputFullPath, bool outputPackedSelected, string outputPackedPath, bool isSuccess);
/// <summary>
/// 所有平台生成结束后的后处理事件。
/// </summary>
/// <param name="productName">产品名称。</param>
/// <param name="companyName">公司名称。</param>
/// <param name="gameIdentifier">游戏识别号。</param>
/// <param name="gameFrameworkVersion">游戏框架版本。</param>
/// <param name="unityVersion">Unity 版本。</param>
/// <param name="applicableGameVersion">适用游戏版本。</param>
/// <param name="internalResourceVersion">内部资源版本。</param>
/// <param name="platforms">生成的目标平台。</param>
/// <param name="assetBundleCompression">AssetBundle 压缩类型。</param>
/// <param name="compressionHelperTypeName">压缩解压缩辅助器类型名称。</param>
/// <param name="additionalCompressionSelected">是否进行再压缩以降低传输开销。</param>
/// <param name="forceRebuildAssetBundleSelected">是否强制重新构建 AssetBundle。</param>
/// <param name="buildEventHandlerTypeName">生成资源事件处理函数名称。</param>
/// <param name="outputDirectory">生成目录。</param>
/// <param name="buildAssetBundleOptions">AssetBundle 生成选项。</param>
/// <param name="workingPath">生成时的工作路径。</param>
/// <param name="outputPackageSelected">是否生成单机模式所需的文件。</param>
/// <param name="outputPackagePath">为单机模式生成的文件存放于此路径。若游戏是单机游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。</param>
/// <param name="outputFullSelected">是否生成可更新模式所需的远程文件。</param>
/// <param name="outputFullPath">为可更新模式生成的远程文件存放于此路径。若游戏是网络游戏,生成结束后应将此目录上传至 Web 服务器,供玩家下载用。</param>
/// <param name="outputPackedSelected">是否生成可更新模式所需的本地文件。</param>
/// <param name="outputPackedPath">为可更新模式生成的本地文件存放于此路径。若游戏是网络游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后打包 App 即可。</param>
/// <param name="buildReportPath">生成报告路径。</param>
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);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a24c2d69ef707e94c8ec819667089bce
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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,
/// <summary>
/// Windows 32 位。
/// </summary>
Windows = 1 << 0,
/// <summary>
/// Windows 64 位。
/// </summary>
Windows64 = 1 << 1,
/// <summary>
/// macOS。
/// </summary>
MacOS = 1 << 2,
/// <summary>
/// Linux。
/// </summary>
Linux = 1 << 3,
/// <summary>
/// iOS。
/// </summary>
IOS = 1 << 4,
/// <summary>
/// Android。
/// </summary>
Android = 1 << 5,
/// <summary>
/// Windows Store。
/// </summary>
WindowsStore = 1 << 6,
/// <summary>
/// WebGL。
/// </summary>
WebGL = 1 << 7,
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 443d82794c390e043b1565cea8da60cd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 资源生成器。
/// </summary>
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<ResourceBuilder>("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));
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e863c5f9e4c0a9d47a926fbb0416a149
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// ResourceBuilder 配置路径属性。
/// </summary>
public sealed class ResourceBuilderConfigPathAttribute : ConfigPathAttribute
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 099a19e921c6da944ba2cdf51139d818
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b52ab112713ba504a84693edd59a6b03
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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<string, ResourceData> 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<string, ResourceData> 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();
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ae0020ba4726cbd46b34a2341c16cd6a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 23c25a2b879a092409b04f2e7851ac6b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 86943b1b61e58a340b707c7c11f47700
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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<AssetData> m_AssetDatas;
private readonly List<ResourceCode> 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<AssetData>();
m_Codes = new List<ResourceCode>();
}
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));
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61757cf57a877ce46a12429a7e8996dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c69cd2ac760709b4ab36ba15bc5d8759
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2678da0502f5874429b8bce3d35f573f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bc804e13da19ff043aac07751e249b43
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 资源。
/// </summary>
public sealed class Asset : IComparable<Asset>
{
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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f0147356ab2aa7548b5448288d785afe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 资源类型。
/// </summary>
public enum AssetType : byte
{
/// <summary>
/// 未知。
/// </summary>
Unknown = 0,
/// <summary>
/// 存放资源。
/// </summary>
Asset,
/// <summary>
/// 存放场景。
/// </summary>
Scene,
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ca96b555ae5b2c34e8cc830446f11525
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 资源加载方式类型。
/// </summary>
public enum LoadType : byte
{
/// <summary>
/// 使用文件方式加载。
/// </summary>
LoadFromFile = 0,
/// <summary>
/// 使用内存方式加载。
/// </summary>
LoadFromMemory,
/// <summary>
/// 使用内存快速解密方式加载。
/// </summary>
LoadFromMemoryAndQuickDecrypt,
/// <summary>
/// 使用内存解密方式加载。
/// </summary>
LoadFromMemoryAndDecrypt,
/// <summary>
/// 使用二进制方式加载。
/// </summary>
LoadFromBinary,
/// <summary>
/// 使用二进制快速解密方式加载。
/// </summary>
LoadFromBinaryAndQuickDecrypt,
/// <summary>
/// 使用二进制解密方式加载。
/// </summary>
LoadFromBinaryAndDecrypt
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f5660cbfaa767b84fbc1ef8799919b26
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 资源。
/// </summary>
public sealed class Resource
{
private readonly List<Asset> m_Assets;
private readonly List<string> m_ResourceGroups;
private Resource(string name, string variant, string fileSystem, LoadType loadType, bool packed, string[] resourceGroups)
{
m_Assets = new List<Asset>();
m_ResourceGroups = new List<string>();
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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2d3d5c5d16bedc54c976247a6a5b429e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 资源集合。
/// </summary>
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<string, Resource> m_Resources;
private readonly SortedDictionary<string, Asset> m_Assets;
public ResourceCollection()
{
m_ConfigurationPath = Type.GetConfigurationPath<ResourceCollectionConfigPathAttribute>() ?? Utility.Path.GetRegularPath(Path.Combine(Application.dataPath, "GameFramework/Configs/ResourceCollection.xml"));
m_Resources = new SortedDictionary<string, Resource>(StringComparer.Ordinal);
m_Assets = new SortedDictionary<string, Asset>(StringComparer.Ordinal);
}
public int ResourceCount
{
get
{
return m_Resources.Count;
}
}
public int AssetCount
{
get
{
return m_Assets.Count;
}
}
public event GameFrameworkAction<int, int> OnLoadingResource = null;
public event GameFrameworkAction<int, int> 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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d1736b422b0ea4c46bbaf798d320e6f1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// ResourceCollection 配置路径属性。
/// </summary>
public sealed class ResourceCollectionConfigPathAttribute : ConfigPathAttribute
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1eb3245545d87064b814268034cc7af6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8e537bb30b04ebc41bd7575567444988
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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,
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5463b22a6a4019146a38f7b80dbe6fa7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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,
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 32b00a6c44b75494f8576b42717b1f1f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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<ResourceFolder> m_Folders;
private readonly List<ResourceItem> m_Items;
public ResourceFolder(string name, ResourceFolder folder)
{
m_Folders = new List<ResourceFolder>();
m_Items = new List<ResourceItem>();
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);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8cb7e55dc8f5c0b4c8bdad2802a24162
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3f2127e06af00f84294606afa2dfc494
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 956e53f5acdcb4c40a8ecc68d943dde0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// ResourceEditor 配置路径属性。
/// </summary>
public sealed class ResourceEditorConfigPathAttribute : ConfigPathAttribute
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: af287b4a1d99d3946b1aab8f70c78964
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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<string> m_SourceAssetSearchPaths;
private readonly List<string> m_SourceAssetSearchRelativePaths;
private readonly Dictionary<string, SourceAsset> 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<ResourceEditorConfigPathAttribute>() ?? 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<string>();
m_SourceAssetSearchRelativePaths = new List<string>();
m_SourceAssets = new Dictionary<string, SourceAsset>(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<int, int> OnLoadingResource = null;
public event GameFrameworkAction<int, int> OnLoadingAsset = null;
public event GameFrameworkAction OnLoadCompleted = null;
public event GameFrameworkAction<SourceAsset[]> OnAssetAssigned = null;
public event GameFrameworkAction<SourceAsset[]> 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<SourceAsset> unassignedSourceAssets = new List<SourceAsset>();
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<Resource> resources = new List<Resource>(m_ResourceCollection.GetResources());
List<Resource> 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<Asset> assets = new List<Asset>(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<Asset> assets = new List<Asset>(m_ResourceCollection.GetAssets());
List<Asset> 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<string, SourceAsset> 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<string> tempGuids = new HashSet<string>();
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<string>(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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7c8c042eb5e752f49920cfc09aff81c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ded5a7d9ccd4b2a409ec840ba3df0b18
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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<SourceFolder> m_Folders;
private readonly List<SourceAsset> m_Assets;
public SourceFolder(string name, SourceFolder folder)
{
m_Folders = new List<SourceFolder>();
m_Assets = new List<SourceAsset>();
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;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bcb967b558b5d254fb96db1fc5ed808b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3564da2c360cfdb46acffa4b7f42d275
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 资源包生成器。
/// </summary>
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[] { "<Unlimited>", "128 MB", "256 MB", "512 MB", "1 GB", "2 GB", "4 GB", "<Custom>" };
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<ResourcePackBuilder>("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 <None>", 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] = "<None>";
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 "<None>";
}
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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e260afdf322bd1f4897314c0d2c777d7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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 = "<None>";
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<string> m_CompressionHelperTypeNames;
private readonly UpdatableVersionListSerializer m_UpdatableVersionListSerializer;
private readonly ResourcePackVersionListSerializer m_ResourcePackVersionListSerializer;
public ResourcePackBuilderController()
{
m_ConfigurationPath = Type.GetConfigurationPath<ResourceBuilderConfigPathAttribute>() ?? 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<string>
{
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<int> OnBuildResourcePacksStarted = null;
public event GameFrameworkAction<int, int> OnBuildResourcePacksCompleted = null;
public event GameFrameworkAction<int, int, string, string> OnBuildResourcePackSuccess = null;
public event GameFrameworkAction<int, int, string, string> 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<string> versionNames = new List<string>();
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<ResourcePackVersionList.Resource> resources = new List<ResourcePackVersionList.Resource>();
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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 886e7d3c19662474caeb030f5b2d9a4e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3d96add3948f44049bb53f4207cdee15
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 资源同步工具。
/// </summary>
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<ResourceSyncTools>("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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d691ed24af244ff41a3012f66ca3ef80
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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<int, int> OnLoadingResource = null;
public event GameFrameworkAction<int, int> OnLoadingAsset = null;
public event GameFrameworkAction OnCompleted = null;
public event GameFrameworkAction<int, int, string> OnResourceDataChanged = null;
public string[] GetAllAssetBundleNames()
{
return AssetDatabase.GetAllAssetBundleNames();
}
public string[] GetUsedAssetBundleNames()
{
HashSet<string> hashSet = new HashSet<string>(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<string> allAssetNames = new HashSet<string>();
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();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 210d0e0a522f6c540b17cf9fe64b71e4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e2255dcc5c6cd5349819787a0ec15554
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,3 @@
{
"name": "Byway.ResourceLoader"
}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2ed8c5c15f686974c93241dd368c4cc8
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c59a93bee4270d54994aa089a32b353d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 使用可更新模式并应用资源包资源完成时的回调函数。
/// </summary>
/// <param name="resourcePackPath">应用的资源包路径。</param>
/// <param name="result">应用资源包资源结果,全部成功为 true否则为 false。</param>
public delegate void ApplyResourcesCompleteCallback(string resourcePackPath, bool result);
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e9d27a65d627b6c4facd67c3371e85f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 使用可更新模式并检查资源完成时的回调函数。
/// </summary>
/// <param name="movedCount">已移动的资源数量。</param>
/// <param name="removedCount">已移除的资源数量。</param>
/// <param name="updateCount">可更新的资源数量。</param>
/// <param name="updateTotalLength">可更新的资源总大小。</param>
/// <param name="updateTotalCompressedLength">可更新的压缩后总大小。</param>
public delegate void CheckResourcesCompleteCallback(int movedCount, int removedCount, int updateCount, long updateTotalLength, long updateTotalCompressedLength);
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 44b378c75bd47654e8269f1a95775e36
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 检查版本资源列表结果。
/// </summary>
public enum CheckVersionListResult : byte
{
/// <summary>
/// 已经是最新的。
/// </summary>
Updated = 0,
/// <summary>
/// 需要更新。
/// </summary>
NeedUpdate
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0011c07ad50f9d4428874a8b1191e5af
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 资源相关常量。
/// </summary>
internal static class Constant
{
/// <summary>
/// 默认资源加载优先级。
/// </summary>
internal const int DefaultPriority = 0;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8568e897065730448853b7e92432a01a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -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
{
/// <summary>
/// 解密资源回调函数。
/// </summary>
/// <param name="bytes">要解密的资源二进制流。</param>
/// <param name="startIndex">解密二进制流的起始位置。</param>
/// <param name="count">解密二进制流的长度。</param>
/// <param name="name">资源名称。</param>
/// <param name="variant">变体名称。</param>
/// <param name="extension">扩展名称。</param>
/// <param name="storageInReadOnly">资源是否在只读区。</param>
/// <param name="fileSystem">文件系统名称。</param>
/// <param name="loadType">资源加载方式。</param>
/// <param name="length">资源大小。</param>
/// <param name="hashCode">资源哈希值。</param>
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);
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5ff1c45ec7e055346aab3793b995ce9c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More