Init TEngine4.0.0

Init TEngine4.0.0
This commit is contained in:
ALEXTANG
2023-10-08 15:21:33 +08:00
parent 4c8c37ffd8
commit 8c3d6308b9
3773 changed files with 49313 additions and 150734 deletions

View File

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

View File

@@ -0,0 +1,172 @@
using UnityEditor;
namespace TEngine.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("TEngine/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("TEngine/Log Scripting Define Symbols/Enable All Logs", false, 31)]
public static void EnableAllLogs()
{
DisableAllLogs();
ScriptingDefineSymbols.AddScriptingDefineSymbol(EnableLogScriptingDefineSymbol);
}
/// <summary>
/// 开启调试及以上级别的日志脚本宏定义。
/// </summary>
[MenuItem("TEngine/Log Scripting Define Symbols/Enable Debug And Above Logs", false, 32)]
public static void EnableDebugAndAboveLogs()
{
SetAboveLogScriptingDefineSymbol(EnableDebugAndAboveLogScriptingDefineSymbol);
}
/// <summary>
/// 开启信息及以上级别的日志脚本宏定义。
/// </summary>
[MenuItem("TEngine/Log Scripting Define Symbols/Enable Info And Above Logs", false, 33)]
public static void EnableInfoAndAboveLogs()
{
SetAboveLogScriptingDefineSymbol(EnableInfoAndAboveLogScriptingDefineSymbol);
}
/// <summary>
/// 开启警告及以上级别的日志脚本宏定义。
/// </summary>
[MenuItem("TEngine/Log Scripting Define Symbols/Enable Warning And Above Logs", false, 34)]
public static void EnableWarningAndAboveLogs()
{
SetAboveLogScriptingDefineSymbol(EnableWarningAndAboveLogScriptingDefineSymbol);
}
/// <summary>
/// 开启错误及以上级别的日志脚本宏定义。
/// </summary>
[MenuItem("TEngine/Log Scripting Define Symbols/Enable Error And Above Logs", false, 35)]
public static void EnableErrorAndAboveLogs()
{
SetAboveLogScriptingDefineSymbol(EnableErrorAndAboveLogScriptingDefineSymbol);
}
/// <summary>
/// 开启严重错误及以上级别的日志脚本宏定义。
/// </summary>
[MenuItem("TEngine/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: a7f38582e7109d344bd714fb29e2cd97
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
using UnityEditor;
namespace TEngine.Editor
{
/// <summary>
/// Profiler分析器宏定义操作类。
/// </summary>
public class ProfilerDefineSymbols
{
private const string EnableFirstProfiler = "FIRST_PROFILER";
private const string EnableDinProFiler = "T_PROFILER";
private static readonly string[] AllProfilerDefineSymbols = new string[]
{
EnableFirstProfiler,
EnableDinProFiler,
};
/// <summary>
/// 禁用所有日志脚本宏定义。
/// </summary>
[MenuItem("TEngine/Profiler Define Symbols/Disable All Profiler", false, 30)]
public static void DisableAllLogs()
{
foreach (string aboveLogScriptingDefineSymbol in AllProfilerDefineSymbols)
{
ScriptingDefineSymbols.RemoveScriptingDefineSymbol(aboveLogScriptingDefineSymbol);
}
}
/// <summary>
/// 开启所有日志脚本宏定义。
/// </summary>
[MenuItem("TEngine/Profiler Define Symbols/Enable All Profiler", false, 31)]
public static void EnableAllLogs()
{
DisableAllLogs();
foreach (string aboveLogScriptingDefineSymbol in AllProfilerDefineSymbols)
{
ScriptingDefineSymbols.AddScriptingDefineSymbol(aboveLogScriptingDefineSymbol);
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1503a11737564a498b65d84dc90758c2
timeCreated: 1694790771

View File

@@ -0,0 +1,150 @@
using System.Collections.Generic;
using UnityEditor;
namespace TEngine.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: 654ee3e03c534f841bf22040608d720e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8886f3797aa14b80ab35d4d5e20d32e6
timeCreated: 1695127130

View File

@@ -0,0 +1,7 @@
using UnityEditor;
public static class SettingsMenu
{
[MenuItem("TEngine/Settings/TEngineSettings", priority = -1)]
public static void OpenSettings() => SettingsService.OpenProjectSettings("TEngine/TEngineSettings");
}

View File

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

View File

@@ -0,0 +1,18 @@
using UnityEditor;
using UnityEngine;
/// <summary>
/// 同步程序集上下文。
/// </summary>
public static class SyncAssemblyContent
{
public static void RefreshAssembly()
{
SettingsUtils.SetHybridCLRHotUpdateAssemblies(HybridCLR.Editor.SettingsUtil.HotUpdateAssemblyFilesIncludePreserved);
SettingsUtils.SetHybridCLRAOTMetaAssemblies(HybridCLR.Editor.SettingsUtil.AOTAssemblyNames);
SettingsUtils.HybridCLRCustomGlobalSettings.Enable = HybridCLR.Editor.SettingsUtil.Enable;
AssetDatabase.Refresh();
AssetDatabase.SaveAssets();
Debug.Log("同步AOT和HotUpdate程序集 HybridCLR到TEngineSettings成功。");
}
}

View File

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

View File

@@ -0,0 +1,90 @@
using System.IO;
using UnityEditor;
using UnityEngine.UIElements;
using System.Collections.Generic;
using UnityEngine;
public class TEngineSettingsProvider : SettingsProvider
{
const string k_SettingsPath = "Assets/TEngine/ResRaw/Resources/TEngineGlobalSettings.asset";
private const string headerName = "TEngine/TEngineSettings";
private SerializedObject m_CustomSettings;
internal static SerializedObject GetSerializedSettings()
{
return new SerializedObject(SettingsUtils.GlobalSettings);
}
public static bool IsSettingsAvailable()
{
return File.Exists(k_SettingsPath);
}
public override void OnActivate(string searchContext, VisualElement rootElement)
{
base.OnActivate(searchContext, rootElement);
m_CustomSettings = GetSerializedSettings();
}
public override void OnDeactivate()
{
base.OnDeactivate();
SaveAssetData(k_SettingsPath);
}
void SaveAssetData(string path)
{
TEngineSettings old = AssetDatabase.LoadAssetAtPath<TEngineSettings>(k_SettingsPath);
TEngineSettings data = ScriptableObject.CreateInstance<TEngineSettings>();
data.Set(old.FrameworkGlobalSettings, old.BybridCLRCustomGlobalSettings);
AssetDatabase.DeleteAsset(path);
AssetDatabase.CreateAsset(data, path);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
public override void OnGUI(string searchContext)
{
base.OnGUI(searchContext);
using var changeCheckScope = new EditorGUI.ChangeCheckScope();
EditorGUILayout.PropertyField(m_CustomSettings.FindProperty("m_FrameworkGlobalSettings"));
if (GUILayout.Button("Refresh HotUpdateAssemblies"))
{
SyncAssemblyContent.RefreshAssembly();
m_CustomSettings.ApplyModifiedPropertiesWithoutUndo();
m_CustomSettings = null;
m_CustomSettings = GetSerializedSettings();
}
EditorGUILayout.PropertyField(m_CustomSettings.FindProperty("m_BybridCLRCustomGlobalSettings"));
EditorGUILayout.Space(20);
if (!changeCheckScope.changed)
{
return;
}
m_CustomSettings.ApplyModifiedPropertiesWithoutUndo();
}
public TEngineSettingsProvider(string path, SettingsScope scopes, IEnumerable<string> keywords = null) : base(path, scopes, keywords)
{
}
[SettingsProvider]
private static SettingsProvider CreateSettingProvider()
{
if (IsSettingsAvailable())
{
var provider = new TEngineSettingsProvider(headerName, SettingsScope.Project);
provider.keywords = GetSearchKeywordsFromGUIContentProperties<TEngineSettings>();
return provider;
}
else
{
Debug.LogError($"Open TEngine Settings error,Please Create TEngine TEngineGlobalSettings.assets File in Path TEngine/ResRaw/Resources/");
}
return null;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 09fb422339ad47ec86205963c369718b
timeCreated: 1678946531

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 71b72a5760a04a4c8a3d8197729c3d10
timeCreated: 1695127841

View File

@@ -0,0 +1,79 @@
using HybridCLR.Editor;
using HybridCLR.Editor.Commands;
using TEngine.Editor;
using UnityEditor;
using UnityEngine;
public static class BuildAssetsCommand
{
private const string EnableHybridClrScriptingDefineSymbol = "ENABLE_HYBRIDCLR";
/// <summary>
/// 禁用HybridCLR宏定义。
/// </summary>
[MenuItem("HybridCLR/Define Symbols/Disable HybridCLR", false, 30)]
public static void Disable()
{
ScriptingDefineSymbols.RemoveScriptingDefineSymbol(EnableHybridClrScriptingDefineSymbol);
}
/// <summary>
/// 开启HybridCLR宏定义。
/// </summary>
[MenuItem("HybridCLR/Define Symbols/Enable HybridCLR", false, 31)]
public static void Enable()
{
ScriptingDefineSymbols.RemoveScriptingDefineSymbol(EnableHybridClrScriptingDefineSymbol);
ScriptingDefineSymbols.AddScriptingDefineSymbol(EnableHybridClrScriptingDefineSymbol);
}
[MenuItem("HybridCLR/Build/BuildAssets And CopyTo AssemblyTextAssetPath")]
public static void BuildAndCopyDlls()
{
BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
CompileDllCommand.CompileDll(target);
CopyAOTHotUpdateDlls(target);
}
public static void CopyAOTHotUpdateDlls(BuildTarget target)
{
CopyAOTAssembliesToAssetPath();
CopyHotUpdateAssembliesToAssetPath();
AssetDatabase.Refresh();
}
public static void CopyAOTAssembliesToAssetPath()
{
var target = EditorUserBuildSettings.activeBuildTarget;
string aotAssembliesSrcDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
string aotAssembliesDstDir = Application.dataPath +"/"+ SettingsUtils.HybridCLRCustomGlobalSettings.AssemblyTextAssetPath;
foreach (var dll in SettingsUtils.HybridCLRCustomGlobalSettings.AOTMetaAssemblies)
{
string srcDllPath = $"{aotAssembliesSrcDir}/{dll}";
if (!System.IO.File.Exists(srcDllPath))
{
Debug.LogError($"ab中添加AOT补充元数据dll:{srcDllPath} 时发生错误,文件不存在。裁剪后的AOT dll在BuildPlayer时才能生成因此需要你先构建一次游戏App后再打包。");
continue;
}
string dllBytesPath = $"{aotAssembliesDstDir}/{dll}.bytes";
System.IO.File.Copy(srcDllPath, dllBytesPath, true);
Debug.Log($"[CopyAOTAssembliesToStreamingAssets] copy AOT dll {srcDllPath} -> {dllBytesPath}");
}
}
public static void CopyHotUpdateAssembliesToAssetPath()
{
var target = EditorUserBuildSettings.activeBuildTarget;
string hotfixDllSrcDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
string hotfixAssembliesDstDir = Application.dataPath +"/"+ SettingsUtils.HybridCLRCustomGlobalSettings.AssemblyTextAssetPath;
foreach (var dll in SettingsUtil.HotUpdateAssemblyFilesExcludePreserved)
{
string dllPath = $"{hotfixDllSrcDir}/{dll}";
string dllBytesPath = $"{hotfixAssembliesDstDir}/{dll}.bytes";
System.IO.File.Copy(dllPath, dllBytesPath, true);
Debug.Log($"[CopyHotUpdateAssembliesToStreamingAssets] copy hotfix dll {dllPath} -> {dllBytesPath}");
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,54 @@
using UnityEditor;
namespace TEngine.Editor.Inspector
{
[CustomEditor(typeof(AudioModule))]
internal sealed class AudioModuleInspector : GameFrameworkInspector
{
private SerializedProperty m_InstanceRoot = null;
private SerializedProperty m_AudioMixer = null;
private SerializedProperty m_AudioGroupConfigs = null;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
AudioModule t = (AudioModule)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_InstanceRoot);
EditorGUILayout.PropertyField(m_AudioMixer);
EditorGUILayout.PropertyField(m_AudioGroupConfigs, true);
}
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot");
m_AudioMixer = serializedObject.FindProperty("m_AudioMixer");
m_AudioGroupConfigs = serializedObject.FindProperty("m_AudioGroupConfigs");
RefreshTypeNames();
}
private void RefreshTypeNames()
{
serializedObject.ApplyModifiedProperties();
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,57 @@
using UnityEditor;
namespace TEngine.Editor.Inspector
{
/// <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: 9d91af5de1cd262429b9414da4df0a4d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
using UnityEditor;
namespace TEngine.Editor.Inspector
{
[CustomEditor(typeof(FsmModule))]
internal sealed class FsmComponentInspector : GameFrameworkInspector
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (!EditorApplication.isPlaying)
{
EditorGUILayout.HelpBox("Available during runtime only.", MessageType.Info);
return;
}
FsmModule t = (FsmModule)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 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: 70767d883b439f84d8daaed6ca3f6d35
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,56 @@
using UnityEditor;
namespace TEngine.Editor.Inspector
{
[CustomEditor(typeof(LocalizationModule))]
internal sealed class LocalizationModuleInspector : GameFrameworkInspector
{
private HelperInfo<LocalizationHelperBase> m_LocalizationHelperInfo = new HelperInfo<LocalizationHelperBase>("Localization");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
LocalizationModule t = (LocalizationModule)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
m_LocalizationHelperInfo.Draw();
}
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());
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_LocalizationHelperInfo.Init(serializedObject);
RefreshTypeNames();
}
private void RefreshTypeNames()
{
m_LocalizationHelperInfo.Refresh();
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8c8de00f4cb14c4fa7b28015f55cd5ee
timeCreated: 1695200030

View File

@@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace TEngine.Editor.Inspector
{
[CustomEditor(typeof(MemoryPoolModule))]
internal sealed class MemoryPoolModuleInspector : GameFrameworkInspector
{
private readonly Dictionary<string, List<MemoryPoolInfo>> m_MemoryPoolInfos = new Dictionary<string, List<MemoryPoolInfo>>(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();
MemoryPoolModule t = (MemoryPoolModule)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("Memory Pool Count", MemoryPool.Count.ToString());
m_ShowFullClassName = EditorGUILayout.Toggle("Show Full Class Name", m_ShowFullClassName);
m_MemoryPoolInfos.Clear();
MemoryPoolInfo[] memoryPoolInfos = MemoryPool.GetAllMemoryPoolInfos();
foreach (MemoryPoolInfo memoryPoolInfo in memoryPoolInfos)
{
string assemblyName = memoryPoolInfo.Type.Assembly.GetName().Name;
List<MemoryPoolInfo> results = null;
if (!m_MemoryPoolInfos.TryGetValue(assemblyName, out results))
{
results = new List<MemoryPoolInfo>();
m_MemoryPoolInfos.Add(assemblyName, results);
}
results.Add(memoryPoolInfo);
}
foreach (KeyValuePair<string, List<MemoryPoolInfo>> assemblyMemoryPoolInfo in m_MemoryPoolInfos)
{
bool lastState = m_OpenedItems.Contains(assemblyMemoryPoolInfo.Key);
bool currentState = EditorGUILayout.Foldout(lastState, assemblyMemoryPoolInfo.Key);
if (currentState != lastState)
{
if (currentState)
{
m_OpenedItems.Add(assemblyMemoryPoolInfo.Key);
}
else
{
m_OpenedItems.Remove(assemblyMemoryPoolInfo.Key);
}
}
if (currentState)
{
EditorGUILayout.BeginVertical("box");
{
EditorGUILayout.LabelField(m_ShowFullClassName ? "Full Class Name" : "Class Name", "Unused\tUsing\tAcquire\tRelease\tAdd\tRemove");
assemblyMemoryPoolInfo.Value.Sort(Comparison);
foreach (MemoryPoolInfo memoryPoolInfo in assemblyMemoryPoolInfo.Value)
{
DrawMemoryPoolInfo(memoryPoolInfo);
}
if (GUILayout.Button("Export CSV Data"))
{
string exportFileName = EditorUtility.SaveFilePanel("Export CSV Data", string.Empty, Utility.Text.Format("Memory Pool Data - {0}.csv", assemblyMemoryPoolInfo.Key), string.Empty);
if (!string.IsNullOrEmpty(exportFileName))
{
try
{
int index = 0;
string[] data = new string[assemblyMemoryPoolInfo.Value.Count + 1];
data[index++] = "Class Name,Full Class Name,Unused,Using,Acquire,Release,Add,Remove";
foreach (MemoryPoolInfo memoryPoolInfo in assemblyMemoryPoolInfo.Value)
{
data[index++] = Utility.Text.Format("{0},{1},{2},{3},{4},{5},{6},{7}", memoryPoolInfo.Type.Name, memoryPoolInfo.Type.FullName, memoryPoolInfo.UnusedMemoryCount.ToString(), memoryPoolInfo.UsingMemoryCount.ToString(), memoryPoolInfo.AcquireMemoryCount.ToString(), memoryPoolInfo.ReleaseMemoryCount.ToString(), memoryPoolInfo.AddMemoryCount.ToString(), memoryPoolInfo.RemoveMemoryCount.ToString());
}
File.WriteAllLines(exportFileName, data, Encoding.UTF8);
Debug.Log(Utility.Text.Format("Export memory pool CSV data to '{0}' success.", exportFileName));
}
catch (Exception exception)
{
Debug.LogError(Utility.Text.Format("Export memory pool CSV data to '{0}' failure, exception is '{1}'.", exportFileName, exception.ToString()));
}
}
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Separator();
}
}
}
else
{
EditorGUILayout.PropertyField(m_EnableStrictCheck);
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
private void OnEnable()
{
m_EnableStrictCheck = serializedObject.FindProperty("m_EnableStrictCheck");
}
private void DrawMemoryPoolInfo(MemoryPoolInfo memoryPoolInfo)
{
EditorGUILayout.LabelField(m_ShowFullClassName ? memoryPoolInfo.Type.FullName : memoryPoolInfo.Type.Name, Utility.Text.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}", memoryPoolInfo.UnusedMemoryCount.ToString(), memoryPoolInfo.UsingMemoryCount.ToString(), memoryPoolInfo.AcquireMemoryCount.ToString(), memoryPoolInfo.ReleaseMemoryCount.ToString(), memoryPoolInfo.AddMemoryCount.ToString(), memoryPoolInfo.RemoveMemoryCount.ToString()));
}
private int Comparison(MemoryPoolInfo a, MemoryPoolInfo 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: 17406c25c88f31948b13eed588b32244
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace TEngine.Editor.Inspector
{
[CustomEditor(typeof(ObjectPoolModule))]
internal sealed class ObjectPoolModuleInspector : 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;
}
ObjectPoolModule t = (ObjectPoolModule)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: 581eaf027c4a96d4d8227e2e16a6645b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,163 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace TEngine.Editor.Inspector
{
[CustomEditor(typeof(ProcedureModule))]
internal sealed class ProcedureModuleInspector : 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();
ProcedureModule t = (ProcedureModule)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("availableProcedureTypeNames");
m_EntranceProcedureTypeName = serializedObject.FindProperty("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: 6f8673b671dafe048a9fcd213c958166
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,258 @@
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using YooAsset.Editor;
namespace TEngine.Editor.Inspector
{
[CustomEditor(typeof(ResourceModule))]
internal sealed class ResourceModuleInspector : GameFrameworkInspector
{
private static readonly string[] _resourceModeNames = new string[]
{
"EditorSimulateMode (编辑器下的模拟模式)",
"OfflinePlayMode (单机模式)",
"HostPlayMode (联机运行模式)" ,
"WebPlayMode (WebGL运行模式)"
};
private static readonly string[] _verifyLevelNames = new string[]
{
"Low (验证文件存在)",
"Middle (验证文件大小)",
"High (验证文件大小和CRC)"
};
private SerializedProperty m_PackageName = null;
private SerializedProperty m_PlayMode = null;
private SerializedProperty m_ReadWritePathType = null;
private SerializedProperty m_VerifyLevel = null;
private SerializedProperty m_Milliseconds = null;
private SerializedProperty m_MinUnloadUnusedAssetsInterval = null;
private SerializedProperty m_MaxUnloadUnusedAssetsInterval = null;
private SerializedProperty m_DownloadingMaxNum = null;
private SerializedProperty m_FailedTryAgain = null;
private int m_ResourceModeIndex = 0;
private int m_PackageIndex = 0;
private int m_VerifyIndex = 0;
private PopupField<string> _buildPackageField;
private List<string> _buildPackageNames;
private void OnEnable()
{
m_PackageName = serializedObject.FindProperty("packageName");
m_PlayMode = serializedObject.FindProperty("playMode");
m_VerifyLevel = serializedObject.FindProperty("verifyLevel");
m_Milliseconds = serializedObject.FindProperty("milliseconds");
m_ReadWritePathType = serializedObject.FindProperty("readWritePathType");
m_MinUnloadUnusedAssetsInterval = serializedObject.FindProperty("minUnloadUnusedAssetsInterval");
m_MaxUnloadUnusedAssetsInterval = serializedObject.FindProperty("maxUnloadUnusedAssetsInterval");
m_DownloadingMaxNum = serializedObject.FindProperty("downloadingMaxNum");
m_FailedTryAgain = serializedObject.FindProperty("failedTryAgain");
RefreshModes();
RefreshTypeNames();
}
private void RefreshModes()
{
m_ResourceModeIndex = m_PlayMode.enumValueIndex > 0 ? m_PlayMode.enumValueIndex : 0;
m_VerifyIndex = m_VerifyLevel.enumValueIndex > 0 ? m_VerifyLevel.enumValueIndex : 0;
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
ResourceModule t = (ResourceModule)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
if (EditorApplication.isPlaying && IsPrefabInHierarchy(t.gameObject))
{
EditorGUILayout.EnumPopup("Resource Mode", t.PlayMode);
EditorGUILayout.EnumPopup("VerifyLevel", t.verifyLevel);
_buildPackageNames = GetBuildPackageNames();
if (_buildPackageNames.Count > 0)
{
GUILayout.Label(_buildPackageNames[0]);
}
}
else
{
// 资源模式
int selectedIndex = EditorGUILayout.Popup("Resource Mode", m_ResourceModeIndex, _resourceModeNames);
if (selectedIndex != m_ResourceModeIndex)
{
m_ResourceModeIndex = selectedIndex;
m_PlayMode.enumValueIndex = selectedIndex;
}
int selectedVerifyIndex = EditorGUILayout.Popup("VerifyLevel", m_VerifyIndex, _verifyLevelNames);
if (selectedVerifyIndex != m_VerifyIndex)
{
m_VerifyIndex = selectedVerifyIndex;
m_VerifyLevel.enumValueIndex = selectedVerifyIndex;
}
// 包裹名称列表
_buildPackageNames = GetBuildPackageNames();
if (_buildPackageNames.Count > 0)
{
int selectedPackageIndex = EditorGUILayout.Popup("Used Packages", m_PackageIndex, _buildPackageNames.ToArray());
if (selectedPackageIndex != m_PackageIndex)
{
m_PackageIndex = selectedPackageIndex;
m_PlayMode.enumValueIndex = selectedIndex + 1;
}
int defaultIndex = GetDefaultPackageIndex(AssetBundleBuilderSettingData.Setting.BuildPackage);
_buildPackageField = new PopupField<string>(_buildPackageNames, defaultIndex);
_buildPackageField.label = "Build Package";
_buildPackageField.style.width = 350;
_buildPackageField.RegisterValueChangedCallback(evt =>
{
AssetBundleBuilderSettingData.IsDirty = true;
AssetBundleBuilderSettingData.Setting.BuildPackage = _buildPackageField.value;
});
}
else
{
GUILayout.Label("Please Create Packages with YooAssets ...!");
}
}
m_ReadWritePathType.enumValueIndex = (int)(ReadWritePathType)EditorGUILayout.EnumPopup("Read-Write Path Type", t.ReadWritePathType);
}
EditorGUI.EndDisabledGroup();
int milliseconds = EditorGUILayout.DelayedIntField("Milliseconds", m_Milliseconds.intValue);
if (milliseconds != m_Milliseconds.intValue)
{
if (EditorApplication.isPlaying)
{
t.milliseconds = milliseconds;
}
else
{
m_Milliseconds.longValue = milliseconds;
}
}
float minUnloadUnusedAssetsInterval = EditorGUILayout.Slider("Min Unload Unused Assets Interval", m_MinUnloadUnusedAssetsInterval.floatValue, 0f, 3600f);
if (Math.Abs(minUnloadUnusedAssetsInterval - m_MinUnloadUnusedAssetsInterval.floatValue) > 0.001f)
{
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 (Math.Abs(maxUnloadUnusedAssetsInterval - m_MaxUnloadUnusedAssetsInterval.floatValue) > 0.001f)
{
if (EditorApplication.isPlaying)
{
t.MaxUnloadUnusedAssetsInterval = maxUnloadUnusedAssetsInterval;
}
else
{
m_MaxUnloadUnusedAssetsInterval.floatValue = maxUnloadUnusedAssetsInterval;
}
}
float downloadingMaxNum = EditorGUILayout.Slider("Max Downloading Num", m_DownloadingMaxNum.intValue, 1f, 48f);
if (Math.Abs(downloadingMaxNum - m_DownloadingMaxNum.intValue) > 0.001f)
{
if (EditorApplication.isPlaying)
{
t.downloadingMaxNum = (int)downloadingMaxNum;
}
else
{
m_DownloadingMaxNum.intValue = (int)downloadingMaxNum;
}
}
float failedTryAgain = EditorGUILayout.Slider("Max FailedTryAgain Count", m_FailedTryAgain.intValue, 1f, 48f);
if (Math.Abs(failedTryAgain - m_FailedTryAgain.intValue) > 0.001f)
{
if (EditorApplication.isPlaying)
{
t.failedTryAgain = (int)failedTryAgain;
}
else
{
m_FailedTryAgain.intValue = (int)failedTryAgain;
}
}
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("Applicable Game Version", t.ApplicableGameVersion ?? "<Unknwon>");
EditorGUILayout.LabelField("Internal Resource Version", t.InternalResourceVersion.ToString());
}
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void RefreshTypeNames()
{
serializedObject.ApplyModifiedProperties();
}
// 构建包裹相关
private int GetDefaultPackageIndex(string packageName)
{
for (int index = 0; index < _buildPackageNames.Count; index++)
{
if (_buildPackageNames[index] == packageName)
{
return index;
}
}
AssetBundleBuilderSettingData.IsDirty = true;
AssetBundleBuilderSettingData.Setting.BuildPackage = _buildPackageNames[0];
return 0;
}
private List<string> GetBuildPackageNames()
{
List<string> result = new List<string>();
foreach (var package in AssetBundleCollectorSettingData.Setting.Packages)
{
result.Add(package.PackageName);
}
return result;
}
}
}

View File

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

View File

@@ -0,0 +1,278 @@
using System;
using TEngine;
using System.Collections.Generic;
using TEngine.Editor.Inspector;
using UnityEditor;
using UnityEngine;
namespace TEngine.Editor
{
[CustomEditor(typeof(RootModule))]
internal sealed class RootModuleInspector : 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_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_JsonHelperTypeNames = null;
private int m_JsonHelperTypeNameIndex = 0;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
RootModule t = (RootModule)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_EditorLanguage);
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 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 (Math.Abs(gameSpeed - m_GameSpeed.floatValue) > 0.01f)
{
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_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> 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: 250c436df9563f04881e590c3fc80e81
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,73 @@
using UnityEditor;
using UnityEngine;
namespace TEngine.Editor.Inspector
{
[CustomEditor(typeof(SettingModule))]
internal sealed class SettingModuleInspector : GameFrameworkInspector
{
private HelperInfo<SettingHelperBase> m_SettingHelperInfo = new HelperInfo<SettingHelperBase>("Setting");
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
SettingModule t = (SettingModule)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: 5ef9a06ba6ea31f47bf3f0ef922cf41b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
using UnityEditor;
namespace TEngine.Editor.Inspector
{
[CustomEditor(typeof(UIModule))]
internal sealed class UIModuleInspector : GameFrameworkInspector
{
private SerializedProperty m_InstanceRoot = null;
private SerializedProperty m_enableErrorLog = null;
private SerializedProperty m_dontDestroyUIRoot = null;
private SerializedProperty m_UICamera = null;
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
UIModule t = (UIModule)target;
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
EditorGUILayout.PropertyField(m_InstanceRoot);
EditorGUILayout.PropertyField(m_enableErrorLog);
EditorGUILayout.PropertyField(m_dontDestroyUIRoot);
EditorGUILayout.PropertyField(m_UICamera);
}
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
Repaint();
}
protected override void OnCompileComplete()
{
base.OnCompileComplete();
RefreshTypeNames();
}
private void OnEnable()
{
m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot");
m_enableErrorLog = serializedObject.FindProperty("m_enableErrorLog");
m_dontDestroyUIRoot = serializedObject.FindProperty("m_dontDestroyUIRoot");
m_UICamera = serializedObject.FindProperty("m_UICamera");
RefreshTypeNames();
}
private void RefreshTypeNames()
{
serializedObject.ApplyModifiedProperties();
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,494 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.U2D;
using UnityEngine;
using Object = UnityEngine.Object;
/// <summary>
/// 图集导入管线。
/// </summary>
public class SpritePostprocessor : AssetPostprocessor
{
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
foreach (var s in importedAssets)
{
EditorSpriteSaveInfo.OnImportSprite(s);
}
foreach (var s in deletedAssets)
{
EditorSpriteSaveInfo.OnDeleteSprite(s);
}
foreach (var s in movedFromAssetPaths)
{
EditorSpriteSaveInfo.OnDeleteSprite(s);
}
foreach (var s in movedAssets)
{
EditorSpriteSaveInfo.OnImportSprite(s);
}
}
}
public static class EditorSpriteSaveInfo
{
private const string NormalAtlasDir = "Assets/AssetArt/Atlas";
private const string UISpritePath = "Assets/AssetRaw/UIRaw";
private const string UIAtlasPath = "Assets/AssetRaw/UIRaw/Atlas";
private const string UIRawPath = "Assets/AssetRaw/UIRaw/UIRaw";
private static List<string> m_dirtyAtlasList = new List<string>();
private static Dictionary<string, List<string>> m_allASprites = new Dictionary<string, List<string>>();
private static Dictionary<string, string> m_uiAtlasMap = new Dictionary<string, string>();
private static bool m_inited = false;
private static bool m_dirty = false;
public static void Init()
{
if (m_inited)
{
return;
}
EditorApplication.update += CheckDirty;
}
public static void CheckDirty()
{
if (m_dirty)
{
m_dirty = false;
AssetDatabase.Refresh();
float lastProgress = -1;
for (int i = 0; i < m_dirtyAtlasList.Count; i++)
{
string atlasName = m_dirtyAtlasList[i];
Debug.Log("更新图集 : " + atlasName);
var curProgress = (float)i / m_dirtyAtlasList.Count;
if (curProgress > lastProgress + 0.01f)
{
lastProgress = curProgress;
var progressText = $"当前进度:{i}/{m_dirtyAtlasList.Count} {atlasName}";
bool cancel = EditorUtility.DisplayCancelableProgressBar("刷新图集" + atlasName, progressText, curProgress);
if (cancel)
{
break;
}
}
bool isUI = atlasName.StartsWith("UIRaw");
SaveAtlas(atlasName, isUI);
}
EditorUtility.ClearProgressBar();
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
m_dirtyAtlasList.Clear();
}
}
public static void OnImportSprite(string assetPath)
{
if (!assetPath.StartsWith(UISpritePath))
{
return;
}
TextureImporter ti = AssetImporter.GetAtPath(assetPath) as TextureImporter;
if (ti != null)
{
var modify = false;
if (assetPath.StartsWith(UISpritePath))
{
if (ti.textureType != TextureImporterType.Sprite)
{
ti.textureType = TextureImporterType.Sprite;
modify = true;
}
if (!string.IsNullOrEmpty(ti.spritePackingTag))
{
ti.spritePackingTag = string.Empty;
modify = true;
}
var setting = new TextureImporterSettings();
ti.ReadTextureSettings(setting);
if (setting.spriteGenerateFallbackPhysicsShape)
{
setting.spriteGenerateFallbackPhysicsShape = false;
ti.SetTextureSettings(setting);
modify = true;
}
if (IsKeepRawImage(assetPath))
{
//调整android格式
var andPlatformSettings = ti.GetPlatformTextureSettings("Android");
if (!andPlatformSettings.overridden)
{
andPlatformSettings.overridden = true;
modify = true;
}
if (andPlatformSettings.format != TextureImporterFormat.ASTC_6x6)
{
andPlatformSettings.format = TextureImporterFormat.ASTC_6x6;
ti.SetPlatformTextureSettings(andPlatformSettings);
modify = true;
}
//调整ios格式
var iosPlatformSettings = ti.GetPlatformTextureSettings("iPhone");
if (!iosPlatformSettings.overridden)
{
iosPlatformSettings.overridden = true;
modify = true;
}
if (iosPlatformSettings.format != TextureImporterFormat.ASTC_5x5)
{
iosPlatformSettings.format = TextureImporterFormat.ASTC_5x5;
iosPlatformSettings.compressionQuality = 50;
ti.SetPlatformTextureSettings(iosPlatformSettings);
modify = true;
}
}
}
if (modify)
{
ti.SaveAndReimport();
}
if (ti.textureType == TextureImporterType.Sprite)
{
OnProcessSprite(assetPath);
}
}
}
/// <summary>
/// 是否保持散图(不打图集)
/// </summary>
/// <param name="dirPath"></param>
/// <returns></returns>
public static bool IsKeepRawImage(string dirPath)
{
return dirPath.Contains("UIRaw/Raw/") || dirPath.Contains("UIRaw_Raw_");
}
public static string GetSpritePath(string assetPath)
{
string path = assetPath.Substring(0, assetPath.LastIndexOf("."));
path = path.Replace("Assets/AssetRaw/", "");
return path;
}
/// <summary>
/// 根据文件路径,返回图集名称
/// </summary>
/// <param name="fullName"></param>
/// <returns></returns>
public static string GetPackageTag(string fullName)
{
fullName = fullName.Replace("\\", "/");
int idx = fullName.LastIndexOf("UIRaw", StringComparison.Ordinal);
if (idx == -1)
{
return "";
}
if (IsKeepRawImage(fullName))
{
return "";
}
var atlasPath = fullName.Substring(idx);
string str = atlasPath;
str = str.Substring(0, str.LastIndexOf("/", StringComparison.Ordinal)).Replace("/", "_");
return str;
}
public static void OnProcessSprite(string assetPath)
{
if (!assetPath.StartsWith("Assets"))
{
return;
}
if (assetPath.StartsWith("Assets/UIRaw_Delete"))
{
return;
}
Init();
var spriteName = Path.GetFileNameWithoutExtension(assetPath);
var spritePath = GetSpritePath(assetPath);
if (!m_uiAtlasMap.TryGetValue(spriteName, out string oldAssetPath) || spritePath == oldAssetPath)
{
m_uiAtlasMap[spriteName] = spritePath;
m_dirty = true;
}
else
{
Debug.LogError($"有重名的图片:{spriteName}\n旧图集{oldAssetPath}\n新图集{spritePath} ");
m_uiAtlasMap[spriteName] = spritePath;
m_dirty = true;
}
string atlasName = GetPackageTag(assetPath);
if (string.IsNullOrEmpty(atlasName))
{
bool keepRaw = IsKeepRawImage(assetPath);
if (!keepRaw)
{
Debug.LogError($"empty packingTag of asset :{assetPath} !!!");
}
return;
}
else
{
List<string> ret;
if (!m_allASprites.TryGetValue(atlasName, out ret))
{
ret = new List<string>();
m_allASprites.Add(atlasName, ret);
}
if (!ret.Contains(assetPath))
{
ret.Add(assetPath);
m_dirty = true;
if (!m_dirtyAtlasList.Contains(atlasName))
{
m_dirtyAtlasList.Add(atlasName);
}
}
}
}
public static void OnDeleteSprite(string assetPath)
{
if (assetPath.StartsWith("Assets/UIRaw_Delete"))
{
return;
}
if (!assetPath.StartsWith(UISpritePath))
{
return;
}
Init();
string atlasName = GetPackageTag(assetPath);
if (!m_allASprites.TryGetValue(atlasName, out var ret))
{
return;
}
//改成文件名的匹配
if (!ret.Exists(s => Path.GetFileName(s) == Path.GetFileName(assetPath)))
{
return;
}
if (assetPath.StartsWith(UISpritePath))
{
var spriteName = Path.GetFileNameWithoutExtension(assetPath);
if (m_uiAtlasMap.ContainsKey(spriteName))
{
m_uiAtlasMap.Remove(spriteName);
m_dirty = true;
}
}
ret.Remove(assetPath);
m_dirty = true;
if (!m_dirtyAtlasList.Contains(atlasName))
{
m_dirtyAtlasList.Add(atlasName);
}
}
#region
public static void SaveAtlas(string atlasName, bool isUI)
{
List<Object> spriteList = new List<Object>();
if (m_allASprites.TryGetValue(atlasName, out var list))
{
list.Sort(StringComparer.Ordinal);
foreach (var s in list)
{
var sprite = AssetDatabase.LoadAssetAtPath<Sprite>(s);
if (sprite != null)
{
spriteList.Add(sprite);
}
}
}
var pathv2 = $"{NormalAtlasDir}/{atlasName}.spriteatlasv2";
var path = $"{NormalAtlasDir}/{atlasName}.asset";
if (spriteList.Count == 0)
{
if (File.Exists(path))
{
AssetDatabase.DeleteAsset(path);
}
if (File.Exists(pathv2))
{
AssetDatabase.DeleteAsset(pathv2);
}
return;
}
var atlas = new SpriteAtlasAsset();
var setting = new SpriteAtlasPackingSettings
{
blockOffset = 1,
padding = 2,
enableRotation = true
};
bool isOpaque = atlasName.Contains("Opaque");
var textureSetting = new SpriteAtlasTextureSettings
{
generateMipMaps = false,
sRGB = true,
filterMode = FilterMode.Bilinear
};
atlas.SetTextureSettings(textureSetting);
var iphonePlatformSetting = atlas.GetPlatformSettings("iPhone");
if (!iphonePlatformSetting.overridden)
{
iphonePlatformSetting.overridden = true;
iphonePlatformSetting.format = isOpaque ? TextureImporterFormat.ASTC_5x5 : TextureImporterFormat.ASTC_5x5;
iphonePlatformSetting.compressionQuality = 100;
atlas.SetPlatformSettings(iphonePlatformSetting);
}
var androidPlatformSetting = atlas.GetPlatformSettings("Android");
if (isOpaque && !androidPlatformSetting.overridden)
{
androidPlatformSetting.overridden = true;
androidPlatformSetting.format = TextureImporterFormat.ETC_RGB4;
androidPlatformSetting.compressionQuality = 100;
atlas.SetPlatformSettings(androidPlatformSetting);
}
atlas.SetPackingSettings(setting);
atlas.Add(spriteList.ToArray());
AssetDatabase.CreateAsset(atlas, path);
File.Move(path, pathv2);
AssetDatabase.Refresh();
}
#endregion
#region
private static Dictionary<string, List<string>> m_tempAllASprites = new Dictionary<string, List<string>>();
[MenuItem("TEngine/图集/重新生成UI图集")]
static void ForceGenAtlas()
{
Init();
List<string> needSaveAtlas = new List<string>();
m_tempAllASprites.Clear();
var findAssets = AssetDatabase.FindAssets("t:sprite", new[] { UIAtlasPath });
foreach (var findAsset in findAssets)
{
var path = AssetDatabase.GUIDToAssetPath(findAsset);
var atlasName = GetPackageTag(path);
if (!m_tempAllASprites.TryGetValue(atlasName, out var spriteList))
{
spriteList = new List<string>();
m_tempAllASprites[atlasName] = spriteList;
}
if (!spriteList.Contains(path))
{
spriteList.Add(path);
}
}
//有变化的才刷
var iter = m_tempAllASprites.GetEnumerator();
while (iter.MoveNext())
{
bool needSave = false;
var atlasName = iter.Current.Key;
var newSpritesList = iter.Current.Value;
if (m_allASprites.TryGetValue(atlasName, out var existSprites))
{
if (existSprites.Count != newSpritesList.Count)
{
needSave = true;
existSprites.Clear();
existSprites.AddRange(newSpritesList);
}
else
{
for (int i = 0; i < newSpritesList.Count; i++)
{
if (!existSprites.Contains(newSpritesList[i]))
{
needSave = true;
break;
}
}
if (needSave)
{
existSprites.Clear();
existSprites.AddRange(newSpritesList);
}
}
}
else
{
needSave = true;
m_allASprites.Add(atlasName, new List<string>(newSpritesList));
}
if (needSave && !needSaveAtlas.Contains(atlasName))
{
needSaveAtlas.Add(atlasName);
}
}
iter.Dispose();
foreach (var atlas in needSaveAtlas)
{
Debug.LogFormat("Gen atlas:{0}", atlas);
SaveAtlas(atlas, true);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
SpriteAtlasUtility.PackAllAtlases(EditorUserBuildSettings.activeBuildTarget);
Debug.Log("Gen end");
}
#endregion
}

View File

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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 86e1ceb0af034fc0aca146e58c0be5ae
timeCreated: 1694879395

View File

@@ -0,0 +1,26 @@
using UnityEditor;
using UnityEngine;
namespace TEngine.Editor.Resource
{
/// <summary>
/// 资源引用编辑器拓展。
/// </summary>
[CustomEditor(typeof(AssetReference), true)]
public class AssetReferenceEditor : UnityEditor.Editor
{
private AssetReference _target;
private void OnEnable()
{
_target = (AssetReference)target;
}
public override void OnInspectorGUI()
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.EndHorizontal();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bd6cd0c1877e4e758d03e4f6fdfa96ad
timeCreated: 1683733968

View File

@@ -0,0 +1,41 @@
using System;
using System.IO;
using TEngine;
using YooAsset;
namespace TEngine.Editor.Resource
{
public class FileOffsetEncryption : IEncryptionServices
{
public EncryptResult Encrypt(EncryptFileInfo fileInfo)
{
int offset = 32;
byte[] fileData = File.ReadAllBytes(fileInfo.FilePath);
var encryptedData = new byte[fileData.Length + offset];
Buffer.BlockCopy(fileData, 0, encryptedData, offset, fileData.Length);
EncryptResult result = new EncryptResult();
result.LoadMethod = EBundleLoadMethod.LoadFromFileOffset;
result.EncryptedData = encryptedData;
return result;
}
}
public class FileStreamEncryption : IEncryptionServices
{
public EncryptResult Encrypt(EncryptFileInfo fileInfo)
{
// LoadFromStream
var fileData = File.ReadAllBytes(fileInfo.FilePath);
for (int i = 0; i < fileData.Length; i++)
{
fileData[i] ^= BundleStream.KEY;
}
EncryptResult result = new EncryptResult();
result.LoadMethod = EBundleLoadMethod.LoadFromStream;
result.EncryptedData = fileData;
return result;
}
}
}

View File

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

View File

@@ -0,0 +1,21 @@
{
"name": "TEngine.Editor",
"rootNamespace": "",
"references": [
"GUID:24c092aee38482f4e80715eaa8148782",
"GUID:e34a5702dd353724aa315fb8011f08c3",
"GUID:4d1926c9df5b052469a1c63448b7609a",
"GUID:2373f786d14518f44b0f475db77ba4de"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,91 @@
using UnityEditor;
using UnityEngine;
using UnityToolbarExtender;
namespace TEngine
{
[InitializeOnLoad]
public class EditorResourceMode
{
static class ToolbarStyles
{
public static readonly GUIStyle ToolBarExtenderBtnStyle;
public static readonly GUIStyle ToolBarTextStyle;
public static readonly GUIStyle ToolBarButtonGuiStyle;
static ToolbarStyles()
{
ToolBarExtenderBtnStyle = new GUIStyle("Command")
{
fontSize = 12,
alignment = TextAnchor.MiddleCenter,
imagePosition = ImagePosition.ImageAbove,
fontStyle = FontStyle.Normal,
fixedWidth = 60
};
ToolBarTextStyle = new GUIStyle(ButtonStyleName)
{
padding = new RectOffset(2, 8, 2, 2),
alignment = TextAnchor.MiddleCenter,
fontStyle = FontStyle.Bold
};
ToolBarButtonGuiStyle = new GUIStyle(ButtonStyleName)
{
padding = new RectOffset(2, 8, 2, 2),
alignment = TextAnchor.MiddleCenter,
fontStyle = FontStyle.Bold
};
}
}
static EditorResourceMode()
{
ToolbarExtender.RightToolbarGUI.Add(OnToolbarGUI);
_resourceModeIndex = EditorPrefs.GetInt("EditorResourceMode", 0);
}
private const string ButtonStyleName = "Tab middle";
static GUIStyle _buttonGuiStyle;
private static readonly string[] _resourceModeNames =
{ "EditorMode (编辑器下的模拟模式)",
"OfflinePlayMode (单机模式)",
"HostPlayMode (联机运行模式)",
"WebPlayMode (WebGL运行模式)"
};
private static int _resourceModeIndex = 0;
public static int ResourceModeIndex => _resourceModeIndex;
static void OnToolbarGUI()
{
EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode);
{
// GUILayout.Label("资源加载模式:",ToolbarStyles.ToolBarTextStyle);
GUILayout.Space(10);
GUILayout.FlexibleSpace();
// 资源模式
int selectedIndex = EditorGUILayout.Popup("", _resourceModeIndex, _resourceModeNames, ToolbarStyles.ToolBarButtonGuiStyle);
// ReSharper disable once RedundantCheckBeforeAssignment
if (selectedIndex != _resourceModeIndex)
{
Debug.Log($"更改编辑器资源运行模式 : {_resourceModeNames[selectedIndex]}");
_resourceModeIndex = selectedIndex;
EditorPrefs.SetInt("EditorResourceMode", selectedIndex);
}
GUILayout.FlexibleSpace();
GUILayout.Space(400);
}
EditorGUI.EndDisabledGroup();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ab26dd2998d84a08b35c0132e1814199
timeCreated: 1683857308

View File

@@ -0,0 +1,84 @@
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityToolbarExtender;
namespace TEngine
{
[InitializeOnLoad]
public class SceneSwitchLeftButton
{
private static readonly string SceneMain = "main";
static SceneSwitchLeftButton()
{
ToolbarExtender.LeftToolbarGUI.Add(OnToolbarGUI);
}
static readonly string ButtonStyleName = "Tab middle";
static GUIStyle _buttonGuiStyle;
static void OnToolbarGUI()
{
_buttonGuiStyle ??= new GUIStyle(ButtonStyleName)
{
padding = new RectOffset(2, 8, 2, 2),
alignment = TextAnchor.MiddleCenter,
fontStyle = FontStyle.Bold
};
GUILayout.FlexibleSpace();
if (GUILayout.Button(
new GUIContent("Launcher", EditorGUIUtility.FindTexture("PlayButton"), $"Start Scene Launcher"),
_buttonGuiStyle))
{
SceneHelper.StartScene(SceneMain);
}
}
}
static class SceneHelper
{
static string _sceneToOpen;
public static void StartScene(string sceneName)
{
if (EditorApplication.isPlaying)
{
EditorApplication.isPlaying = false;
}
_sceneToOpen = sceneName;
EditorApplication.update += OnUpdate;
}
static void OnUpdate()
{
if (_sceneToOpen == null ||
EditorApplication.isPlaying || EditorApplication.isPaused ||
EditorApplication.isCompiling || EditorApplication.isPlayingOrWillChangePlaymode)
{
return;
}
EditorApplication.update -= OnUpdate;
if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
string[] guids = AssetDatabase.FindAssets("t:scene " + _sceneToOpen, null);
if (guids.Length == 0)
{
Debug.LogWarning("Couldn't find scene file");
}
else
{
string scenePath = AssetDatabase.GUIDToAssetPath(guids[0]);
EditorSceneManager.OpenScene(scenePath);
EditorApplication.isPlaying = true;
}
}
_sceneToOpen = null;
}
}
}

View File

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

View File

@@ -0,0 +1,111 @@
using System;
using UnityEngine;
using UnityEditor;
using System.Reflection;
#if UNITY_2019_1_OR_NEWER
using UnityEngine.UIElements;
#else
using UnityEngine.Experimental.UIElements;
#endif
namespace UnityToolbarExtender
{
public static class ToolbarCallback
{
static Type m_toolbarType = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar");
static Type m_guiViewType = typeof(Editor).Assembly.GetType("UnityEditor.GUIView");
#if UNITY_2020_1_OR_NEWER
static Type m_iWindowBackendType = typeof(Editor).Assembly.GetType("UnityEditor.IWindowBackend");
static PropertyInfo m_windowBackend = m_guiViewType.GetProperty("windowBackend",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
static PropertyInfo m_viewVisualTree = m_iWindowBackendType.GetProperty("visualTree",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
#else
static PropertyInfo m_viewVisualTree = m_guiViewType.GetProperty("visualTree",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
#endif
static FieldInfo m_imguiContainerOnGui = typeof(IMGUIContainer).GetField("m_OnGUIHandler",
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
static ScriptableObject m_currentToolbar;
/// <summary>
/// Callback for toolbar OnGUI method.
/// </summary>
public static Action OnToolbarGUI;
public static Action OnToolbarGUILeft;
public static Action OnToolbarGUIRight;
static ToolbarCallback()
{
EditorApplication.update -= OnUpdate;
EditorApplication.update += OnUpdate;
}
static void OnUpdate()
{
// Relying on the fact that toolbar is ScriptableObject and gets deleted when layout changes
if (m_currentToolbar == null)
{
// Find toolbar
var toolbars = Resources.FindObjectsOfTypeAll(m_toolbarType);
m_currentToolbar = toolbars.Length > 0 ? (ScriptableObject) toolbars[0] : null;
if (m_currentToolbar != null)
{
#if UNITY_2021_1_OR_NEWER
var root = m_currentToolbar.GetType().GetField("m_Root", BindingFlags.NonPublic | BindingFlags.Instance);
var rawRoot = root.GetValue(m_currentToolbar);
var mRoot = rawRoot as VisualElement;
RegisterCallback("ToolbarZoneLeftAlign", OnToolbarGUILeft);
RegisterCallback("ToolbarZoneRightAlign", OnToolbarGUIRight);
void RegisterCallback(string root, Action cb) {
var toolbarZone = mRoot.Q(root);
var parent = new VisualElement()
{
style = {
flexGrow = 1,
flexDirection = FlexDirection.Row,
}
};
var container = new IMGUIContainer();
container.style.flexGrow = 1;
container.onGUIHandler += () => {
cb?.Invoke();
};
parent.Add(container);
toolbarZone.Add(parent);
}
#else
#if UNITY_2020_1_OR_NEWER
var windowBackend = m_windowBackend.GetValue(m_currentToolbar);
// Get it's visual tree
var visualTree = (VisualElement) m_viewVisualTree.GetValue(windowBackend, null);
#else
// Get it's visual tree
var visualTree = (VisualElement) m_viewVisualTree.GetValue(m_currentToolbar, null);
#endif
// Get first child which 'happens' to be toolbar IMGUIContainer
var container = (IMGUIContainer) visualTree[0];
// (Re)attach handler
var handler = (Action) m_imguiContainerOnGui.GetValue(container);
handler -= OnGUI;
handler += OnGUI;
m_imguiContainerOnGui.SetValue(container, handler);
#endif
}
}
}
static void OnGUI()
{
var handler = OnToolbarGUI;
if (handler != null) handler();
}
}
}

View File

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

View File

@@ -0,0 +1,169 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace UnityToolbarExtender
{
[InitializeOnLoad]
public static class ToolbarExtender
{
static int m_toolCount;
static GUIStyle m_commandStyle = null;
public static readonly List<Action> LeftToolbarGUI = new List<Action>();
public static readonly List<Action> RightToolbarGUI = new List<Action>();
static ToolbarExtender()
{
Type toolbarType = typeof(Editor).Assembly.GetType("UnityEditor.Toolbar");
#if UNITY_2019_1_OR_NEWER
string fieldName = "k_ToolCount";
#else
string fieldName = "s_ShownToolIcons";
#endif
FieldInfo toolIcons = toolbarType.GetField(fieldName,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
#if UNITY_2019_3_OR_NEWER
m_toolCount = toolIcons != null ? ((int) toolIcons.GetValue(null)) : 8;
#elif UNITY_2019_1_OR_NEWER
m_toolCount = toolIcons != null ? ((int) toolIcons.GetValue(null)) : 7;
#elif UNITY_2018_1_OR_NEWER
m_toolCount = toolIcons != null ? ((Array) toolIcons.GetValue(null)).Length : 6;
#else
m_toolCount = toolIcons != null ? ((Array) toolIcons.GetValue(null)).Length : 5;
#endif
ToolbarCallback.OnToolbarGUI = OnGUI;
ToolbarCallback.OnToolbarGUILeft = GUILeft;
ToolbarCallback.OnToolbarGUIRight = GUIRight;
}
#if UNITY_2019_3_OR_NEWER
public const float space = 8;
#else
public const float space = 10;
#endif
public const float largeSpace = 20;
public const float buttonWidth = 32;
public const float dropdownWidth = 80;
#if UNITY_2019_1_OR_NEWER
public const float playPauseStopWidth = 140;
#else
public const float playPauseStopWidth = 100;
#endif
static void OnGUI()
{
// Create two containers, left and right
// Screen is whole toolbar
if (m_commandStyle == null)
{
m_commandStyle = new GUIStyle("CommandLeft");
}
var screenWidth = EditorGUIUtility.currentViewWidth;
// Following calculations match code reflected from Toolbar.OldOnGUI()
float playButtonsPosition = Mathf.RoundToInt ((screenWidth - playPauseStopWidth) / 2);
Rect leftRect = new Rect(0, 0, screenWidth, Screen.height);
leftRect.xMin += space; // Spacing left
leftRect.xMin += buttonWidth * m_toolCount; // Tool buttons
#if UNITY_2019_3_OR_NEWER
leftRect.xMin += space; // Spacing between tools and pivot
#else
leftRect.xMin += largeSpace; // Spacing between tools and pivot
#endif
leftRect.xMin += 64 * 2; // Pivot buttons
leftRect.xMax = playButtonsPosition;
Rect rightRect = new Rect(0, 0, screenWidth, Screen.height);
rightRect.xMin = playButtonsPosition;
rightRect.xMin += m_commandStyle.fixedWidth * 3; // Play buttons
rightRect.xMax = screenWidth;
rightRect.xMax -= space; // Spacing right
rightRect.xMax -= dropdownWidth; // Layout
rightRect.xMax -= space; // Spacing between layout and layers
rightRect.xMax -= dropdownWidth; // Layers
#if UNITY_2019_3_OR_NEWER
rightRect.xMax -= space; // Spacing between layers and account
#else
rightRect.xMax -= largeSpace; // Spacing between layers and account
#endif
rightRect.xMax -= dropdownWidth; // Account
rightRect.xMax -= space; // Spacing between account and cloud
rightRect.xMax -= buttonWidth; // Cloud
rightRect.xMax -= space; // Spacing between cloud and collab
rightRect.xMax -= 78; // Colab
// Add spacing around existing controls
leftRect.xMin += space;
leftRect.xMax -= space;
rightRect.xMin += space;
rightRect.xMax -= space;
// Add top and bottom margins
#if UNITY_2019_3_OR_NEWER
leftRect.y = 4;
leftRect.height = 22;
rightRect.y = 4;
rightRect.height = 22;
#else
leftRect.y = 5;
leftRect.height = 24;
rightRect.y = 5;
rightRect.height = 24;
#endif
if (leftRect.width > 0)
{
GUILayout.BeginArea(leftRect);
GUILayout.BeginHorizontal();
foreach (var handler in LeftToolbarGUI)
{
handler();
}
GUILayout.EndHorizontal();
GUILayout.EndArea();
}
if (rightRect.width > 0)
{
GUILayout.BeginArea(rightRect);
GUILayout.BeginHorizontal();
foreach (var handler in RightToolbarGUI)
{
handler();
}
GUILayout.EndHorizontal();
GUILayout.EndArea();
}
}
public static void GUILeft() {
GUILayout.BeginHorizontal();
foreach (var handler in LeftToolbarGUI)
{
handler();
}
GUILayout.EndHorizontal();
}
public static void GUIRight() {
GUILayout.BeginHorizontal();
foreach (var handler in RightToolbarGUI)
{
handler();
}
GUILayout.EndHorizontal();
}
}
}

View File

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

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1b2fcf4655c847ef95af68f68fc9fc0a
timeCreated: 1695286287

View File

@@ -0,0 +1,335 @@
using System.Collections.Generic;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace TEngine.Editor.UI
{
public class ScriptGenerator
{
private const string Gap = "/";
[MenuItem("GameObject/ScriptGenerator/UIProperty", priority = 41)]
public static void MemberProperty()
{
Generate(false);
}
[MenuItem("GameObject/ScriptGenerator/UIProperty - UniTask", priority = 43)]
public static void MemberPropertyUniTask()
{
Generate(false, true);
}
[MenuItem("GameObject/ScriptGenerator/UIPropertyAndListener", priority = 42)]
public static void MemberPropertyAndListener()
{
Generate(true);
}
[MenuItem("GameObject/ScriptGenerator/UIPropertyAndListener - UniTask", priority = 44)]
public static void MemberPropertyAndListenerUniTask()
{
Generate(true, true);
}
private static void Generate(bool includeListener, bool isUniTask = false)
{
var root = Selection.activeTransform;
if (root != null)
{
StringBuilder strVar = new StringBuilder();
StringBuilder strBind = new StringBuilder();
StringBuilder strOnCreate = new StringBuilder();
StringBuilder strCallback = new StringBuilder();
Ergodic(root, root, ref strVar, ref strBind, ref strOnCreate, ref strCallback, isUniTask);
StringBuilder strFile = new StringBuilder();
if (includeListener)
{
#if ENABLE_TEXTMESHPRO
strFile.Append("using TMPro;\n");
#endif
if (isUniTask)
{
strFile.Append("using Cysharp.Threading.Tasks;\n");
}
strFile.Append("using UnityEngine;\n");
strFile.Append("using UnityEngine.UI;\n");
strFile.Append("using TEngine;\n\n");
strFile.Append($"namespace {SettingsUtils.GetUINameSpace()}\n");
strFile.Append("{\n");
strFile.Append("\t[Window(UILayer.UI)]\n");
strFile.Append("\tclass " + root.name + " : UIWindow\n");
strFile.Append("\t{\n");
}
// 脚本工具生成的代码
strFile.Append("\t\t#region 脚本工具生成的代码\n");
strFile.Append(strVar);
strFile.Append("\t\tpublic override void ScriptGenerator()\n");
strFile.Append("\t\t{\n");
strFile.Append(strBind);
strFile.Append(strOnCreate);
strFile.Append("\t\t}\n");
strFile.Append("\t\t#endregion");
if (includeListener)
{
strFile.Append("\n\n");
// #region 事件
strFile.Append("\t\t#region 事件\n");
strFile.Append(strCallback);
strFile.Append("\t\t#endregion\n\n");
strFile.Append("\t}\n");
strFile.Append("}\n");
}
TextEditor te = new TextEditor();
te.text = strFile.ToString();
te.SelectAll();
te.Copy();
}
}
private static void Ergodic(Transform root, Transform transform, ref StringBuilder strVar, ref StringBuilder strBind, ref StringBuilder strOnCreate,
ref StringBuilder strCallback, bool isUniTask)
{
for (int i = 0; i < transform.childCount; ++i)
{
Transform child = transform.GetChild(i);
WriteScript(root, child, ref strVar, ref strBind, ref strOnCreate, ref strCallback, isUniTask);
if (child.name.StartsWith("m_item"))
{
// 子 Item 不再往下遍历
continue;
}
Ergodic(root, child, ref strVar, ref strBind, ref strOnCreate, ref strCallback, isUniTask);
}
}
private static string GetRelativePath(Transform child, Transform root)
{
StringBuilder path = new StringBuilder();
path.Append(child.name);
while (child.parent != null && child.parent != root)
{
child = child.parent;
path.Insert(0, Gap);
path.Insert(0, child.name);
}
return path.ToString();
}
public static string GetBtnFuncName(string varName)
{
return "OnClick" + varName.Replace("m_btn", string.Empty) + "Btn";
}
public static string GetToggleFuncName(string varName)
{
return "OnToggle" + varName.Replace("m_toggle", string.Empty) + "Change";
}
public static string GetSliderFuncName(string varName)
{
return "OnSlider" + varName.Replace("m_slider", string.Empty) + "Change";
}
private static void WriteScript(Transform root, Transform child, ref StringBuilder strVar, ref StringBuilder strBind, ref StringBuilder strOnCreate,
ref StringBuilder strCallback, bool isUniTask)
{
string varName = child.name;
string componentName = string.Empty;
var rule = SettingsUtils.GetScriptGenerateRule().Find(t => varName.StartsWith(t.uiElementRegex));
if (rule != null)
{
componentName = rule.componentName;
}
if (componentName == string.Empty)
{
return;
}
string varPath = GetRelativePath(child, root);
if (!string.IsNullOrEmpty(varName))
{
strVar.Append("\t\tprivate " + componentName + " " + varName + ";\n");
switch (componentName)
{
case "Transform":
strBind.Append($"\t\t\t{varName} = FindChild(\"{varPath}\");\n");
break;
case "GameObject":
strBind.Append($"\t\t\t{varName} = FindChild(\"{varPath}\").gameObject;\n");
break;
case "AnimationCurve":
strBind.Append($"\t\t\t{varName} = FindChildComponent<AnimCurveObject>(\"{varPath}\").m_animCurve;\n");
break;
case "RichItemIcon":
case "CommonFightWidget":
case "PlayerHeadWidget":
strBind.Append($"\t\t\t{varName} = CreateWidgetByType<{componentName}>(\"{varPath}\");\n");
break;
case "RedNoteBehaviour":
case "TextButtonItem":
case "SwitchTabItem":
case "UIActorWidget":
case "UIEffectWidget":
case "UISpineWidget":
strBind.Append($"\t\t\t{varName} = CreateWidget<{componentName}>(\"{varPath}\");\n");
break;
case "ActorNameBinderText":
strBind.Append($"\t\t\t{varName} = FindTextBinder(\"{varPath}\");\n");
break;
case "ActorNameBinderEffect":
strBind.Append($"\t\t\t{varName} = FindEffectBinder(\"{varPath}\");\n");
break;
default:
strBind.Append($"\t\t\t{varName} = FindChildComponent<{componentName}>(\"{varPath}\");\n");
break;
}
if (componentName == "Button")
{
string varFuncName = GetBtnFuncName(varName);
if (isUniTask)
{
strOnCreate.Append($"\t\t\t{varName}.onClick.AddListener(UniTask.UnityAction({varFuncName}));\n");
strCallback.Append($"\t\tprivate async UniTaskVoid {varFuncName}()\n");
strCallback.Append("\t\t{\n await UniTask.Yield();\n\t\t}\n");
}
else
{
strOnCreate.Append($"\t\t\t{varName}.onClick.AddListener({varFuncName});\n");
strCallback.Append($"\t\tprivate void {varFuncName}()\n");
strCallback.Append("\t\t{\n\t\t}\n");
}
}
else if (componentName == "Toggle")
{
string varFuncName = GetToggleFuncName(varName);
strOnCreate.Append($"\t\t\t{varName}.onValueChanged.AddListener({varFuncName});\n");
strCallback.Append($"\t\tprivate void {varFuncName}(bool isOn)\n");
strCallback.Append("\t\t{\n\t\t}\n");
}
else if (componentName == "Slider")
{
string varFuncName = GetSliderFuncName(varName);
strOnCreate.Append($"\t\t\t{varName}.onValueChanged.AddListener({varFuncName});\n");
strCallback.Append($"\t\tprivate void {varFuncName}(float value)\n");
strCallback.Append("\t\t{\n\t\t}\n");
}
}
}
public class GeneratorHelper : EditorWindow
{
[MenuItem("GameObject/ScriptGenerator/About", priority = 49)]
public static void About()
{
GeneratorHelper welcomeWindow = (GeneratorHelper)EditorWindow.GetWindow(typeof(GeneratorHelper), false, "About");
}
public void Awake()
{
minSize = new Vector2(400, 600);
}
protected void OnGUI()
{
GUILayout.BeginVertical();
foreach (var item in SettingsUtils.GetScriptGenerateRule())
{
GUILayout.Label(item.uiElementRegex + "\t" + item.componentName);
}
GUILayout.EndVertical();
}
}
public class SwitchGroupGenerator
{
private const string Condition = "m_switchGroup";
public static readonly SwitchGroupGenerator Instance = new SwitchGroupGenerator();
public string Process(Transform root)
{
var sbd = new StringBuilder();
var list = new List<Transform>();
Collect(root, list);
foreach (var node in list)
{
sbd.AppendLine(Process(root, node)).AppendLine();
}
return sbd.ToString();
}
public void Collect(Transform node, List<Transform> nodeList)
{
if (node.name.StartsWith(Condition))
{
nodeList.Add(node);
return;
}
var childCnt = node.childCount;
for (var i = 0; i < childCnt; i++)
{
var child = node.GetChild(i);
Collect(child, nodeList);
}
}
private string Process(Transform root, Transform groupTf)
{
var parentPath = GetPath(root, groupTf);
var name = groupTf.name;
var sbd = new StringBuilder(@"
var _namePath = ""#parentPath"";
var _nameTf = FindChild(_namePath);
var childCnt = _nameTf.childCount;
SwitchTabItem[] _name;
_name = new SwitchTabItem[childCnt];
for (var i = 0; i < childCnt; i++)
{
var child = _nameTf.GetChild(i);
_name[i] = CreateWidget<SwitchTabItem>(_namePath + ""/"" + child.name);
}");
sbd.Replace("_name", name);
sbd.Replace("#parentPath", parentPath);
return sbd.ToString();
}
public string GetPath(Transform root, Transform childTf)
{
if (childTf == null)
{
return string.Empty;
}
if (childTf == root)
{
return childTf.name;
}
var parentPath = GetPath(root, childTf.parent);
if (parentPath == string.Empty)
{
return childTf.name;
}
return parentPath + "/" + childTf.name;
}
}
}
}

View File

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

View File

@@ -0,0 +1,179 @@
using System.Collections.Generic;
using System.Text;
using Sirenix.OdinInspector.Editor;
using TEngine.Editor.UI;
using UnityEditor;
using UnityEngine;
#if UNITY_EDITOR
namespace TEngine
{
[CanEditMultipleObjects]
[CustomEditor(typeof(UIElement), true)]
public class UIElementEditor : OdinEditor
{
protected UIElement Element;
protected override void OnEnable()
{
base.OnEnable();
Element = target as UIElement;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUI.BeginChangeCheck();
if (GUILayout.Button("Generate", GUILayout.Width(130)))
{
CheckUiItems();
}
serializedObject.ApplyModifiedProperties();
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(Element);
}
base.OnInspectorGUI();
}
protected void CheckUiItems()
{
if (Element == null) return;
ClearUnusedItems();
var root = Element.transform;
StringBuilder strVar = new StringBuilder();
StringBuilder strBind = new StringBuilder();
StringBuilder strOnCreate = new StringBuilder();
StringBuilder strOnCreateRedNote = new StringBuilder();
StringBuilder strCallback = new StringBuilder();
Ergodic(root, root, ref strVar, ref strBind, ref strOnCreate, ref strOnCreateRedNote, ref strCallback);
StringBuilder strFile = new StringBuilder();
// 脚本工具生成的代码
strFile.Append("\t\t#region 脚本工具生成的代码\n");
strFile.Append(strVar);
strFile.Append("\t\tpublic override void ScriptGenerator()\n");
strFile.Append("\t\t{\n");
strFile.Append("\t\t\tCheckUIElement();\n");
strFile.Append(strBind);
strFile.Append(strOnCreate);
strFile.Append(strOnCreateRedNote);
strFile.Append("\t\t}\n");
strFile.Append("\t\t#endregion");
TextEditor te = new TextEditor();
te.text = strFile.ToString();
te.SelectAll();
te.Copy();
}
private void ClearUnusedItems()
{
if (Element == null || Element.Elements == null) return;
List<string> ids = new List<string>();
foreach (var kv in Element.Elements)
{
if (kv.Value == null || !string.IsNullOrEmpty(GetVerType(kv.Key)))
{
ids.Add(kv.Key);
}
}
foreach (var id in ids)
{
Element.Elements.Remove(id);
}
}
private void Ergodic(Transform root, Transform transform, ref StringBuilder strVar, ref StringBuilder strBind, ref StringBuilder strOnCreate,
ref StringBuilder strOnCreateRedNote, ref StringBuilder strCallback)
{
for (int i = 0; i < transform.childCount; ++i)
{
Transform child = transform.GetChild(i);
WriteScript(root, child, ref strVar, ref strBind, ref strOnCreate, ref strOnCreateRedNote, ref strCallback);
if (child.name.StartsWith("m_item"))
{
continue;
}
Ergodic(root, child, ref strVar, ref strBind, ref strOnCreate, ref strOnCreateRedNote, ref strCallback);
}
}
private void WriteScript(Transform root, Transform child, ref StringBuilder strVar, ref StringBuilder strBind, ref StringBuilder strOnCreate,
ref StringBuilder strOnCreateRedNote, ref StringBuilder strCallback)
{
var varName = child.name;
var varType = GetVerType(varName);
if (varType == string.Empty) return;
if (Element.Elements.Contains(varName))
{
Debug.LogError("有重复的key:" + varName);
return;
}
Element.Elements[varName] = child;
if (!string.IsNullOrEmpty(varName))
{
strVar.Append("\t\tprivate " + varType + " " + varName + ";\n");
switch (varType)
{
case "Transform":
strBind.Append($"\t\t\t{varName} = FChild(\"{varName}\");\n");
break;
case "GameObject":
strBind.Append($"\t\t\t{varName} = FChild(\"{varName}\").gameObject;\n");
break;
case "RichItemIcon":
strBind.Append($"\t\t\t{varName} = CreateWidgetByType<{varType}>(FChild(\"{varName}\"));\n");
break;
case "RedNoteWidget":
break;
case "TextButtonItem":
case "SwitchTabItem":
case "UIActorWidget":
case "UIEffectWidget":
case "UISpineWidget":
case "UIMainPlayerWidget":
strBind.Append($"\t\t\t{varName} = CreateWidget<{varType}>(FChild(\"{varName}\").gameObject);\n");
break;
default:
strBind.Append($"\t\t\t{varName} = FChild<{varType}>(\"{varName}\");\n");
break;
}
if (varType == "Button")
{
string varFuncName = ScriptGenerator.GetBtnFuncName(varName);
strOnCreate.Append($"\t\t\t{varName}.onClick.AddListener({varFuncName});\n");
strCallback.Append($"\t\tprivate void {varFuncName}()\n");
strCallback.Append("\t\t{\n\t\t}\n");
}
else if (varType == "Toggle")
{
string varFuncName = ScriptGenerator.GetToggleFuncName(varName);
strOnCreate.Append($"\t\t\t{varName}.onValueChanged.AddListener({varFuncName});\n");
strCallback.Append($"\t\tprivate void {varFuncName}(bool isOn)\n");
strCallback.Append("\t\t{\n\t\t}\n");
}
}
}
protected string GetVerType(string uiName)
{
foreach (var pair in SettingsUtils.GetScriptGenerateRule())
{
if (uiName.StartsWith(pair.uiElementRegex))
{
return pair.componentName;
}
}
return string.Empty;
}
}
}
#endif

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 02ba9976b78c4a079e16aa9302c1b43e
timeCreated: 1696659319

View File

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

View File

@@ -0,0 +1,41 @@
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace TEngine.Editor
{
/// <summary>
/// 获取资源路径相关的实用函数。
/// </summary>
public static class GetAssetHelper
{
[MenuItem("Assets/Get Asset Path", priority = 3)]
static void GetAssetPath()
{
UnityEngine.Object selObj = Selection.activeObject;
if (selObj != null)
{
string assetPath = AssetDatabase.GetAssetPath(selObj);
EditorGUIUtility.systemCopyBuffer = assetPath;
Debug.Log($"Asset path is {assetPath}");
}
}
[MenuItem("Assets/Get Addressable Path", priority = 3)]
static void GetAddressablePath()
{
UnityEngine.Object selObj = Selection.activeObject;
if (selObj != null)
{
string assetPath = AssetDatabase.GetAssetPath(selObj);
var split = assetPath.Split('/');
var name = split.Last();
assetPath = name.Split('.').First();
EditorGUIUtility.systemCopyBuffer = assetPath;
Debug.Log($"Addressable path is {assetPath}");
}
}
}
}

View File

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

View File

@@ -0,0 +1,89 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
namespace TEngine.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,3 @@
fileFormatVersion: 2
guid: 5e1e932beb704b8d855ada90d41d6b56
timeCreated: 1695116209

View File

@@ -0,0 +1,83 @@
using System.Diagnostics;
using UnityEditor;
using UnityEngine;
namespace TEngine.Editor
{
/// <summary>
/// 打开文件夹相关的实用函数。
/// </summary>
public static class OpenFolderHelper
{
/// <summary>
/// 打开 Data Path 文件夹。
/// </summary>
[MenuItem("TEngine/Open Folder/Data Path", false, 10)]
public static void OpenFolderDataPath()
{
Execute(Application.dataPath);
}
/// <summary>
/// 打开 Persistent Data Path 文件夹。
/// </summary>
[MenuItem("TEngine/Open Folder/Persistent Data Path", false, 11)]
public static void OpenFolderPersistentDataPath()
{
Execute(Application.persistentDataPath);
}
/// <summary>
/// 打开 Streaming Assets Path 文件夹。
/// </summary>
[MenuItem("TEngine/Open Folder/Streaming Assets Path", false, 12)]
public static void OpenFolderStreamingAssetsPath()
{
Execute(Application.streamingAssetsPath);
}
/// <summary>
/// 打开 Temporary Cache Path 文件夹。
/// </summary>
[MenuItem("TEngine/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("TEngine/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 = $"\"{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 System.Exception($"Not support open folder on '{Application.platform}' platform.");
}
}
}
}

View File

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

View File

@@ -0,0 +1,103 @@
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace TEngine
{
public static class ShellHelper
{
public static void Run(string cmd, string workDirectory, List<string> environmentVars = null)
{
System.Diagnostics.Process process = new();
try
{
#if UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX
string app = "bash";
string splitChar = ":";
string arguments = "-c";
#elif UNITY_EDITOR_WIN
string app = "cmd.exe";
string splitChar = ";";
string arguments = "/c";
#endif
ProcessStartInfo start = new ProcessStartInfo(app);
if (environmentVars != null)
{
foreach (string var in environmentVars)
{
start.EnvironmentVariables["PATH"] += (splitChar + var);
}
}
process.StartInfo = start;
start.Arguments = arguments + " \"" + cmd + "\"";
start.CreateNoWindow = true;
start.ErrorDialog = true;
start.UseShellExecute = false;
start.WorkingDirectory = workDirectory;
if (start.UseShellExecute)
{
start.RedirectStandardOutput = false;
start.RedirectStandardError = false;
start.RedirectStandardInput = false;
}
else
{
start.RedirectStandardOutput = true;
start.RedirectStandardError = true;
start.RedirectStandardInput = true;
start.StandardOutputEncoding = System.Text.Encoding.UTF8;
start.StandardErrorEncoding = System.Text.Encoding.UTF8;
}
bool endOutput = false;
bool endError = false;
process.OutputDataReceived += (sender, args) =>
{
if (args.Data != null)
{
UnityEngine.Debug.Log(args.Data);
}
else
{
endOutput = true;
}
};
process.ErrorDataReceived += (sender, args) =>
{
if (args.Data != null)
{
UnityEngine.Debug.LogError(args.Data);
}
else
{
endError = true;
}
};
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
while (!endOutput || !endError)
{
}
process.CancelOutputRead();
process.CancelErrorRead();
}
catch (Exception e)
{
UnityEngine.Debug.LogException(e);
}
finally
{
process.Close();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a1d4e955485549fcbcc754c333953255
timeCreated: 1695193247

View File

@@ -0,0 +1,83 @@
using System.Collections.Generic;
using System.Reflection;
namespace TEngine.Editor
{
/// <summary>
/// 类型相关的实用函数。
/// </summary>
internal static class Type
{
private static readonly string[] RuntimeAssemblyNames =
{
"TEngine.Runtime",
"Assembly-CSharp",
"GameMain.Runtime",
"GameMain",
};
private static readonly string[] RuntimeOrEditorAssemblyNames =
{
"TEngine.Runtime",
"Assembly-CSharp",
"TEngine.Editor",
"Assembly-CSharp-Editor",
"GameMain",
"GameMain.Editor"
};
/// <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: 9a791d3891e3eeb40b35602635e8093b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: