上传package

This commit is contained in:
zhang hongbo 2026-03-12 15:02:42 +08:00
parent 88145ee28d
commit 30b171ae7b
1452 changed files with 146976 additions and 3 deletions

6
.gitignore vendored
View File

@ -76,9 +76,9 @@ ehthumbs.db
[Aa]ssets/Plugins/Android/*.aar
# 忽略Packages目录但保留manifest
[Pp]ackages/*
![Pp]ackages/manifest.json
![Pp]ackages/packages-lock.json
# [Pp]ackages/*
# ![Pp]ackages/manifest.json
# ![Pp]ackages/packages-lock.json
# Timeline
[Aa]ssets/**/[Tt]imeline/

View File

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

View File

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

View File

@ -0,0 +1,319 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(BaseComponent))]
internal sealed class BaseComponentInspector : GameFrameworkInspector
{
private const string NoneOptionName = "<None>";
private static readonly float[] GameSpeed = new float[] { 0f, 0.01f, 0.1f, 0.25f, 0.5f, 1f, 1.5f, 2f, 4f, 8f };
private static readonly string[] GameSpeedForDisplay = new string[] { "0x", "0.01x", "0.1x", "0.25x", "0.5x", "1x", "1.5x", "2x", "4x", "8x" };
private SerializedProperty m_EditorResourceMode = null;
private SerializedProperty m_EditorLanguage = null;
private SerializedProperty m_TextHelperTypeName = null;
private SerializedProperty m_VersionHelperTypeName = null;
private SerializedProperty m_LogHelperTypeName = null;
private SerializedProperty m_CompressionHelperTypeName = null;
private SerializedProperty m_JsonHelperTypeName = null;
private SerializedProperty m_FrameRate = null;
private SerializedProperty m_GameSpeed = null;
private SerializedProperty m_RunInBackground = null;
private SerializedProperty m_NeverSleep = null;
private string[] m_TextHelperTypeNames = null;
private int m_TextHelperTypeNameIndex = 0;
private string[] m_VersionHelperTypeNames = null;
private int m_VersionHelperTypeNameIndex = 0;
private string[] m_LogHelperTypeNames = null;
private int m_LogHelperTypeNameIndex = 0;
private string[] m_CompressionHelperTypeNames = null;
private int m_CompressionHelperTypeNameIndex = 0;
private string[] m_JsonHelperTypeNames = null;
private int m_JsonHelperTypeNameIndex = 0;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
BaseComponent t = (BaseComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
m_EditorResourceMode.boolValue = EditorGUILayout.BeginToggleGroup("Editor Resource Mode", m_EditorResourceMode.boolValue);
{
EditorGUILayout.HelpBox("Editor resource mode option is only for editor mode. Game Framework will use editor resource files, which you should validate first.", MessageType.Warning);
EditorGUILayout.PropertyField(m_EditorLanguage);
EditorGUILayout.HelpBox("Editor language option is only use for localization test in editor mode.", MessageType.Info);
}
EditorGUILayout.EndToggleGroup();
EditorGUILayout.BeginVertical("box");
{
EditorGUILayout.LabelField("Global Helpers", EditorStyles.boldLabel);
int textHelperSelectedIndex = EditorGUILayout.Popup("Text Helper", m_TextHelperTypeNameIndex, m_TextHelperTypeNames);
if (textHelperSelectedIndex != m_TextHelperTypeNameIndex)
{
m_TextHelperTypeNameIndex = textHelperSelectedIndex;
m_TextHelperTypeName.stringValue = textHelperSelectedIndex <= 0 ? null : m_TextHelperTypeNames[textHelperSelectedIndex];
}
int versionHelperSelectedIndex = EditorGUILayout.Popup("Version Helper", m_VersionHelperTypeNameIndex, m_VersionHelperTypeNames);
if (versionHelperSelectedIndex != m_VersionHelperTypeNameIndex)
{
m_VersionHelperTypeNameIndex = versionHelperSelectedIndex;
m_VersionHelperTypeName.stringValue = versionHelperSelectedIndex <= 0 ? null : m_VersionHelperTypeNames[versionHelperSelectedIndex];
}
int logHelperSelectedIndex = EditorGUILayout.Popup("Log Helper", m_LogHelperTypeNameIndex, m_LogHelperTypeNames);
if (logHelperSelectedIndex != m_LogHelperTypeNameIndex)
{
m_LogHelperTypeNameIndex = logHelperSelectedIndex;
m_LogHelperTypeName.stringValue = logHelperSelectedIndex <= 0 ? null : m_LogHelperTypeNames[logHelperSelectedIndex];
}
int compressionHelperSelectedIndex = EditorGUILayout.Popup("Compression Helper", m_CompressionHelperTypeNameIndex, m_CompressionHelperTypeNames);
if (compressionHelperSelectedIndex != m_CompressionHelperTypeNameIndex)
{
m_CompressionHelperTypeNameIndex = compressionHelperSelectedIndex;
m_CompressionHelperTypeName.stringValue = compressionHelperSelectedIndex <= 0 ? null : m_CompressionHelperTypeNames[compressionHelperSelectedIndex];
}
int jsonHelperSelectedIndex = EditorGUILayout.Popup("JSON Helper", m_JsonHelperTypeNameIndex, m_JsonHelperTypeNames);
if (jsonHelperSelectedIndex != m_JsonHelperTypeNameIndex)
{
m_JsonHelperTypeNameIndex = jsonHelperSelectedIndex;
m_JsonHelperTypeName.stringValue = jsonHelperSelectedIndex <= 0 ? null : m_JsonHelperTypeNames[jsonHelperSelectedIndex];
}
}
EditorGUILayout.EndVertical();
}
EditorGUI.EndDisabledGroup();
int frameRate = EditorGUILayout.IntSlider("Frame Rate", m_FrameRate.intValue, 1, 120);
if (frameRate != m_FrameRate.intValue)
{
if (EditorApplication.isPlaying)
{
t.FrameRate = frameRate;
}
else
{
m_FrameRate.intValue = frameRate;
}
}
EditorGUILayout.BeginVertical("box");
{
float gameSpeed = EditorGUILayout.Slider("Game Speed", m_GameSpeed.floatValue, 0f, 8f);
int selectedGameSpeed = GUILayout.SelectionGrid(GetSelectedGameSpeed(gameSpeed), GameSpeedForDisplay, 5);
if (selectedGameSpeed >= 0)
{
gameSpeed = GetGameSpeed(selectedGameSpeed);
}
if (gameSpeed != m_GameSpeed.floatValue)
{
if (EditorApplication.isPlaying)
{
t.GameSpeed = gameSpeed;
}
else
{
m_GameSpeed.floatValue = gameSpeed;
}
}
}
EditorGUILayout.EndVertical();
bool runInBackground = EditorGUILayout.Toggle("Run in Background", m_RunInBackground.boolValue);
if (runInBackground != m_RunInBackground.boolValue)
{
if (EditorApplication.isPlaying)
{
t.RunInBackground = runInBackground;
}
else
{
m_RunInBackground.boolValue = runInBackground;
}
}
bool neverSleep = EditorGUILayout.Toggle("Never Sleep", m_NeverSleep.boolValue);
if (neverSleep != m_NeverSleep.boolValue)
{
if (EditorApplication.isPlaying)
{
t.NeverSleep = neverSleep;
}
else
{
m_NeverSleep.boolValue = neverSleep;
}
}
serializedObject.ApplyModifiedProperties();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_EditorResourceMode = serializedObject.FindProperty("m_EditorResourceMode");
m_EditorLanguage = serializedObject.FindProperty("m_EditorLanguage");
m_TextHelperTypeName = serializedObject.FindProperty("m_TextHelperTypeName");
m_VersionHelperTypeName = serializedObject.FindProperty("m_VersionHelperTypeName");
m_LogHelperTypeName = serializedObject.FindProperty("m_LogHelperTypeName");
m_CompressionHelperTypeName = serializedObject.FindProperty("m_CompressionHelperTypeName");
m_JsonHelperTypeName = serializedObject.FindProperty("m_JsonHelperTypeName");
m_FrameRate = serializedObject.FindProperty("m_FrameRate");
m_GameSpeed = serializedObject.FindProperty("m_GameSpeed");
m_RunInBackground = serializedObject.FindProperty("m_RunInBackground");
m_NeverSleep = serializedObject.FindProperty("m_NeverSleep");
RefreshTypeNames();
}
private void RefreshTypeNames()
{
List<string> textHelperTypeNames = new List<string>
{
NoneOptionName
};
textHelperTypeNames.AddRange(Type.GetRuntimeTypeNames(typeof(Utility.Text.ITextHelper)));
m_TextHelperTypeNames = textHelperTypeNames.ToArray();
m_TextHelperTypeNameIndex = 0;
if (!string.IsNullOrEmpty(m_TextHelperTypeName.stringValue))
{
m_TextHelperTypeNameIndex = textHelperTypeNames.IndexOf(m_TextHelperTypeName.stringValue);
if (m_TextHelperTypeNameIndex <= 0)
{
m_TextHelperTypeNameIndex = 0;
m_TextHelperTypeName.stringValue = null;
}
}
List<string> versionHelperTypeNames = new List<string>
{
NoneOptionName
};
versionHelperTypeNames.AddRange(Type.GetRuntimeTypeNames(typeof(Version.IVersionHelper)));
m_VersionHelperTypeNames = versionHelperTypeNames.ToArray();
m_VersionHelperTypeNameIndex = 0;
if (!string.IsNullOrEmpty(m_VersionHelperTypeName.stringValue))
{
m_VersionHelperTypeNameIndex = versionHelperTypeNames.IndexOf(m_VersionHelperTypeName.stringValue);
if (m_VersionHelperTypeNameIndex <= 0)
{
m_VersionHelperTypeNameIndex = 0;
m_VersionHelperTypeName.stringValue = null;
}
}
List<string> logHelperTypeNames = new List<string>
{
NoneOptionName
};
logHelperTypeNames.AddRange(Type.GetRuntimeTypeNames(typeof(GameFrameworkLog.ILogHelper)));
m_LogHelperTypeNames = logHelperTypeNames.ToArray();
m_LogHelperTypeNameIndex = 0;
if (!string.IsNullOrEmpty(m_LogHelperTypeName.stringValue))
{
m_LogHelperTypeNameIndex = logHelperTypeNames.IndexOf(m_LogHelperTypeName.stringValue);
if (m_LogHelperTypeNameIndex <= 0)
{
m_LogHelperTypeNameIndex = 0;
m_LogHelperTypeName.stringValue = null;
}
}
List<string> compressionHelperTypeNames = new List<string>
{
NoneOptionName
};
compressionHelperTypeNames.AddRange(Type.GetRuntimeTypeNames(typeof(Utility.Compression.ICompressionHelper)));
m_CompressionHelperTypeNames = compressionHelperTypeNames.ToArray();
m_CompressionHelperTypeNameIndex = 0;
if (!string.IsNullOrEmpty(m_CompressionHelperTypeName.stringValue))
{
m_CompressionHelperTypeNameIndex = compressionHelperTypeNames.IndexOf(m_CompressionHelperTypeName.stringValue);
if (m_CompressionHelperTypeNameIndex <= 0)
{
m_CompressionHelperTypeNameIndex = 0;
m_CompressionHelperTypeName.stringValue = null;
}
}
List<string> jsonHelperTypeNames = new List<string>
{
NoneOptionName
};
jsonHelperTypeNames.AddRange(Type.GetRuntimeTypeNames(typeof(Utility.Json.IJsonHelper)));
m_JsonHelperTypeNames = jsonHelperTypeNames.ToArray();
m_JsonHelperTypeNameIndex = 0;
if (!string.IsNullOrEmpty(m_JsonHelperTypeName.stringValue))
{
m_JsonHelperTypeNameIndex = jsonHelperTypeNames.IndexOf(m_JsonHelperTypeName.stringValue);
if (m_JsonHelperTypeNameIndex <= 0)
{
m_JsonHelperTypeNameIndex = 0;
m_JsonHelperTypeName.stringValue = null;
}
}
serializedObject.ApplyModifiedProperties();
}
private float GetGameSpeed(int selectedGameSpeed)
{
if (selectedGameSpeed < 0)
{
return GameSpeed[0];
}
if (selectedGameSpeed >= GameSpeed.Length)
{
return GameSpeed[GameSpeed.Length - 1];
}
return GameSpeed[selectedGameSpeed];
}
private int GetSelectedGameSpeed(float gameSpeed)
{
for (int i = 0; i < GameSpeed.Length; i++)
{
if (gameSpeed == GameSpeed[i])
{
return i;
}
}
return -1;
}
}
}

View File

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

View File

@ -0,0 +1,74 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using UnityEditor;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(ConfigComponent))]
internal sealed class ConfigComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_EnableLoadConfigUpdateEvent = null;
private SerializedProperty m_EnableLoadConfigDependencyAssetEvent = null;
private SerializedProperty m_CachedBytesSize = null;
private HelperInfo<ConfigHelperBase> m_ConfigHelperInfo = new HelperInfo<ConfigHelperBase>("Config");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
ConfigComponent t = (ConfigComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_EnableLoadConfigUpdateEvent);
EditorGUILayout.PropertyField(m_EnableLoadConfigDependencyAssetEvent);
m_ConfigHelperInfo.Draw();
EditorGUILayout.PropertyField(m_CachedBytesSize);
}
EditorGUI.EndDisabledGroup();
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Config Count", t.Count.ToString());
EditorGUILayout.LabelField("Cached Bytes Size", t.CachedBytesSize.ToString());
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_EnableLoadConfigUpdateEvent = serializedObject.FindProperty("m_EnableLoadConfigUpdateEvent");
m_EnableLoadConfigDependencyAssetEvent = serializedObject.FindProperty("m_EnableLoadConfigDependencyAssetEvent");
m_CachedBytesSize = serializedObject.FindProperty("m_CachedBytesSize");
m_ConfigHelperInfo.Init(serializedObject);
RefreshTypeNames();
}
private void RefreshTypeNames()
{
m_ConfigHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

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

View File

@ -0,0 +1,51 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework.DataNode;
using UnityEditor;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(DataNodeComponent))]
internal sealed class DataNodeComponentInspector : GameFrameworkInspector
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (!EditorApplication.isPlaying)
{
EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info);
return;
}
DataNodeComponent t = (DataNodeComponent)target;
if (IsPrefabInHierarchy(t.gameObject))
{
DrawDataNode(t.Root);
}
Repaint();
}
private void OnEnable()
{
}
private void DrawDataNode(IDataNode dataNode)
{
EditorGUILayout.LabelField(dataNode.FullName, dataNode.ToDataString());
IDataNode[] child = dataNode.GetAllChild();
foreach (IDataNode c in child)
{
DrawDataNode(c);
}
}
}
}

View File

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

View File

@ -0,0 +1,87 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using GameFramework.DataTable;
using UnityEditor;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(DataTableComponent))]
internal sealed class DataTableComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_EnableLoadDataTableUpdateEvent = null;
private SerializedProperty m_EnableLoadDataTableDependencyAssetEvent = null;
private SerializedProperty m_CachedBytesSize = null;
private HelperInfo<DataTableHelperBase> m_DataTableHelperInfo = new HelperInfo<DataTableHelperBase>("DataTable");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
DataTableComponent t = (DataTableComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_EnableLoadDataTableUpdateEvent);
EditorGUILayout.PropertyField(m_EnableLoadDataTableDependencyAssetEvent);
m_DataTableHelperInfo.Draw();
EditorGUILayout.PropertyField(m_CachedBytesSize);
}
EditorGUI.EndDisabledGroup();
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Data Table Count", t.Count.ToString());
EditorGUILayout.LabelField("Cached Bytes Size", t.CachedBytesSize.ToString());
DataTableBase[] dataTables = t.GetAllDataTables();
foreach (DataTableBase dataTable in dataTables)
{
DrawDataTable(dataTable);
}
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_EnableLoadDataTableUpdateEvent = serializedObject.FindProperty("m_EnableLoadDataTableUpdateEvent");
m_EnableLoadDataTableDependencyAssetEvent = serializedObject.FindProperty("m_EnableLoadDataTableDependencyAssetEvent");
m_CachedBytesSize = serializedObject.FindProperty("m_CachedBytesSize");
m_DataTableHelperInfo.Init(serializedObject);
RefreshTypeNames();
}
private void DrawDataTable(DataTableBase dataTable)
{
EditorGUILayout.LabelField(dataTable.FullName, Utility.Text.Format("{0} Rows", dataTable.Count));
}
private void RefreshTypeNames()
{
m_DataTableHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

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

View File

@ -0,0 +1,68 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using UnityEditor;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(DebuggerComponent))]
internal sealed class DebuggerComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_Skin = null;
private SerializedProperty m_ActiveWindow = null;
private SerializedProperty m_ShowFullWindow = null;
private SerializedProperty m_ConsoleWindow = null;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
DebuggerComponent t = (DebuggerComponent)target;
EditorGUILayout.PropertyField(m_Skin);
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
bool activeWindow = EditorGUILayout.Toggle("Active Window", t.ActiveWindow);
if (activeWindow != t.ActiveWindow)
{
t.ActiveWindow = activeWindow;
}
}
else
{
EditorGUILayout.PropertyField(m_ActiveWindow);
}
EditorGUILayout.PropertyField(m_ShowFullWindow);
if (EditorApplication.isPlaying)
{
if (GUILayout.Button("Reset Layout"))
{
t.ResetLayout();
}
}
EditorGUILayout.PropertyField(m_ConsoleWindow, true);
serializedObject.ApplyModifiedProperties();
}
private void OnEnable()
{
m_Skin = serializedObject.FindProperty("m_Skin");
m_ActiveWindow = serializedObject.FindProperty("m_ActiveWindow");
m_ShowFullWindow = serializedObject.FindProperty("m_ShowFullWindow");
m_ConsoleWindow = serializedObject.FindProperty("m_ConsoleWindow");
}
}
}

View File

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

View File

@ -0,0 +1,156 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using System;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(DownloadComponent))]
internal sealed class DownloadComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_InstanceRoot = null;
private SerializedProperty m_DownloadAgentHelperCount = null;
private SerializedProperty m_Timeout = null;
private SerializedProperty m_FlushSize = null;
private HelperInfo<DownloadAgentHelperBase> m_DownloadAgentHelperInfo = new HelperInfo<DownloadAgentHelperBase>("DownloadAgent");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
DownloadComponent t = (DownloadComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_InstanceRoot);
m_DownloadAgentHelperInfo.Draw();
m_DownloadAgentHelperCount.intValue = EditorGUILayout.IntSlider("Download Agent Helper Count", m_DownloadAgentHelperCount.intValue, 1, 16);
}
EditorGUI.EndDisabledGroup();
float timeout = EditorGUILayout.Slider("Timeout", m_Timeout.floatValue, 0f, 120f);
if (timeout != m_Timeout.floatValue)
{
if (EditorApplication.isPlaying)
{
t.Timeout = timeout;
}
else
{
m_Timeout.floatValue = timeout;
}
}
int flushSize = EditorGUILayout.DelayedIntField("Flush Size", m_FlushSize.intValue);
if (flushSize != m_FlushSize.intValue)
{
if (EditorApplication.isPlaying)
{
t.FlushSize = flushSize;
}
else
{
m_FlushSize.intValue = flushSize;
}
}
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Paused", t.Paused.ToString());
EditorGUILayout.LabelField("Total Agent Count", t.TotalAgentCount.ToString());
EditorGUILayout.LabelField("Free Agent Count", t.FreeAgentCount.ToString());
EditorGUILayout.LabelField("Working Agent Count", t.WorkingAgentCount.ToString());
EditorGUILayout.LabelField("Waiting Agent Count", t.WaitingTaskCount.ToString());
EditorGUILayout.LabelField("Current Speed", t.CurrentSpeed.ToString());
EditorGUILayout.BeginVertical("box");
{
TaskInfo[] downloadInfos = t.GetAllDownloadInfos();
if (downloadInfos.Length > 0)
{
foreach (TaskInfo downloadInfo in downloadInfos)
{
DrawDownloadInfo(downloadInfo);
}
if (GUILayout.Button("Export CSV Data"))
{
string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, "Download Task Data.csv", string.Empty);
if (!string.IsNullOrEmpty(exportFileName))
{
try
{
int index = 0;
string[] data = new string[downloadInfos.Length + 1];
data[index++] = "Download Path,Serial Id,Tag,Priority,Status";
foreach (TaskInfo downloadInfo in downloadInfos)
{
data[index++] = Utility.Text.Format("{0},{1},{2},{3},{4}", downloadInfo.Description, downloadInfo.SerialId, downloadInfo.Tag ?? string.Empty, downloadInfo.Priority, downloadInfo.Status);
}
File.WriteAllLines(exportFileName, data, Encoding.UTF8);
Debug.Log(Utility.Text.Format("Export download task CSV data to '{0}' success.", exportFileName));
}
catch (Exception exception)
{
Debug.LogError(Utility.Text.Format("Export download task CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception));
}
}
}
}
else
{
GUILayout.Label("Download Task is Empty ...");
}
}
EditorGUILayout.EndVertical();
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot");
m_DownloadAgentHelperCount = serializedObject.FindProperty("m_DownloadAgentHelperCount");
m_Timeout = serializedObject.FindProperty("m_Timeout");
m_FlushSize = serializedObject.FindProperty("m_FlushSize");
m_DownloadAgentHelperInfo.Init(serializedObject);
RefreshTypeNames();
}
private void DrawDownloadInfo(TaskInfo downloadInfo)
{
EditorGUILayout.LabelField(downloadInfo.Description, Utility.Text.Format("[SerialId]{0} [Tag]{1} [Priority]{2} [Status]{3}", downloadInfo.SerialId, downloadInfo.Tag ?? "<None>", downloadInfo.Priority, downloadInfo.Status));
}
private void RefreshTypeNames()
{
m_DownloadAgentHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

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

View File

@ -0,0 +1,52 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using UnityEditor;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(EditorResourceComponent))]
internal sealed class EditorResourceComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_EnableCachedAssets = null;
private SerializedProperty m_LoadAssetCountPerFrame = null;
private SerializedProperty m_MinLoadAssetRandomDelaySeconds = null;
private SerializedProperty m_MaxLoadAssetRandomDelaySeconds = null;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
EditorResourceComponent t = (EditorResourceComponent)target;
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Load Waiting Asset Count", t.LoadWaitingAssetCount.ToString());
}
EditorGUILayout.PropertyField(m_EnableCachedAssets);
EditorGUILayout.PropertyField(m_LoadAssetCountPerFrame);
EditorGUILayout.PropertyField(m_MinLoadAssetRandomDelaySeconds);
EditorGUILayout.PropertyField(m_MaxLoadAssetRandomDelaySeconds);
serializedObject.ApplyModifiedProperties();
Repaint();
}
private void OnEnable()
{
m_EnableCachedAssets = serializedObject.FindProperty("m_EnableCachedAssets");
m_LoadAssetCountPerFrame = serializedObject.FindProperty("m_LoadAssetCountPerFrame");
m_MinLoadAssetRandomDelaySeconds = serializedObject.FindProperty("m_MinLoadAssetRandomDelaySeconds");
m_MaxLoadAssetRandomDelaySeconds = serializedObject.FindProperty("m_MaxLoadAssetRandomDelaySeconds");
}
}
}

View File

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

View File

@ -0,0 +1,88 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using GameFramework.Entity;
using UnityEditor;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(EntityComponent))]
internal sealed class EntityComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_EnableShowEntityUpdateEvent = null;
private SerializedProperty m_EnableShowEntityDependencyAssetEvent = null;
private SerializedProperty m_InstanceRoot = null;
private SerializedProperty m_EntityGroups = null;
private HelperInfo<EntityHelperBase> m_EntityHelperInfo = new HelperInfo<EntityHelperBase>("Entity");
private HelperInfo<EntityGroupHelperBase> m_EntityGroupHelperInfo = new HelperInfo<EntityGroupHelperBase>("EntityGroup");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
EntityComponent t = (EntityComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_EnableShowEntityUpdateEvent);
EditorGUILayout.PropertyField(m_EnableShowEntityDependencyAssetEvent);
EditorGUILayout.PropertyField(m_InstanceRoot);
m_EntityHelperInfo.Draw();
m_EntityGroupHelperInfo.Draw();
EditorGUILayout.PropertyField(m_EntityGroups, true);
}
EditorGUI.EndDisabledGroup();
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Entity Group Count", t.EntityGroupCount.ToString());
EditorGUILayout.LabelField("Entity Count (Total)", t.EntityCount.ToString());
IEntityGroup[] entityGroups = t.GetAllEntityGroups();
foreach (IEntityGroup entityGroup in entityGroups)
{
EditorGUILayout.LabelField(Utility.Text.Format("Entity Count ({0})", entityGroup.Name), entityGroup.EntityCount.ToString());
}
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_EnableShowEntityUpdateEvent = serializedObject.FindProperty("m_EnableShowEntityUpdateEvent");
m_EnableShowEntityDependencyAssetEvent = serializedObject.FindProperty("m_EnableShowEntityDependencyAssetEvent");
m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot");
m_EntityGroups = serializedObject.FindProperty("m_EntityGroups");
m_EntityHelperInfo.Init(serializedObject);
m_EntityGroupHelperInfo.Init(serializedObject);
RefreshTypeNames();
}
private void RefreshTypeNames()
{
m_EntityHelperInfo.Refresh();
m_EntityGroupHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

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

View File

@ -0,0 +1,41 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using UnityEditor;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(EventComponent))]
internal sealed class EventComponentInspector : GameFrameworkInspector
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (!EditorApplication.isPlaying)
{
EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info);
return;
}
EventComponent t = (EventComponent)target;
if (IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Event Handler Count", t.EventHandlerCount.ToString());
EditorGUILayout.LabelField("Event Count", t.EventCount.ToString());
}
Repaint();
}
private void OnEnable()
{
}
}
}

View File

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

View File

@ -0,0 +1,73 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using GameFramework.FileSystem;
using UnityEditor;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(FileSystemComponent))]
internal sealed class FileSystemComponentInspector : GameFrameworkInspector
{
private HelperInfo<FileSystemHelperBase> m_FileSystemHelperInfo = new HelperInfo<FileSystemHelperBase>("FileSystem");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
FileSystemComponent t = (FileSystemComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
m_FileSystemHelperInfo.Draw();
}
EditorGUI.EndDisabledGroup();
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("File System Count", t.Count.ToString());
IFileSystem[] fileSystems = t.GetAllFileSystems();
foreach (IFileSystem fileSystem in fileSystems)
{
DrawFileSystem(fileSystem);
}
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_FileSystemHelperInfo.Init(serializedObject);
RefreshTypeNames();
}
private void RefreshTypeNames()
{
m_FileSystemHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
private void DrawFileSystem(IFileSystem fileSystem)
{
EditorGUILayout.LabelField(fileSystem.FullPath, Utility.Text.Format("{0}, {1} / {2} Files", fileSystem.Access, fileSystem.FileCount, fileSystem.MaxFileCount));
}
}
}

View File

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

View File

@ -0,0 +1,53 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using GameFramework.Fsm;
using UnityEditor;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(FsmComponent))]
internal sealed class FsmComponentInspector : GameFrameworkInspector
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (!EditorApplication.isPlaying)
{
EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info);
return;
}
FsmComponent t = (FsmComponent)target;
if (IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("FSM Count", t.Count.ToString());
FsmBase[] fsms = t.GetAllFsms();
foreach (FsmBase fsm in fsms)
{
DrawFsm(fsm);
}
}
Repaint();
}
private void OnEnable()
{
}
private void DrawFsm(FsmBase fsm)
{
EditorGUILayout.LabelField(fsm.FullName, fsm.IsRunning ? Utility.Text.Format("{0}, {1:F1} s", fsm.CurrentStateName, fsm.CurrentStateTime) : (fsm.IsDestroyed ? "Destroyed" : "Not Running"));
}
}
}

View File

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

View File

@ -0,0 +1,64 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using UnityEditor;
namespace UnityGameFramework.Editor
{
/// <summary>
/// 游戏框架 Inspector 抽象类。
/// </summary>
public abstract class GameFrameworkInspector : UnityEditor.Editor
{
private bool m_IsCompiling = false;
/// <summary>
/// 绘制事件。
/// </summary>
public override void OnInspectorGUI()
{
if (m_IsCompiling && !EditorApplication.isCompiling)
{
m_IsCompiling = false;
OnCompileComplete();
}
else if (!m_IsCompiling && EditorApplication.isCompiling)
{
m_IsCompiling = true;
OnCompileStart();
}
}
/// <summary>
/// 编译开始事件。
/// </summary>
protected virtual void OnCompileStart()
{
}
/// <summary>
/// 编译完成事件。
/// </summary>
protected virtual void OnCompileComplete()
{
}
protected bool IsPrefabInHierarchy(UnityEngine.Object obj)
{
if (obj == null)
{
return false;
}
#if UNITY_2018_3_OR_NEWER
return PrefabUtility.GetPrefabAssetType(obj) != PrefabAssetType.Regular;
#else
return PrefabUtility.GetPrefabType(obj) != PrefabType.Prefab;
#endif
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b5bb373d9bcd4bd45861670fa5208e05
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 UnityEditor;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(LocalizationComponent))]
internal sealed class LocalizationComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_EnableLoadDictionaryUpdateEvent = null;
private SerializedProperty m_EnableLoadDictionaryDependencyAssetEvent = null;
private SerializedProperty m_CachedBytesSize = null;
private HelperInfo<LocalizationHelperBase> m_LocalizationHelperInfo = new HelperInfo<LocalizationHelperBase>("Localization");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
LocalizationComponent t = (LocalizationComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_EnableLoadDictionaryUpdateEvent);
EditorGUILayout.PropertyField(m_EnableLoadDictionaryDependencyAssetEvent);
m_LocalizationHelperInfo.Draw();
EditorGUILayout.PropertyField(m_CachedBytesSize);
}
EditorGUI.EndDisabledGroup();
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Language", t.Language.ToString());
EditorGUILayout.LabelField("System Language", t.SystemLanguage.ToString());
EditorGUILayout.LabelField("Dictionary Count", t.DictionaryCount.ToString());
EditorGUILayout.LabelField("Cached Bytes Size", t.CachedBytesSize.ToString());
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_EnableLoadDictionaryUpdateEvent = serializedObject.FindProperty("m_EnableLoadDictionaryUpdateEvent");
m_EnableLoadDictionaryDependencyAssetEvent = serializedObject.FindProperty("m_EnableLoadDictionaryDependencyAssetEvent");
m_CachedBytesSize = serializedObject.FindProperty("m_CachedBytesSize");
m_LocalizationHelperInfo.Init(serializedObject);
RefreshTypeNames();
}
private void RefreshTypeNames()
{
m_LocalizationHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e90ad13aae4116347b57e87e5d00c94d
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 GameFramework;
using GameFramework.Network;
using UnityEditor;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(NetworkComponent))]
internal sealed class NetworkComponentInspector : GameFrameworkInspector
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (!EditorApplication.isPlaying)
{
EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info);
return;
}
NetworkComponent t = (NetworkComponent)target;
if (IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Network Channel Count", t.NetworkChannelCount.ToString());
INetworkChannel[] networkChannels = t.GetAllNetworkChannels();
foreach (INetworkChannel networkChannel in networkChannels)
{
DrawNetworkChannel(networkChannel);
}
}
Repaint();
}
private void OnEnable()
{
}
private void DrawNetworkChannel(INetworkChannel networkChannel)
{
EditorGUILayout.BeginVertical("box");
{
EditorGUILayout.LabelField(networkChannel.Name, networkChannel.Connected ? "Connected" : "Disconnected");
EditorGUILayout.LabelField("Service Type", networkChannel.ServiceType.ToString());
EditorGUILayout.LabelField("Address Family", networkChannel.AddressFamily.ToString());
EditorGUILayout.LabelField("Local Address", networkChannel.Connected ? networkChannel.Socket.LocalEndPoint.ToString() : "Unavailable");
EditorGUILayout.LabelField("Remote Address", networkChannel.Connected ? networkChannel.Socket.RemoteEndPoint.ToString() : "Unavailable");
EditorGUILayout.LabelField("Send Packet", Utility.Text.Format("{0} / {1}", networkChannel.SendPacketCount, networkChannel.SentPacketCount));
EditorGUILayout.LabelField("Receive Packet", Utility.Text.Format("{0} / {1}", networkChannel.ReceivePacketCount, networkChannel.ReceivedPacketCount));
EditorGUILayout.LabelField("Miss Heart Beat Count", networkChannel.MissHeartBeatCount.ToString());
EditorGUILayout.LabelField("Heart Beat", Utility.Text.Format("{0:F2} / {1:F2}", networkChannel.HeartBeatElapseSeconds, networkChannel.HeartBeatInterval));
EditorGUI.BeginDisabledGroup(!networkChannel.Connected);
{
if (GUILayout.Button("Disconnect"))
{
networkChannel.Close();
}
}
EditorGUI.EndDisabledGroup();
}
EditorGUILayout.EndVertical();
EditorGUILayout.Separator();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7cbb7330261939244ac0b87d6798313a
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 GameFramework;
using GameFramework.ObjectPool;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(ObjectPoolComponent))]
internal sealed class ObjectPoolComponentInspector : GameFrameworkInspector
{
private readonly HashSet<string> m_OpenedItems = new HashSet<string>();
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (!EditorApplication.isPlaying)
{
EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info);
return;
}
ObjectPoolComponent t = (ObjectPoolComponent)target;
if (IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Object Pool Count", t.Count.ToString());
ObjectPoolBase[] objectPools = t.GetAllObjectPools(true);
foreach (ObjectPoolBase objectPool in objectPools)
{
DrawObjectPool(objectPool);
}
}
Repaint();
}
private void OnEnable()
{
}
private void DrawObjectPool(ObjectPoolBase objectPool)
{
bool lastState = m_OpenedItems.Contains(objectPool.FullName);
bool currentState = EditorGUILayout.Foldout(lastState, objectPool.FullName);
if (currentState != lastState)
{
if (currentState)
{
m_OpenedItems.Add(objectPool.FullName);
}
else
{
m_OpenedItems.Remove(objectPool.FullName);
}
}
if (currentState)
{
EditorGUILayout.BeginVertical("box");
{
EditorGUILayout.LabelField("Name", objectPool.Name);
EditorGUILayout.LabelField("Type", objectPool.ObjectType.FullName);
EditorGUILayout.LabelField("Auto Release Interval", objectPool.AutoReleaseInterval.ToString());
EditorGUILayout.LabelField("Capacity", objectPool.Capacity.ToString());
EditorGUILayout.LabelField("Used Count", objectPool.Count.ToString());
EditorGUILayout.LabelField("Can Release Count", objectPool.CanReleaseCount.ToString());
EditorGUILayout.LabelField("Expire Time", objectPool.ExpireTime.ToString());
EditorGUILayout.LabelField("Priority", objectPool.Priority.ToString());
ObjectInfo[] objectInfos = objectPool.GetAllObjectInfos();
if (objectInfos.Length > 0)
{
EditorGUILayout.LabelField("Name", objectPool.AllowMultiSpawn ? "Locked\tCount\tFlag\tPriority\tLast Use Time" : "Locked\tIn Use\tFlag\tPriority\tLast Use Time");
foreach (ObjectInfo objectInfo in objectInfos)
{
EditorGUILayout.LabelField(string.IsNullOrEmpty(objectInfo.Name) ? "<None>" : objectInfo.Name, objectPool.AllowMultiSpawn ? Utility.Text.Format("{0}\t{1}\t{2}\t{3}\t{4:yyyy-MM-dd HH:mm:ss}", objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime()) : Utility.Text.Format("{0}\t{1}\t{2}\t{3}\t{4:yyyy-MM-dd HH:mm:ss}", objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime()));
}
if (GUILayout.Button("Release"))
{
objectPool.Release();
}
if (GUILayout.Button("Release All Unused"))
{
objectPool.ReleaseAllUnused();
}
if (GUILayout.Button("Export CSV Data"))
{
string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, Utility.Text.Format("Object Pool Data - {0}.csv", objectPool.Name), string.Empty);
if (!string.IsNullOrEmpty(exportFileName))
{
try
{
int index = 0;
string[] data = new string[objectInfos.Length + 1];
data[index++] = Utility.Text.Format("Name,Locked,{0},Custom Can Release Flag,Priority,Last Use Time", objectPool.AllowMultiSpawn ? "Count" : "In Use");
foreach (ObjectInfo objectInfo in objectInfos)
{
data[index++] = objectPool.AllowMultiSpawn ? Utility.Text.Format("{0},{1},{2},{3},{4},{5:yyyy-MM-dd HH:mm:ss}", objectInfo.Name, objectInfo.Locked, objectInfo.SpawnCount, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime()) : Utility.Text.Format("{0},{1},{2},{3},{4},{5:yyyy-MM-dd HH:mm:ss}", objectInfo.Name, objectInfo.Locked, objectInfo.IsInUse, objectInfo.CustomCanReleaseFlag, objectInfo.Priority, objectInfo.LastUseTime.ToLocalTime());
}
File.WriteAllLines(exportFileName, data, Encoding.UTF8);
Debug.Log(Utility.Text.Format("Export object pool CSV data to '{0}' success.", exportFileName));
}
catch (Exception exception)
{
Debug.LogError(Utility.Text.Format("Export object pool CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception));
}
}
}
}
else
{
GUILayout.Label("Object Pool is Empty ...");
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Separator();
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: eb0d4111d9ba0ad469b2361c7731666a
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.Procedure;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(ProcedureComponent))]
internal sealed class ProcedureComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_AvailableProcedureTypeNames = null;
private SerializedProperty m_EntranceProcedureTypeName = null;
private string[] m_ProcedureTypeNames = null;
private List<string> m_CurrentAvailableProcedureTypeNames = null;
private int m_EntranceProcedureIndex = -1;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
ProcedureComponent t = (ProcedureComponent)target;
if (string.IsNullOrEmpty(m_EntranceProcedureTypeName.stringValue))
{
EditorGUILayout.HelpBox("Entrance procedure is invalid.", MessageType.Error);
}
else if (EditorApplication.isPlaying)
{
EditorGUILayout.LabelField("Current Procedure", t.CurrentProcedure == null ? "None" : t.CurrentProcedure.GetType().ToString());
}
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
GUILayout.Label("Available Procedures", EditorStyles.boldLabel);
if (m_ProcedureTypeNames.Length > 0)
{
EditorGUILayout.BeginVertical("box");
{
foreach (string procedureTypeName in m_ProcedureTypeNames)
{
bool selected = m_CurrentAvailableProcedureTypeNames.Contains(procedureTypeName);
if (selected != EditorGUILayout.ToggleLeft(procedureTypeName, selected))
{
if (!selected)
{
m_CurrentAvailableProcedureTypeNames.Add(procedureTypeName);
WriteAvailableProcedureTypeNames();
}
else if (procedureTypeName != m_EntranceProcedureTypeName.stringValue)
{
m_CurrentAvailableProcedureTypeNames.Remove(procedureTypeName);
WriteAvailableProcedureTypeNames();
}
}
}
}
EditorGUILayout.EndVertical();
}
else
{
EditorGUILayout.HelpBox("There is no available procedure.", MessageType.Warning);
}
if (m_CurrentAvailableProcedureTypeNames.Count > 0)
{
EditorGUILayout.Separator();
int selectedIndex = EditorGUILayout.Popup("Entrance Procedure", m_EntranceProcedureIndex, m_CurrentAvailableProcedureTypeNames.ToArray());
if (selectedIndex != m_EntranceProcedureIndex)
{
m_EntranceProcedureIndex = selectedIndex;
m_EntranceProcedureTypeName.stringValue = m_CurrentAvailableProcedureTypeNames[selectedIndex];
}
}
else
{
EditorGUILayout.HelpBox("Select available procedures first.", MessageType.Info);
}
}
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_AvailableProcedureTypeNames = serializedObject.FindProperty("m_AvailableProcedureTypeNames");
m_EntranceProcedureTypeName = serializedObject.FindProperty("m_EntranceProcedureTypeName");
RefreshTypeNames();
}
private void RefreshTypeNames()
{
m_ProcedureTypeNames = Type.GetRuntimeTypeNames(typeof(ProcedureBase));
ReadAvailableProcedureTypeNames();
int oldCount = m_CurrentAvailableProcedureTypeNames.Count;
m_CurrentAvailableProcedureTypeNames = m_CurrentAvailableProcedureTypeNames.Where(x => m_ProcedureTypeNames.Contains(x)).ToList();
if (m_CurrentAvailableProcedureTypeNames.Count != oldCount)
{
WriteAvailableProcedureTypeNames();
}
else if (!string.IsNullOrEmpty(m_EntranceProcedureTypeName.stringValue))
{
m_EntranceProcedureIndex = m_CurrentAvailableProcedureTypeNames.IndexOf(m_EntranceProcedureTypeName.stringValue);
if (m_EntranceProcedureIndex < 0)
{
m_EntranceProcedureTypeName.stringValue = null;
}
}
serializedObject.ApplyModifiedProperties();
}
private void ReadAvailableProcedureTypeNames()
{
m_CurrentAvailableProcedureTypeNames = new List<string>();
int count = m_AvailableProcedureTypeNames.arraySize;
for (int i = 0; i < count; i++)
{
m_CurrentAvailableProcedureTypeNames.Add(m_AvailableProcedureTypeNames.GetArrayElementAtIndex(i).stringValue);
}
}
private void WriteAvailableProcedureTypeNames()
{
m_AvailableProcedureTypeNames.ClearArray();
if (m_CurrentAvailableProcedureTypeNames == null)
{
return;
}
m_CurrentAvailableProcedureTypeNames.Sort();
int count = m_CurrentAvailableProcedureTypeNames.Count;
for (int i = 0; i < count; i++)
{
m_AvailableProcedureTypeNames.InsertArrayElementAtIndex(i);
m_AvailableProcedureTypeNames.GetArrayElementAtIndex(i).stringValue = m_CurrentAvailableProcedureTypeNames[i];
}
if (!string.IsNullOrEmpty(m_EntranceProcedureTypeName.stringValue))
{
m_EntranceProcedureIndex = m_CurrentAvailableProcedureTypeNames.IndexOf(m_EntranceProcedureTypeName.stringValue);
if (m_EntranceProcedureIndex < 0)
{
m_EntranceProcedureTypeName.stringValue = null;
}
}
}
}
}

View File

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

View File

@ -0,0 +1,152 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(ReferencePoolComponent))]
internal sealed class ReferencePoolComponentInspector : GameFrameworkInspector
{
private readonly Dictionary<string, List<ReferencePoolInfo>> m_ReferencePoolInfos = new Dictionary<string, List<ReferencePoolInfo>>(StringComparer.Ordinal);
private readonly HashSet<string> m_OpenedItems = new HashSet<string>();
private SerializedProperty m_EnableStrictCheck = null;
private bool m_ShowFullClassName = false;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
ReferencePoolComponent t = (ReferencePoolComponent)target;
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
bool enableStrictCheck = EditorGUILayout.Toggle("Enable Strict Check", t.EnableStrictCheck);
if (enableStrictCheck != t.EnableStrictCheck)
{
t.EnableStrictCheck = enableStrictCheck;
}
EditorGUILayout.LabelField("Reference Pool Count", ReferencePool.Count.ToString());
m_ShowFullClassName = EditorGUILayout.Toggle("Show Full Class Name", m_ShowFullClassName);
m_ReferencePoolInfos.Clear();
ReferencePoolInfo[] referencePoolInfos = ReferencePool.GetAllReferencePoolInfos();
foreach (ReferencePoolInfo referencePoolInfo in referencePoolInfos)
{
string assemblyName = referencePoolInfo.Type.Assembly.GetName().Name;
List<ReferencePoolInfo> results = null;
if (!m_ReferencePoolInfos.TryGetValue(assemblyName, out results))
{
results = new List<ReferencePoolInfo>();
m_ReferencePoolInfos.Add(assemblyName, results);
}
results.Add(referencePoolInfo);
}
foreach (KeyValuePair<string, List<ReferencePoolInfo>> assemblyReferencePoolInfo in m_ReferencePoolInfos)
{
bool lastState = m_OpenedItems.Contains(assemblyReferencePoolInfo.Key);
bool currentState = EditorGUILayout.Foldout(lastState, assemblyReferencePoolInfo.Key);
if (currentState != lastState)
{
if (currentState)
{
m_OpenedItems.Add(assemblyReferencePoolInfo.Key);
}
else
{
m_OpenedItems.Remove(assemblyReferencePoolInfo.Key);
}
}
if (currentState)
{
EditorGUILayout.BeginVertical("box");
{
EditorGUILayout.LabelField(m_ShowFullClassName ? "Full Class Name" : "Class Name", "Unused\tUsing\tAcquire\tRelease\tAdd\tRemove");
assemblyReferencePoolInfo.Value.Sort(Comparison);
foreach (ReferencePoolInfo referencePoolInfo in assemblyReferencePoolInfo.Value)
{
DrawReferencePoolInfo(referencePoolInfo);
}
if (GUILayout.Button("Export CSV Data"))
{
string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, Utility.Text.Format("Reference Pool Data - {0}.csv", assemblyReferencePoolInfo.Key), string.Empty);
if (!string.IsNullOrEmpty(exportFileName))
{
try
{
int index = 0;
string[] data = new string[assemblyReferencePoolInfo.Value.Count + 1];
data[index++] = "Class Name,Full Class Name,Unused,Using,Acquire,Release,Add,Remove";
foreach (ReferencePoolInfo referencePoolInfo in assemblyReferencePoolInfo.Value)
{
data[index++] = Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7}", referencePoolInfo.Type.Name, referencePoolInfo.Type.FullName, referencePoolInfo.UnusedReferenceCount, referencePoolInfo.UsingReferenceCount, referencePoolInfo.AcquireReferenceCount, referencePoolInfo.ReleaseReferenceCount, referencePoolInfo.AddReferenceCount, referencePoolInfo.RemoveReferenceCount);
}
File.WriteAllLines(exportFileName, data, Encoding.UTF8);
Debug.Log(Utility.Text.Format("Export reference pool CSV data to '{0}' success.", exportFileName));
}
catch (Exception exception)
{
Debug.LogError(Utility.Text.Format("Export reference pool CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception));
}
}
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Separator();
}
}
}
else
{
EditorGUILayout.PropertyField(m_EnableStrictCheck);
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
private void OnEnable()
{
m_EnableStrictCheck = serializedObject.FindProperty("m_EnableStrictCheck");
}
private void DrawReferencePoolInfo(ReferencePoolInfo referencePoolInfo)
{
EditorGUILayout.LabelField(m_ShowFullClassName ? referencePoolInfo.Type.FullName : referencePoolInfo.Type.Name, Utility.Text.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}", referencePoolInfo.UnusedReferenceCount, referencePoolInfo.UsingReferenceCount, referencePoolInfo.AcquireReferenceCount, referencePoolInfo.ReleaseReferenceCount, referencePoolInfo.AddReferenceCount, referencePoolInfo.RemoveReferenceCount));
}
private int Comparison(ReferencePoolInfo a, ReferencePoolInfo b)
{
if (m_ShowFullClassName)
{
return a.Type.FullName.CompareTo(b.Type.FullName);
}
else
{
return a.Type.Name.CompareTo(b.Type.Name);
}
}
}
}

View File

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

View File

@ -0,0 +1,397 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using System;
using System.IO;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(ResourceComponent))]
internal sealed class ResourceComponentInspector : GameFrameworkInspector
{
private static readonly string[] ResourceModeNames = new string[] { "Package", "Updatable", "Updatable While Playing" };
private SerializedProperty m_ResourceMode = null;
private SerializedProperty m_ReadWritePathType = null;
private SerializedProperty m_MinUnloadUnusedAssetsInterval = null;
private SerializedProperty m_MaxUnloadUnusedAssetsInterval = null;
private SerializedProperty m_AssetAutoReleaseInterval = null;
private SerializedProperty m_AssetCapacity = null;
private SerializedProperty m_AssetExpireTime = null;
private SerializedProperty m_AssetPriority = null;
private SerializedProperty m_ResourceAutoReleaseInterval = null;
private SerializedProperty m_ResourceCapacity = null;
private SerializedProperty m_ResourceExpireTime = null;
private SerializedProperty m_ResourcePriority = null;
private SerializedProperty m_UpdatePrefixUri = null;
private SerializedProperty m_GenerateReadWriteVersionListLength = null;
private SerializedProperty m_UpdateRetryCount = null;
private SerializedProperty m_InstanceRoot = null;
private SerializedProperty m_LoadResourceAgentHelperCount = null;
private FieldInfo m_EditorResourceModeFieldInfo = null;
private int m_ResourceModeIndex = 0;
private HelperInfo<ResourceHelperBase> m_ResourceHelperInfo = new HelperInfo<ResourceHelperBase>("Resource");
private HelperInfo<LoadResourceAgentHelperBase> m_LoadResourceAgentHelperInfo = new HelperInfo<LoadResourceAgentHelperBase>("LoadResourceAgent");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
ResourceComponent t = (ResourceComponent)target;
bool isEditorResourceMode = (bool)m_EditorResourceModeFieldInfo.GetValue(target);
if (isEditorResourceMode)
{
EditorGUILayout.HelpBox("Editor resource mode is enabled. Some options are disabled.", MessageType.Warning);
}
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.EnumPopup("Resource Mode", t.ResourceMode);
}
else
{
int selectedIndex = EditorGUILayout.Popup("Resource Mode", m_ResourceModeIndex, ResourceModeNames);
if (selectedIndex != m_ResourceModeIndex)
{
m_ResourceModeIndex = selectedIndex;
m_ResourceMode.enumValueIndex = selectedIndex + 1;
}
}
m_ReadWritePathType.enumValueIndex = (int)(ReadWritePathType)EditorGUILayout.EnumPopup("Read-Write Path Type", t.ReadWritePathType);
}
EditorGUI.EndDisabledGroup();
float minUnloadUnusedAssetsInterval = EditorGUILayout.Slider("Min Unload Unused Assets Interval", m_MinUnloadUnusedAssetsInterval.floatValue, 0f, 3600f);
if (minUnloadUnusedAssetsInterval != m_MinUnloadUnusedAssetsInterval.floatValue)
{
if (EditorApplication.isPlaying)
{
t.MinUnloadUnusedAssetsInterval = minUnloadUnusedAssetsInterval;
}
else
{
m_MinUnloadUnusedAssetsInterval.floatValue = minUnloadUnusedAssetsInterval;
}
}
float maxUnloadUnusedAssetsInterval = EditorGUILayout.Slider("Max Unload Unused Assets Interval", m_MaxUnloadUnusedAssetsInterval.floatValue, 0f, 3600f);
if (maxUnloadUnusedAssetsInterval != m_MaxUnloadUnusedAssetsInterval.floatValue)
{
if (EditorApplication.isPlaying)
{
t.MaxUnloadUnusedAssetsInterval = maxUnloadUnusedAssetsInterval;
}
else
{
m_MaxUnloadUnusedAssetsInterval.floatValue = maxUnloadUnusedAssetsInterval;
}
}
EditorGUI.BeginDisabledGroup(EditorApplication.isPlaying && isEditorResourceMode);
{
float assetAutoReleaseInterval = EditorGUILayout.DelayedFloatField("Asset Auto Release Interval", m_AssetAutoReleaseInterval.floatValue);
if (assetAutoReleaseInterval != m_AssetAutoReleaseInterval.floatValue)
{
if (EditorApplication.isPlaying)
{
t.AssetAutoReleaseInterval = assetAutoReleaseInterval;
}
else
{
m_AssetAutoReleaseInterval.floatValue = assetAutoReleaseInterval;
}
}
int assetCapacity = EditorGUILayout.DelayedIntField("Asset Capacity", m_AssetCapacity.intValue);
if (assetCapacity != m_AssetCapacity.intValue)
{
if (EditorApplication.isPlaying)
{
t.AssetCapacity = assetCapacity;
}
else
{
m_AssetCapacity.intValue = assetCapacity;
}
}
float assetExpireTime = EditorGUILayout.DelayedFloatField("Asset Expire Time", m_AssetExpireTime.floatValue);
if (assetExpireTime != m_AssetExpireTime.floatValue)
{
if (EditorApplication.isPlaying)
{
t.AssetExpireTime = assetExpireTime;
}
else
{
m_AssetExpireTime.floatValue = assetExpireTime;
}
}
int assetPriority = EditorGUILayout.DelayedIntField("Asset Priority", m_AssetPriority.intValue);
if (assetPriority != m_AssetPriority.intValue)
{
if (EditorApplication.isPlaying)
{
t.AssetPriority = assetPriority;
}
else
{
m_AssetPriority.intValue = assetPriority;
}
}
float resourceAutoReleaseInterval = EditorGUILayout.DelayedFloatField("Resource Auto Release Interval", m_ResourceAutoReleaseInterval.floatValue);
if (resourceAutoReleaseInterval != m_ResourceAutoReleaseInterval.floatValue)
{
if (EditorApplication.isPlaying)
{
t.ResourceAutoReleaseInterval = resourceAutoReleaseInterval;
}
else
{
m_ResourceAutoReleaseInterval.floatValue = resourceAutoReleaseInterval;
}
}
int resourceCapacity = EditorGUILayout.DelayedIntField("Resource Capacity", m_ResourceCapacity.intValue);
if (resourceCapacity != m_ResourceCapacity.intValue)
{
if (EditorApplication.isPlaying)
{
t.ResourceCapacity = resourceCapacity;
}
else
{
m_ResourceCapacity.intValue = resourceCapacity;
}
}
float resourceExpireTime = EditorGUILayout.DelayedFloatField("Resource Expire Time", m_ResourceExpireTime.floatValue);
if (resourceExpireTime != m_ResourceExpireTime.floatValue)
{
if (EditorApplication.isPlaying)
{
t.ResourceExpireTime = resourceExpireTime;
}
else
{
m_ResourceExpireTime.floatValue = resourceExpireTime;
}
}
int resourcePriority = EditorGUILayout.DelayedIntField("Resource Priority", m_ResourcePriority.intValue);
if (resourcePriority != m_ResourcePriority.intValue)
{
if (EditorApplication.isPlaying)
{
t.ResourcePriority = resourcePriority;
}
else
{
m_ResourcePriority.intValue = resourcePriority;
}
}
if (m_ResourceModeIndex > 0)
{
string updatePrefixUri = EditorGUILayout.DelayedTextField("Update Prefix Uri", m_UpdatePrefixUri.stringValue);
if (updatePrefixUri != m_UpdatePrefixUri.stringValue)
{
if (EditorApplication.isPlaying)
{
t.UpdatePrefixUri = updatePrefixUri;
}
else
{
m_UpdatePrefixUri.stringValue = updatePrefixUri;
}
}
int generateReadWriteVersionListLength = EditorGUILayout.DelayedIntField("Generate Read-Write Version List Length", m_GenerateReadWriteVersionListLength.intValue);
if (generateReadWriteVersionListLength != m_GenerateReadWriteVersionListLength.intValue)
{
if (EditorApplication.isPlaying)
{
t.GenerateReadWriteVersionListLength = generateReadWriteVersionListLength;
}
else
{
m_GenerateReadWriteVersionListLength.intValue = generateReadWriteVersionListLength;
}
}
int updateRetryCount = EditorGUILayout.DelayedIntField("Update Retry Count", m_UpdateRetryCount.intValue);
if (updateRetryCount != m_UpdateRetryCount.intValue)
{
if (EditorApplication.isPlaying)
{
t.UpdateRetryCount = updateRetryCount;
}
else
{
m_UpdateRetryCount.intValue = updateRetryCount;
}
}
}
}
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_InstanceRoot);
m_ResourceHelperInfo.Draw();
m_LoadResourceAgentHelperInfo.Draw();
m_LoadResourceAgentHelperCount.intValue = EditorGUILayout.IntSlider("Load Resource Agent Helper Count", m_LoadResourceAgentHelperCount.intValue, 1, 128);
}
EditorGUI.EndDisabledGroup();
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Unload Unused Assets", Utility.Text.Format("{0:F2} / {1:F2}", t.LastUnloadUnusedAssetsOperationElapseSeconds, t.MaxUnloadUnusedAssetsInterval));
EditorGUILayout.LabelField("Read-Only Path", t.ReadOnlyPath.ToString());
EditorGUILayout.LabelField("Read-Write Path", t.ReadWritePath.ToString());
EditorGUILayout.LabelField("Current Variant", t.CurrentVariant ?? "<Unknwon>");
EditorGUILayout.LabelField("Applicable Game Version", isEditorResourceMode ? "N/A" : t.ApplicableGameVersion ?? "<Unknwon>");
EditorGUILayout.LabelField("Internal Resource Version", isEditorResourceMode ? "N/A" : t.InternalResourceVersion.ToString());
EditorGUILayout.LabelField("Asset Count", isEditorResourceMode ? "N/A" : t.AssetCount.ToString());
EditorGUILayout.LabelField("Resource Count", isEditorResourceMode ? "N/A" : t.ResourceCount.ToString());
EditorGUILayout.LabelField("Resource Group Count", isEditorResourceMode ? "N/A" : t.ResourceGroupCount.ToString());
if (m_ResourceModeIndex > 0)
{
EditorGUILayout.LabelField("Applying Resource Pack Path", isEditorResourceMode ? "N/A" : t.ApplyingResourcePackPath ?? "<Unknwon>");
EditorGUILayout.LabelField("Apply Waiting Count", isEditorResourceMode ? "N/A" : t.ApplyWaitingCount.ToString());
EditorGUILayout.LabelField("Updating Resource Group", isEditorResourceMode ? "N/A" : t.UpdatingResourceGroup != null ? t.UpdatingResourceGroup.Name : "<Unknwon>");
EditorGUILayout.LabelField("Update Waiting Count", isEditorResourceMode ? "N/A" : t.UpdateWaitingCount.ToString());
EditorGUILayout.LabelField("Update Waiting While Playing Count", isEditorResourceMode ? "N/A" : t.UpdateWaitingWhilePlayingCount.ToString());
EditorGUILayout.LabelField("Update Candidate Count", isEditorResourceMode ? "N/A" : t.UpdateCandidateCount.ToString());
}
EditorGUILayout.LabelField("Load Total Agent Count", isEditorResourceMode ? "N/A" : t.LoadTotalAgentCount.ToString());
EditorGUILayout.LabelField("Load Free Agent Count", isEditorResourceMode ? "N/A" : t.LoadFreeAgentCount.ToString());
EditorGUILayout.LabelField("Load Working Agent Count", isEditorResourceMode ? "N/A" : t.LoadWorkingAgentCount.ToString());
EditorGUILayout.LabelField("Load Waiting Task Count", isEditorResourceMode ? "N/A" : t.LoadWaitingTaskCount.ToString());
if (!isEditorResourceMode)
{
EditorGUILayout.BeginVertical("box");
{
TaskInfo[] loadAssetInfos = t.GetAllLoadAssetInfos();
if (loadAssetInfos.Length > 0)
{
foreach (TaskInfo loadAssetInfo in loadAssetInfos)
{
DrawLoadAssetInfo(loadAssetInfo);
}
if (GUILayout.Button("Export CSV Data"))
{
string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, "Load Asset Task Data.csv", string.Empty);
if (!string.IsNullOrEmpty(exportFileName))
{
try
{
int index = 0;
string[] data = new string[loadAssetInfos.Length + 1];
data[index++] = "Load Asset Name,Serial Id,Priority,Status";
foreach (TaskInfo loadAssetInfo in loadAssetInfos)
{
data[index++] = Utility.Text.Format("{0},{1},{2},{3}", loadAssetInfo.Description, loadAssetInfo.SerialId, loadAssetInfo.Priority, loadAssetInfo.Status);
}
File.WriteAllLines(exportFileName, data, Encoding.UTF8);
Debug.Log(Utility.Text.Format("Export load asset task CSV data to '{0}' success.", exportFileName));
}
catch (Exception exception)
{
Debug.LogError(Utility.Text.Format("Export load asset task CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception));
}
}
}
}
else
{
GUILayout.Label("Load Asset Task is Empty ...");
}
}
EditorGUILayout.EndVertical();
}
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_ResourceMode = serializedObject.FindProperty("m_ResourceMode");
m_ReadWritePathType = serializedObject.FindProperty("m_ReadWritePathType");
m_MinUnloadUnusedAssetsInterval = serializedObject.FindProperty("m_MinUnloadUnusedAssetsInterval");
m_MaxUnloadUnusedAssetsInterval = serializedObject.FindProperty("m_MaxUnloadUnusedAssetsInterval");
m_AssetAutoReleaseInterval = serializedObject.FindProperty("m_AssetAutoReleaseInterval");
m_AssetCapacity = serializedObject.FindProperty("m_AssetCapacity");
m_AssetExpireTime = serializedObject.FindProperty("m_AssetExpireTime");
m_AssetPriority = serializedObject.FindProperty("m_AssetPriority");
m_ResourceAutoReleaseInterval = serializedObject.FindProperty("m_ResourceAutoReleaseInterval");
m_ResourceCapacity = serializedObject.FindProperty("m_ResourceCapacity");
m_ResourceExpireTime = serializedObject.FindProperty("m_ResourceExpireTime");
m_ResourcePriority = serializedObject.FindProperty("m_ResourcePriority");
m_UpdatePrefixUri = serializedObject.FindProperty("m_UpdatePrefixUri");
m_GenerateReadWriteVersionListLength = serializedObject.FindProperty("m_GenerateReadWriteVersionListLength");
m_UpdateRetryCount = serializedObject.FindProperty("m_UpdateRetryCount");
m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot");
m_LoadResourceAgentHelperCount = serializedObject.FindProperty("m_LoadResourceAgentHelperCount");
m_EditorResourceModeFieldInfo = target.GetType().GetField("m_EditorResourceMode", BindingFlags.NonPublic | BindingFlags.Instance);
m_ResourceHelperInfo.Init(serializedObject);
m_LoadResourceAgentHelperInfo.Init(serializedObject);
RefreshModes();
RefreshTypeNames();
}
private void DrawLoadAssetInfo(TaskInfo loadAssetInfo)
{
EditorGUILayout.LabelField(loadAssetInfo.Description, Utility.Text.Format("[SerialId]{0} [Priority]{1} [Status]{2}", loadAssetInfo.SerialId, loadAssetInfo.Priority, loadAssetInfo.Status));
}
private void RefreshModes()
{
m_ResourceModeIndex = m_ResourceMode.enumValueIndex > 0 ? m_ResourceMode.enumValueIndex - 1 : 0;
}
private void RefreshTypeNames()
{
m_ResourceHelperInfo.Refresh();
m_LoadResourceAgentHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

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

View File

@ -0,0 +1,75 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using UnityEditor;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(SceneComponent))]
internal sealed class SceneComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_EnableLoadSceneUpdateEvent = null;
private SerializedProperty m_EnableLoadSceneDependencyAssetEvent = null;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
SceneComponent t = (SceneComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_EnableLoadSceneUpdateEvent);
EditorGUILayout.PropertyField(m_EnableLoadSceneDependencyAssetEvent);
}
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Loaded Scene Asset Names", GetSceneNameString(t.GetLoadedSceneAssetNames()));
EditorGUILayout.LabelField("Loading Scene Asset Names", GetSceneNameString(t.GetLoadingSceneAssetNames()));
EditorGUILayout.LabelField("Unloading Scene Asset Names", GetSceneNameString(t.GetUnloadingSceneAssetNames()));
EditorGUILayout.ObjectField("Main Camera", t.MainCamera, typeof(Camera), true);
Repaint();
}
}
private void OnEnable()
{
m_EnableLoadSceneUpdateEvent = serializedObject.FindProperty("m_EnableLoadSceneUpdateEvent");
m_EnableLoadSceneDependencyAssetEvent = serializedObject.FindProperty("m_EnableLoadSceneDependencyAssetEvent");
}
private string GetSceneNameString(string[] sceneAssetNames)
{
if (sceneAssetNames == null || sceneAssetNames.Length <= 0)
{
return "<Empty>";
}
string sceneNameString = string.Empty;
foreach (string sceneAssetName in sceneAssetNames)
{
if (!string.IsNullOrEmpty(sceneNameString))
{
sceneNameString += ", ";
}
sceneNameString += SceneComponent.GetSceneName(sceneAssetName);
}
return sceneNameString;
}
}
}

View File

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

View File

@ -0,0 +1,81 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using UnityEditor;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(SettingComponent))]
internal sealed class SettingComponentInspector : GameFrameworkInspector
{
private HelperInfo<SettingHelperBase> m_SettingHelperInfo = new HelperInfo<SettingHelperBase>("Setting");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
SettingComponent t = (SettingComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
m_SettingHelperInfo.Draw();
}
EditorGUI.EndDisabledGroup();
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Setting Count", t.Count >= 0 ? t.Count.ToString() : "<Unknown>");
if (t.Count > 0)
{
string[] settingNames = t.GetAllSettingNames();
foreach (string settingName in settingNames)
{
EditorGUILayout.LabelField(settingName, t.GetString(settingName));
}
}
}
if (EditorApplication.isPlaying)
{
if (GUILayout.Button("Save Settings"))
{
t.Save();
}
if (GUILayout.Button("Remove All Settings"))
{
t.RemoveAllSettings();
}
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_SettingHelperInfo.Init(serializedObject);
RefreshTypeNames();
}
private void RefreshTypeNames()
{
m_SettingHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

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

View File

@ -0,0 +1,87 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using UnityEditor;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(SoundComponent))]
internal sealed class SoundComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_EnablePlaySoundUpdateEvent = null;
private SerializedProperty m_EnablePlaySoundDependencyAssetEvent = null;
private SerializedProperty m_InstanceRoot = null;
private SerializedProperty m_AudioMixer = null;
private SerializedProperty m_SoundGroups = null;
private HelperInfo<SoundHelperBase> m_SoundHelperInfo = new HelperInfo<SoundHelperBase>("Sound");
private HelperInfo<SoundGroupHelperBase> m_SoundGroupHelperInfo = new HelperInfo<SoundGroupHelperBase>("SoundGroup");
private HelperInfo<SoundAgentHelperBase> m_SoundAgentHelperInfo = new HelperInfo<SoundAgentHelperBase>("SoundAgent");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
SoundComponent t = (SoundComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_EnablePlaySoundUpdateEvent);
EditorGUILayout.PropertyField(m_EnablePlaySoundDependencyAssetEvent);
EditorGUILayout.PropertyField(m_InstanceRoot);
EditorGUILayout.PropertyField(m_AudioMixer);
m_SoundHelperInfo.Draw();
m_SoundGroupHelperInfo.Draw();
m_SoundAgentHelperInfo.Draw();
EditorGUILayout.PropertyField(m_SoundGroups, true);
}
EditorGUI.EndDisabledGroup();
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Sound Group Count", t.SoundGroupCount.ToString());
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_EnablePlaySoundUpdateEvent = serializedObject.FindProperty("m_EnablePlaySoundUpdateEvent");
m_EnablePlaySoundDependencyAssetEvent = serializedObject.FindProperty("m_EnablePlaySoundDependencyAssetEvent");
m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot");
m_AudioMixer = serializedObject.FindProperty("m_AudioMixer");
m_SoundGroups = serializedObject.FindProperty("m_SoundGroups");
m_SoundHelperInfo.Init(serializedObject);
m_SoundGroupHelperInfo.Init(serializedObject);
m_SoundAgentHelperInfo.Init(serializedObject);
RefreshTypeNames();
}
private void RefreshTypeNames()
{
m_SoundHelperInfo.Refresh();
m_SoundGroupHelperInfo.Refresh();
m_SoundAgentHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

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

View File

@ -0,0 +1,154 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using UnityEditor;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(UIComponent))]
internal sealed class UIComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_EnableOpenUIFormSuccessEvent = null;
private SerializedProperty m_EnableOpenUIFormFailureEvent = null;
private SerializedProperty m_EnableOpenUIFormUpdateEvent = null;
private SerializedProperty m_EnableOpenUIFormDependencyAssetEvent = null;
private SerializedProperty m_EnableCloseUIFormCompleteEvent = null;
private SerializedProperty m_InstanceAutoReleaseInterval = null;
private SerializedProperty m_InstanceCapacity = null;
private SerializedProperty m_InstanceExpireTime = null;
private SerializedProperty m_InstancePriority = null;
private SerializedProperty m_InstanceRoot = null;
private SerializedProperty m_UIGroups = null;
private HelperInfo<UIFormHelperBase> m_UIFormHelperInfo = new HelperInfo<UIFormHelperBase>("UIForm");
private HelperInfo<UIGroupHelperBase> m_UIGroupHelperInfo = new HelperInfo<UIGroupHelperBase>("UIGroup");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
UIComponent t = (UIComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_EnableOpenUIFormSuccessEvent);
EditorGUILayout.PropertyField(m_EnableOpenUIFormFailureEvent);
EditorGUILayout.PropertyField(m_EnableOpenUIFormUpdateEvent);
EditorGUILayout.PropertyField(m_EnableOpenUIFormDependencyAssetEvent);
EditorGUILayout.PropertyField(m_EnableCloseUIFormCompleteEvent);
}
EditorGUI.EndDisabledGroup();
float instanceAutoReleaseInterval = EditorGUILayout.DelayedFloatField("Instance Auto Release Interval", m_InstanceAutoReleaseInterval.floatValue);
if (instanceAutoReleaseInterval != m_InstanceAutoReleaseInterval.floatValue)
{
if (EditorApplication.isPlaying)
{
t.InstanceAutoReleaseInterval = instanceAutoReleaseInterval;
}
else
{
m_InstanceAutoReleaseInterval.floatValue = instanceAutoReleaseInterval;
}
}
int instanceCapacity = EditorGUILayout.DelayedIntField("Instance Capacity", m_InstanceCapacity.intValue);
if (instanceCapacity != m_InstanceCapacity.intValue)
{
if (EditorApplication.isPlaying)
{
t.InstanceCapacity = instanceCapacity;
}
else
{
m_InstanceCapacity.intValue = instanceCapacity;
}
}
float instanceExpireTime = EditorGUILayout.DelayedFloatField("Instance Expire Time", m_InstanceExpireTime.floatValue);
if (instanceExpireTime != m_InstanceExpireTime.floatValue)
{
if (EditorApplication.isPlaying)
{
t.InstanceExpireTime = instanceExpireTime;
}
else
{
m_InstanceExpireTime.floatValue = instanceExpireTime;
}
}
int instancePriority = EditorGUILayout.DelayedIntField("Instance Priority", m_InstancePriority.intValue);
if (instancePriority != m_InstancePriority.intValue)
{
if (EditorApplication.isPlaying)
{
t.InstancePriority = instancePriority;
}
else
{
m_InstancePriority.intValue = instancePriority;
}
}
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_InstanceRoot);
m_UIFormHelperInfo.Draw();
m_UIGroupHelperInfo.Draw();
EditorGUILayout.PropertyField(m_UIGroups, true);
}
EditorGUI.EndDisabledGroup();
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("UI Group Count", t.UIGroupCount.ToString());
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_EnableOpenUIFormSuccessEvent = serializedObject.FindProperty("m_EnableOpenUIFormSuccessEvent");
m_EnableOpenUIFormFailureEvent = serializedObject.FindProperty("m_EnableOpenUIFormFailureEvent");
m_EnableOpenUIFormUpdateEvent = serializedObject.FindProperty("m_EnableOpenUIFormUpdateEvent");
m_EnableOpenUIFormDependencyAssetEvent = serializedObject.FindProperty("m_EnableOpenUIFormDependencyAssetEvent");
m_EnableCloseUIFormCompleteEvent = serializedObject.FindProperty("m_EnableCloseUIFormCompleteEvent");
m_InstanceAutoReleaseInterval = serializedObject.FindProperty("m_InstanceAutoReleaseInterval");
m_InstanceCapacity = serializedObject.FindProperty("m_InstanceCapacity");
m_InstanceExpireTime = serializedObject.FindProperty("m_InstanceExpireTime");
m_InstancePriority = serializedObject.FindProperty("m_InstancePriority");
m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot");
m_UIGroups = serializedObject.FindProperty("m_UIGroups");
m_UIFormHelperInfo.Init(serializedObject);
m_UIGroupHelperInfo.Init(serializedObject);
RefreshTypeNames();
}
private void RefreshTypeNames()
{
m_UIFormHelperInfo.Refresh();
m_UIGroupHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

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

View File

@ -0,0 +1,141 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using System;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace UnityGameFramework.Editor
{
[CustomEditor(typeof(WebRequestComponent))]
internal sealed class WebRequestComponentInspector : GameFrameworkInspector
{
private SerializedProperty m_InstanceRoot = null;
private SerializedProperty m_WebRequestAgentHelperCount = null;
private SerializedProperty m_Timeout = null;
private HelperInfo<WebRequestAgentHelperBase> m_WebRequestAgentHelperInfo = new HelperInfo<WebRequestAgentHelperBase>("WebRequestAgent");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
WebRequestComponent t = (WebRequestComponent)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_InstanceRoot);
m_WebRequestAgentHelperInfo.Draw();
m_WebRequestAgentHelperCount.intValue = EditorGUILayout.IntSlider("Web Request Agent Helper Count", m_WebRequestAgentHelperCount.intValue, 1, 16);
}
EditorGUI.EndDisabledGroup();
float timeout = EditorGUILayout.Slider("Timeout", m_Timeout.floatValue, 0f, 120f);
if (timeout != m_Timeout.floatValue)
{
if (EditorApplication.isPlaying)
{
t.Timeout = timeout;
}
else
{
m_Timeout.floatValue = timeout;
}
}
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.LabelField("Total Agent Count", t.TotalAgentCount.ToString());
EditorGUILayout.LabelField("Free Agent Count", t.FreeAgentCount.ToString());
EditorGUILayout.LabelField("Working Agent Count", t.WorkingAgentCount.ToString());
EditorGUILayout.LabelField("Waiting Agent Count", t.WaitingTaskCount.ToString());
EditorGUILayout.BeginVertical("box");
{
TaskInfo[] webRequestInfos = t.GetAllWebRequestInfos();
if (webRequestInfos.Length > 0)
{
foreach (TaskInfo webRequestInfo in webRequestInfos)
{
DrawWebRequestInfo(webRequestInfo);
}
if (GUILayout.Button("Export CSV Data"))
{
string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, "WebRequest Task Data.csv", string.Empty);
if (!string.IsNullOrEmpty(exportFileName))
{
try
{
int index = 0;
string[] data = new string[webRequestInfos.Length + 1];
data[index++] = "WebRequest Uri,Serial Id,Tag,Priority,Status";
foreach (TaskInfo webRequestInfo in webRequestInfos)
{
data[index++] = Utility.Text.Format("{0},{1},{2},{3},{4}", webRequestInfo.Description, webRequestInfo.SerialId, webRequestInfo.Tag ?? string.Empty, webRequestInfo.Priority, webRequestInfo.Status);
}
File.WriteAllLines(exportFileName, data, Encoding.UTF8);
Debug.Log(Utility.Text.Format("Export web request task CSV data to '{0}' success.", exportFileName));
}
catch (Exception exception)
{
Debug.LogError(Utility.Text.Format("Export web request task CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception));
}
}
}
}
else
{
GUILayout.Label("WebRequset Task is Empty ...");
}
}
EditorGUILayout.EndVertical();
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot");
m_WebRequestAgentHelperCount = serializedObject.FindProperty("m_WebRequestAgentHelperCount");
m_Timeout = serializedObject.FindProperty("m_Timeout");
m_WebRequestAgentHelperInfo.Init(serializedObject);
RefreshTypeNames();
}
private void DrawWebRequestInfo(TaskInfo webRequestInfo)
{
EditorGUILayout.LabelField(webRequestInfo.Description, Utility.Text.Format("[SerialId]{0} [Tag]{1} [Priority]{2} [Status]{3}", webRequestInfo.SerialId, webRequestInfo.Tag ?? "<None>", webRequestInfo.Priority, webRequestInfo.Status));
}
private void RefreshTypeNames()
{
m_WebRequestAgentHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

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

View File

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

View File

@ -0,0 +1,133 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using UnityEditor;
using UnityEngine;
namespace UnityGameFramework.Editor
{
/// <summary>
/// 构建配置相关的实用函数。
/// </summary>
internal static class BuildSettings
{
private static readonly string s_ConfigurationPath = null;
private static readonly List<string> s_DefaultSceneNames = new List<string>();
private static readonly List<string> s_SearchScenePaths = new List<string>();
static BuildSettings()
{
s_ConfigurationPath = Type.GetConfigurationPath<BuildSettingsConfigPathAttribute>() ?? Utility.Path.GetRegularPath(Path.Combine(Application.dataPath, "GameFramework/Configs/BuildSettings.xml"));
s_DefaultSceneNames.Clear();
s_SearchScenePaths.Clear();
if (!File.Exists(s_ConfigurationPath))
{
return;
}
try
{
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(s_ConfigurationPath);
XmlNode xmlRoot = xmlDocument.SelectSingleNode("UnityGameFramework");
XmlNode xmlBuildSettings = xmlRoot.SelectSingleNode("BuildSettings");
XmlNode xmlDefaultScenes = xmlBuildSettings.SelectSingleNode("DefaultScenes");
XmlNode xmlSearchScenePaths = xmlBuildSettings.SelectSingleNode("SearchScenePaths");
XmlNodeList xmlNodeList = null;
XmlNode xmlNode = null;
xmlNodeList = xmlDefaultScenes.ChildNodes;
for (int i = 0; i < xmlNodeList.Count; i++)
{
xmlNode = xmlNodeList.Item(i);
if (xmlNode.Name != "DefaultScene")
{
continue;
}
string defaultSceneName = xmlNode.Attributes.GetNamedItem("Name").Value;
s_DefaultSceneNames.Add(defaultSceneName);
}
xmlNodeList = xmlSearchScenePaths.ChildNodes;
for (int i = 0; i < xmlNodeList.Count; i++)
{
xmlNode = xmlNodeList.Item(i);
if (xmlNode.Name != "SearchScenePath")
{
continue;
}
string searchScenePath = xmlNode.Attributes.GetNamedItem("Path").Value;
s_SearchScenePaths.Add(searchScenePath);
}
}
catch
{
}
}
/// <summary>
/// 将构建场景设置为默认。
/// </summary>
[MenuItem("Game Framework/Scenes in Build Settings/Default Scenes", false, 20)]
public static void DefaultScenes()
{
HashSet<string> sceneNames = new HashSet<string>();
foreach (string sceneName in s_DefaultSceneNames)
{
sceneNames.Add(sceneName);
}
List<EditorBuildSettingsScene> scenes = new List<EditorBuildSettingsScene>();
foreach (string sceneName in sceneNames)
{
scenes.Add(new EditorBuildSettingsScene(sceneName, true));
}
EditorBuildSettings.scenes = scenes.ToArray();
Debug.Log("Set scenes of build settings to default scenes.");
}
/// <summary>
/// 将构建场景设置为所有。
/// </summary>
[MenuItem("Game Framework/Scenes in Build Settings/All Scenes", false, 21)]
public static void AllScenes()
{
HashSet<string> sceneNames = new HashSet<string>();
foreach (string sceneName in s_DefaultSceneNames)
{
sceneNames.Add(sceneName);
}
string[] sceneGuids = AssetDatabase.FindAssets("t:Scene", s_SearchScenePaths.ToArray());
foreach (string sceneGuid in sceneGuids)
{
string sceneName = AssetDatabase.GUIDToAssetPath(sceneGuid);
sceneNames.Add(sceneName);
}
List<EditorBuildSettingsScene> scenes = new List<EditorBuildSettingsScene>();
foreach (string sceneName in sceneNames)
{
scenes.Add(new EditorBuildSettingsScene(sceneName, true));
}
EditorBuildSettings.scenes = scenes.ToArray();
Debug.Log("Set scenes of build settings to all scenes.");
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b487342e56dd1f649bf6f423bbddd3ea
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
{
/// <summary>
/// BuildSettings 配置路径属性。
/// </summary>
public sealed class BuildSettingsConfigPathAttribute : ConfigPathAttribute
{
}
}

View File

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

View File

@ -0,0 +1,18 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System;
namespace UnityGameFramework.Editor
{
/// <summary>
/// 配置路径属性。
/// </summary>
public abstract class ConfigPathAttribute : Attribute
{
}
}

View File

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

View File

@ -0,0 +1,35 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using UnityEditor;
using UnityEngine;
namespace UnityGameFramework.Editor
{
/// <summary>
/// 帮助相关的实用函数。
/// </summary>
public static class Help
{
[MenuItem("Game Framework/Documentation", false, 90)]
public static void ShowDocumentation()
{
ShowHelp("https://gameframework.cn/document/");
}
[MenuItem("Game Framework/API Reference", false, 91)]
public static void ShowApiReference()
{
ShowHelp("https://gameframework.cn/api/");
}
private static void ShowHelp(string uri)
{
Application.OpenURL(uri);
}
}
}

View File

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

View File

@ -0,0 +1,97 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
namespace UnityGameFramework.Editor
{
internal sealed class HelperInfo<T> where T : MonoBehaviour
{
private const string CustomOptionName = "<Custom>";
private readonly string m_Name;
private SerializedProperty m_HelperTypeName;
private SerializedProperty m_CustomHelper;
private string[] m_HelperTypeNames;
private int m_HelperTypeNameIndex;
public HelperInfo(string name)
{
m_Name = name;
m_HelperTypeName = null;
m_CustomHelper = null;
m_HelperTypeNames = null;
m_HelperTypeNameIndex = 0;
}
public void Init(SerializedObject serializedObject)
{
m_HelperTypeName = serializedObject.FindProperty(Utility.Text.Format("m_{0}HelperTypeName", m_Name));
m_CustomHelper = serializedObject.FindProperty(Utility.Text.Format("m_Custom{0}Helper", m_Name));
}
public void Draw()
{
string displayName = FieldNameForDisplay(m_Name);
int selectedIndex = EditorGUILayout.Popup(Utility.Text.Format("{0} Helper", displayName), m_HelperTypeNameIndex, m_HelperTypeNames);
if (selectedIndex != m_HelperTypeNameIndex)
{
m_HelperTypeNameIndex = selectedIndex;
m_HelperTypeName.stringValue = selectedIndex <= 0 ? null : m_HelperTypeNames[selectedIndex];
}
if (m_HelperTypeNameIndex <= 0)
{
EditorGUILayout.PropertyField(m_CustomHelper);
if (m_CustomHelper.objectReferenceValue == null)
{
EditorGUILayout.HelpBox(Utility.Text.Format("You must set Custom {0} Helper.", displayName), MessageType.Error);
}
}
}
public void Refresh()
{
List<string> helperTypeNameList = new List<string>
{
CustomOptionName
};
helperTypeNameList.AddRange(Type.GetRuntimeTypeNames(typeof(T)));
m_HelperTypeNames = helperTypeNameList.ToArray();
m_HelperTypeNameIndex = 0;
if (!string.IsNullOrEmpty(m_HelperTypeName.stringValue))
{
m_HelperTypeNameIndex = helperTypeNameList.IndexOf(m_HelperTypeName.stringValue);
if (m_HelperTypeNameIndex <= 0)
{
m_HelperTypeNameIndex = 0;
m_HelperTypeName.stringValue = null;
}
}
}
private string FieldNameForDisplay(string fieldName)
{
if (string.IsNullOrEmpty(fieldName))
{
return string.Empty;
}
string str = Regex.Replace(fieldName, @"^m_", string.Empty);
str = Regex.Replace(str, @"((?<=[a-z])[A-Z]|[A-Z](?=[a-z]))", @" $1").TrimStart();
return str;
}
}
}

View File

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

View File

@ -0,0 +1,122 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
#if !UNITY_2019_1_OR_NEWER
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditorInternal;
using UnityEngine;
namespace UnityGameFramework.Editor
{
/// <summary>
/// 日志重定向相关的实用函数。
/// </summary>
internal static class LogRedirection
{
private static readonly Regex LogRegex = new Regex(@" \(at (.+)\:(\d+)\)\r?\n");
[OnOpenAsset(0)]
private static bool OnOpenAsset(int instanceId, int line)
{
string selectedStackTrace = GetSelectedStackTrace();
if (string.IsNullOrEmpty(selectedStackTrace))
{
return false;
}
if (!selectedStackTrace.Contains("UnityGameFramework.Runtime.DefaultLogHelper:Log"))
{
return false;
}
Match match = LogRegex.Match(selectedStackTrace);
if (!match.Success)
{
return false;
}
if (!match.Groups[1].Value.Contains("DefaultLogHelper.cs"))
{
return false;
}
match = match.NextMatch();
if (!match.Success)
{
return false;
}
if (match.Groups[1].Value.Contains("GameFrameworkLog.cs"))
{
match = match.NextMatch();
if (!match.Success)
{
return false;
}
}
if (match.Groups[1].Value.Contains("Log.cs"))
{
match = match.NextMatch();
if (!match.Success)
{
return false;
}
}
InternalEditorUtility.OpenFileAtLineExternal(Path.Combine(Application.dataPath, match.Groups[1].Value.Substring(7)), int.Parse(match.Groups[2].Value));
return true;
}
private static string GetSelectedStackTrace()
{
Assembly editorWindowAssembly = typeof(EditorWindow).Assembly;
if (editorWindowAssembly == null)
{
return null;
}
System.Type consoleWindowType = editorWindowAssembly.GetType("UnityEditor.ConsoleWindow");
if (consoleWindowType == null)
{
return null;
}
FieldInfo consoleWindowFieldInfo = consoleWindowType.GetField("ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic);
if (consoleWindowFieldInfo == null)
{
return null;
}
EditorWindow consoleWindow = consoleWindowFieldInfo.GetValue(null) as EditorWindow;
if (consoleWindow == null)
{
return null;
}
if (consoleWindow != EditorWindow.focusedWindow)
{
return null;
}
FieldInfo activeTextFieldInfo = consoleWindowType.GetField("m_ActiveText", BindingFlags.Instance | BindingFlags.NonPublic);
if (activeTextFieldInfo == null)
{
return null;
}
return (string)activeTextFieldInfo.GetValue(consoleWindow);
}
}
}
#endif

View File

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

View File

@ -0,0 +1,179 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using UnityEditor;
namespace UnityGameFramework.Editor
{
/// <summary>
/// 日志脚本宏定义。
/// </summary>
public static class LogScriptingDefineSymbols
{
private const string EnableLogScriptingDefineSymbol = "ENABLE_LOG";
private const string EnableDebugAndAboveLogScriptingDefineSymbol = "ENABLE_DEBUG_AND_ABOVE_LOG";
private const string EnableInfoAndAboveLogScriptingDefineSymbol = "ENABLE_INFO_AND_ABOVE_LOG";
private const string EnableWarningAndAboveLogScriptingDefineSymbol = "ENABLE_WARNING_AND_ABOVE_LOG";
private const string EnableErrorAndAboveLogScriptingDefineSymbol = "ENABLE_ERROR_AND_ABOVE_LOG";
private const string EnableFatalAndAboveLogScriptingDefineSymbol = "ENABLE_FATAL_AND_ABOVE_LOG";
private const string EnableDebugLogScriptingDefineSymbol = "ENABLE_DEBUG_LOG";
private const string EnableInfoLogScriptingDefineSymbol = "ENABLE_INFO_LOG";
private const string EnableWarningLogScriptingDefineSymbol = "ENABLE_WARNING_LOG";
private const string EnableErrorLogScriptingDefineSymbol = "ENABLE_ERROR_LOG";
private const string EnableFatalLogScriptingDefineSymbol = "ENABLE_FATAL_LOG";
private static readonly string[] AboveLogScriptingDefineSymbols = new string[]
{
EnableDebugAndAboveLogScriptingDefineSymbol,
EnableInfoAndAboveLogScriptingDefineSymbol,
EnableWarningAndAboveLogScriptingDefineSymbol,
EnableErrorAndAboveLogScriptingDefineSymbol,
EnableFatalAndAboveLogScriptingDefineSymbol
};
private static readonly string[] SpecifyLogScriptingDefineSymbols = new string[]
{
EnableDebugLogScriptingDefineSymbol,
EnableInfoLogScriptingDefineSymbol,
EnableWarningLogScriptingDefineSymbol,
EnableErrorLogScriptingDefineSymbol,
EnableFatalLogScriptingDefineSymbol
};
/// <summary>
/// 禁用所有日志脚本宏定义。
/// </summary>
[MenuItem("Game Framework/Log Scripting Define Symbols/Disable All Logs", false, 30)]
public static void DisableAllLogs()
{
ScriptingDefineSymbols.RemoveScriptingDefineSymbol(EnableLogScriptingDefineSymbol);
foreach (string specifyLogScriptingDefineSymbol in SpecifyLogScriptingDefineSymbols)
{
ScriptingDefineSymbols.RemoveScriptingDefineSymbol(specifyLogScriptingDefineSymbol);
}
foreach (string aboveLogScriptingDefineSymbol in AboveLogScriptingDefineSymbols)
{
ScriptingDefineSymbols.RemoveScriptingDefineSymbol(aboveLogScriptingDefineSymbol);
}
}
/// <summary>
/// 开启所有日志脚本宏定义。
/// </summary>
[MenuItem("Game Framework/Log Scripting Define Symbols/Enable All Logs", false, 31)]
public static void EnableAllLogs()
{
DisableAllLogs();
ScriptingDefineSymbols.AddScriptingDefineSymbol(EnableLogScriptingDefineSymbol);
}
/// <summary>
/// 开启调试及以上级别的日志脚本宏定义。
/// </summary>
[MenuItem("Game Framework/Log Scripting Define Symbols/Enable Debug And Above Logs", false, 32)]
public static void EnableDebugAndAboveLogs()
{
SetAboveLogScriptingDefineSymbol(EnableDebugAndAboveLogScriptingDefineSymbol);
}
/// <summary>
/// 开启信息及以上级别的日志脚本宏定义。
/// </summary>
[MenuItem("Game Framework/Log Scripting Define Symbols/Enable Info And Above Logs", false, 33)]
public static void EnableInfoAndAboveLogs()
{
SetAboveLogScriptingDefineSymbol(EnableInfoAndAboveLogScriptingDefineSymbol);
}
/// <summary>
/// 开启警告及以上级别的日志脚本宏定义。
/// </summary>
[MenuItem("Game Framework/Log Scripting Define Symbols/Enable Warning And Above Logs", false, 34)]
public static void EnableWarningAndAboveLogs()
{
SetAboveLogScriptingDefineSymbol(EnableWarningAndAboveLogScriptingDefineSymbol);
}
/// <summary>
/// 开启错误及以上级别的日志脚本宏定义。
/// </summary>
[MenuItem("Game Framework/Log Scripting Define Symbols/Enable Error And Above Logs", false, 35)]
public static void EnableErrorAndAboveLogs()
{
SetAboveLogScriptingDefineSymbol(EnableErrorAndAboveLogScriptingDefineSymbol);
}
/// <summary>
/// 开启严重错误及以上级别的日志脚本宏定义。
/// </summary>
[MenuItem("Game Framework/Log Scripting Define Symbols/Enable Fatal And Above Logs", false, 36)]
public static void EnableFatalAndAboveLogs()
{
SetAboveLogScriptingDefineSymbol(EnableFatalAndAboveLogScriptingDefineSymbol);
}
/// <summary>
/// 设置日志脚本宏定义。
/// </summary>
/// <param name="aboveLogScriptingDefineSymbol">要设置的日志脚本宏定义。</param>
public static void SetAboveLogScriptingDefineSymbol(string aboveLogScriptingDefineSymbol)
{
if (string.IsNullOrEmpty(aboveLogScriptingDefineSymbol))
{
return;
}
foreach (string i in AboveLogScriptingDefineSymbols)
{
if (i == aboveLogScriptingDefineSymbol)
{
DisableAllLogs();
ScriptingDefineSymbols.AddScriptingDefineSymbol(aboveLogScriptingDefineSymbol);
return;
}
}
}
/// <summary>
/// 设置日志脚本宏定义。
/// </summary>
/// <param name="specifyLogScriptingDefineSymbols">要设置的日志脚本宏定义。</param>
public static void SetSpecifyLogScriptingDefineSymbols(string[] specifyLogScriptingDefineSymbols)
{
if (specifyLogScriptingDefineSymbols == null || specifyLogScriptingDefineSymbols.Length <= 0)
{
return;
}
bool removed = false;
foreach (string specifyLogScriptingDefineSymbol in specifyLogScriptingDefineSymbols)
{
if (string.IsNullOrEmpty(specifyLogScriptingDefineSymbol))
{
continue;
}
foreach (string i in SpecifyLogScriptingDefineSymbols)
{
if (i == specifyLogScriptingDefineSymbol)
{
if (!removed)
{
removed = true;
DisableAllLogs();
}
ScriptingDefineSymbols.AddScriptingDefineSymbol(specifyLogScriptingDefineSymbol);
break;
}
}
}
}
}
}

View File

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

View File

@ -0,0 +1,91 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using System.Diagnostics;
using UnityEditor;
using UnityEngine;
namespace UnityGameFramework.Editor
{
/// <summary>
/// 打开文件夹相关的实用函数。
/// </summary>
public static class OpenFolder
{
/// <summary>
/// 打开 Data Path 文件夹。
/// </summary>
[MenuItem("Game Framework/Open Folder/Data Path", false, 10)]
public static void OpenFolderDataPath()
{
Execute(Application.dataPath);
}
/// <summary>
/// 打开 Persistent Data Path 文件夹。
/// </summary>
[MenuItem("Game Framework/Open Folder/Persistent Data Path", false, 11)]
public static void OpenFolderPersistentDataPath()
{
Execute(Application.persistentDataPath);
}
/// <summary>
/// 打开 Streaming Assets Path 文件夹。
/// </summary>
[MenuItem("Game Framework/Open Folder/Streaming Assets Path", false, 12)]
public static void OpenFolderStreamingAssetsPath()
{
Execute(Application.streamingAssetsPath);
}
/// <summary>
/// 打开 Temporary Cache Path 文件夹。
/// </summary>
[MenuItem("Game Framework/Open Folder/Temporary Cache Path", false, 13)]
public static void OpenFolderTemporaryCachePath()
{
Execute(Application.temporaryCachePath);
}
#if UNITY_2018_3_OR_NEWER
/// <summary>
/// 打开 Console Log Path 文件夹。
/// </summary>
[MenuItem("Game Framework/Open Folder/Console Log Path", false, 14)]
public static void OpenFolderConsoleLogPath()
{
Execute(System.IO.Path.GetDirectoryName(Application.consoleLogPath));
}
#endif
/// <summary>
/// 打开指定路径的文件夹。
/// </summary>
/// <param name="folder">要打开的文件夹的路径。</param>
public static void Execute(string folder)
{
folder = Utility.Text.Format("\"{0}\"", folder);
switch (Application.platform)
{
case RuntimePlatform.WindowsEditor:
Process.Start("Explorer.exe", folder.Replace('/', '\\'));
break;
case RuntimePlatform.OSXEditor:
Process.Start("open", folder);
break;
default:
throw new GameFrameworkException(Utility.Text.Format("Not support open folder on '{0}' platform.", Application.platform));
}
}
}
}

View File

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

View File

@ -0,0 +1,157 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using System.Collections.Generic;
using UnityEditor;
namespace UnityGameFramework.Editor
{
/// <summary>
/// 脚本宏定义。
/// </summary>
public static class ScriptingDefineSymbols
{
private static readonly BuildTargetGroup[] BuildTargetGroups = new BuildTargetGroup[]
{
BuildTargetGroup.Standalone,
BuildTargetGroup.iOS,
BuildTargetGroup.Android,
BuildTargetGroup.WSA,
BuildTargetGroup.WebGL
};
/// <summary>
/// 检查指定平台是否存在指定的脚本宏定义。
/// </summary>
/// <param name="buildTargetGroup">要检查脚本宏定义的平台。</param>
/// <param name="scriptingDefineSymbol">要检查的脚本宏定义。</param>
/// <returns>指定平台是否存在指定的脚本宏定义。</returns>
public static bool HasScriptingDefineSymbol(BuildTargetGroup buildTargetGroup, string scriptingDefineSymbol)
{
if (string.IsNullOrEmpty(scriptingDefineSymbol))
{
return false;
}
string[] scriptingDefineSymbols = GetScriptingDefineSymbols(buildTargetGroup);
foreach (string i in scriptingDefineSymbols)
{
if (i == scriptingDefineSymbol)
{
return true;
}
}
return false;
}
/// <summary>
/// 为指定平台增加指定的脚本宏定义。
/// </summary>
/// <param name="buildTargetGroup">要增加脚本宏定义的平台。</param>
/// <param name="scriptingDefineSymbol">要增加的脚本宏定义。</param>
public static void AddScriptingDefineSymbol(BuildTargetGroup buildTargetGroup, string scriptingDefineSymbol)
{
if (string.IsNullOrEmpty(scriptingDefineSymbol))
{
return;
}
if (HasScriptingDefineSymbol(buildTargetGroup, scriptingDefineSymbol))
{
return;
}
List<string> scriptingDefineSymbols = new List<string>(GetScriptingDefineSymbols(buildTargetGroup))
{
scriptingDefineSymbol
};
SetScriptingDefineSymbols(buildTargetGroup, scriptingDefineSymbols.ToArray());
}
/// <summary>
/// 为指定平台移除指定的脚本宏定义。
/// </summary>
/// <param name="buildTargetGroup">要移除脚本宏定义的平台。</param>
/// <param name="scriptingDefineSymbol">要移除的脚本宏定义。</param>
public static void RemoveScriptingDefineSymbol(BuildTargetGroup buildTargetGroup, string scriptingDefineSymbol)
{
if (string.IsNullOrEmpty(scriptingDefineSymbol))
{
return;
}
if (!HasScriptingDefineSymbol(buildTargetGroup, scriptingDefineSymbol))
{
return;
}
List<string> scriptingDefineSymbols = new List<string>(GetScriptingDefineSymbols(buildTargetGroup));
while (scriptingDefineSymbols.Contains(scriptingDefineSymbol))
{
scriptingDefineSymbols.Remove(scriptingDefineSymbol);
}
SetScriptingDefineSymbols(buildTargetGroup, scriptingDefineSymbols.ToArray());
}
/// <summary>
/// 为所有平台增加指定的脚本宏定义。
/// </summary>
/// <param name="scriptingDefineSymbol">要增加的脚本宏定义。</param>
public static void AddScriptingDefineSymbol(string scriptingDefineSymbol)
{
if (string.IsNullOrEmpty(scriptingDefineSymbol))
{
return;
}
foreach (BuildTargetGroup buildTargetGroup in BuildTargetGroups)
{
AddScriptingDefineSymbol(buildTargetGroup, scriptingDefineSymbol);
}
}
/// <summary>
/// 为所有平台移除指定的脚本宏定义。
/// </summary>
/// <param name="scriptingDefineSymbol">要移除的脚本宏定义。</param>
public static void RemoveScriptingDefineSymbol(string scriptingDefineSymbol)
{
if (string.IsNullOrEmpty(scriptingDefineSymbol))
{
return;
}
foreach (BuildTargetGroup buildTargetGroup in BuildTargetGroups)
{
RemoveScriptingDefineSymbol(buildTargetGroup, scriptingDefineSymbol);
}
}
/// <summary>
/// 获取指定平台的脚本宏定义。
/// </summary>
/// <param name="buildTargetGroup">要获取脚本宏定义的平台。</param>
/// <returns>平台的脚本宏定义。</returns>
public static string[] GetScriptingDefineSymbols(BuildTargetGroup buildTargetGroup)
{
return PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup).Split(';');
}
/// <summary>
/// 设置指定平台的脚本宏定义。
/// </summary>
/// <param name="buildTargetGroup">要设置脚本宏定义的平台。</param>
/// <param name="scriptingDefineSymbols">要设置的脚本宏定义。</param>
public static void SetScriptingDefineSymbols(BuildTargetGroup buildTargetGroup, string[] scriptingDefineSymbols)
{
PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, string.Join(";", scriptingDefineSymbols));
}
}
}

View File

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

View File

@ -0,0 +1,127 @@
//------------------------------------------------------------
// Game Framework
// Copyright © 2013-2021 Jiang Yin. All rights reserved.
// Homepage: https://gameframework.cn/
// Feedback: mailto:ellan@gameframework.cn
//------------------------------------------------------------
using GameFramework;
using System.Collections.Generic;
using System.Reflection;
namespace UnityGameFramework.Editor
{
/// <summary>
/// 类型相关的实用函数。
/// </summary>
internal static class Type
{
private static readonly string[] RuntimeAssemblyNames =
{
#if UNITY_2017_3_OR_NEWER
"UnityGameFramework.Runtime",
#endif
"Assembly-CSharp",
};
private static readonly string[] RuntimeOrEditorAssemblyNames =
{
#if UNITY_2017_3_OR_NEWER
"UnityGameFramework.Runtime",
#endif
"Assembly-CSharp",
#if UNITY_2017_3_OR_NEWER
"UnityGameFramework.Editor",
#endif
"Assembly-CSharp-Editor",
};
/// <summary>
/// 获取配置路径。
/// </summary>
/// <typeparam name="T">配置类型。</typeparam>
/// <returns>配置路径。</returns>
internal static string GetConfigurationPath<T>() where T : ConfigPathAttribute
{
foreach (System.Type type in Utility.Assembly.GetTypes())
{
if (!type.IsAbstract || !type.IsSealed)
{
continue;
}
foreach (FieldInfo fieldInfo in type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly))
{
if (fieldInfo.FieldType == typeof(string) && fieldInfo.IsDefined(typeof(T), false))
{
return (string)fieldInfo.GetValue(null);
}
}
foreach (PropertyInfo propertyInfo in type.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly))
{
if (propertyInfo.PropertyType == typeof(string) && propertyInfo.IsDefined(typeof(T), false))
{
return (string)propertyInfo.GetValue(null, null);
}
}
}
return null;
}
/// <summary>
/// 在运行时程序集中获取指定基类的所有子类的名称。
/// </summary>
/// <param name="typeBase">基类类型。</param>
/// <returns>指定基类的所有子类的名称。</returns>
internal static string[] GetRuntimeTypeNames(System.Type typeBase)
{
return GetTypeNames(typeBase, RuntimeAssemblyNames);
}
/// <summary>
/// 在运行时或编辑器程序集中获取指定基类的所有子类的名称。
/// </summary>
/// <param name="typeBase">基类类型。</param>
/// <returns>指定基类的所有子类的名称。</returns>
internal static string[] GetRuntimeOrEditorTypeNames(System.Type typeBase)
{
return GetTypeNames(typeBase, RuntimeOrEditorAssemblyNames);
}
private static string[] GetTypeNames(System.Type typeBase, string[] assemblyNames)
{
List<string> typeNames = new List<string>();
foreach (string assemblyName in assemblyNames)
{
Assembly assembly = null;
try
{
assembly = Assembly.Load(assemblyName);
}
catch
{
continue;
}
if (assembly == null)
{
continue;
}
System.Type[] types = assembly.GetTypes();
foreach (System.Type type in types)
{
if (type.IsClass && !type.IsAbstract && typeBase.IsAssignableFrom(type))
{
typeNames.Add(type.FullName);
}
}
}
typeNames.Sort();
return typeNames.ToArray();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 82f73088e6e538649abbb7e35e3d6bf5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
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:

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