提交修改
This commit is contained in:
8
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime.meta
vendored
Normal file
8
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime.meta
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78c51fb0052fac049a29ae6289cda649
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
16
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/CheckUnityVersion.cs
vendored
Normal file
16
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/CheckUnityVersion.cs
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
|
||||
namespace Fantasy
|
||||
{
|
||||
internal static class CheckUnityVersion
|
||||
{
|
||||
[InitializeOnLoadMethod]
|
||||
private static void OnInitializeOnLoad()
|
||||
{
|
||||
#if !UNITY_2022_3_OR_NEWER
|
||||
Debug.LogError("Fantasy支持的最低版本为Unity2022.3.622f2");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/CheckUnityVersion.cs.meta
vendored
Normal file
3
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/CheckUnityVersion.cs.meta
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 208434147045e0d4bae1287de7e28fa3
|
||||
timeCreated: 1725943424
|
||||
18
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Fantasy.Editor.asmdef
vendored
Normal file
18
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Fantasy.Editor.asmdef
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "Fantasy.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:0b7224b83ba514121aa026f3857f820a"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Fantasy.Editor.asmdef.meta
vendored
Normal file
7
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Fantasy.Editor.asmdef.meta
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5d7370e11934b547a4e8dac960ea72e
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
56
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/FantasyStartup.cs
vendored
Normal file
56
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/FantasyStartup.cs
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Fantasy
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public static class FantasyStartup
|
||||
{
|
||||
private const string ScriptAssemblies = "Library/ScriptAssemblies/";
|
||||
|
||||
static FantasyStartup()
|
||||
{
|
||||
if (!FantasySettingsScriptableObject.Instance.autoCopyAssembly)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var hotUpdatePath = FantasySettingsScriptableObject.Instance.hotUpdatePath;
|
||||
|
||||
if (string.IsNullOrEmpty(hotUpdatePath))
|
||||
{
|
||||
Debug.LogError("请先在菜单Fantasy-Fantasy Settings里设置自动拷贝程序集输出目录位置");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(hotUpdatePath))
|
||||
{
|
||||
Directory.CreateDirectory(hotUpdatePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var file in Directory.GetFiles(hotUpdatePath))
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
|
||||
// ReSharper disable once StringLastIndexOfIsCultureSpecific.1
|
||||
if (hotUpdatePath.LastIndexOf("/") != hotUpdatePath.Length - 1)
|
||||
{
|
||||
FantasySettingsScriptableObject.Instance.hotUpdatePath += "/";
|
||||
hotUpdatePath = FantasySettingsScriptableObject.Instance.hotUpdatePath;
|
||||
}
|
||||
|
||||
foreach (var instanceHotUpdateAssemblyDefinition in FantasySettingsScriptableObject.Instance.hotUpdateAssemblyDefinitions)
|
||||
{
|
||||
var dll = instanceHotUpdateAssemblyDefinition.name;
|
||||
File.Copy($"{ScriptAssemblies}{dll}.dll", $"{hotUpdatePath}/{dll}.dll.bytes", true);
|
||||
File.Copy($"{ScriptAssemblies}{dll}.pdb", $"{hotUpdatePath}/{dll}.pdb.bytes", true);
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/FantasyStartup.cs.meta
vendored
Normal file
3
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/FantasyStartup.cs.meta
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13e9d2b99522b124680b7723aaded8d9
|
||||
timeCreated: 1688276977
|
||||
64
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/LinkXmlGenerator.cs
vendored
Normal file
64
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/LinkXmlGenerator.cs
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Fantasy
|
||||
{
|
||||
public class LinkXmlGenerator
|
||||
{
|
||||
private const string LinkPath = "Assets/link.xml";
|
||||
// 在Unity编辑器中运行该方法来生成link.xml文件
|
||||
public static void GenerateLinkXml()
|
||||
{
|
||||
using (var writer = new StreamWriter("Assets/link.xml"))
|
||||
{
|
||||
var assemblyHashSet = new HashSet<string>();
|
||||
|
||||
foreach (var assembly in FantasySettingsScriptableObject.Instance.includeAssembly)
|
||||
{
|
||||
assemblyHashSet.Add(assembly);
|
||||
}
|
||||
|
||||
if (FantasySettingsScriptableObject.Instance?.linkAssemblyDefinitions != null)
|
||||
{
|
||||
foreach (var assemblyDefinition in FantasySettingsScriptableObject.Instance.linkAssemblyDefinitions)
|
||||
{
|
||||
assemblyHashSet.Add(assemblyDefinition.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (assemblyHashSet.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
writer.WriteLine("<linker>");
|
||||
|
||||
foreach (var assembly in assemblyHashSet)
|
||||
{
|
||||
GenerateLinkXml(writer, assembly, LinkPath);
|
||||
Debug.Log($"{assembly} Link generation completed");
|
||||
}
|
||||
|
||||
writer.WriteLine("</linker>");
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("link.xml generated successfully!");
|
||||
}
|
||||
|
||||
private static void GenerateLinkXml(StreamWriter writer, string assemblyName, string outputPath)
|
||||
{
|
||||
var assembly = System.Reflection.Assembly.Load(assemblyName);
|
||||
var types = assembly.GetTypes();
|
||||
writer.WriteLine($" <assembly fullname=\"{assembly.GetName().Name}\">");
|
||||
foreach (var type in types)
|
||||
{
|
||||
var typeName = type.FullName.Replace('<', '+').Replace('>', '+');
|
||||
writer.WriteLine($" <type fullname=\"{typeName}\" preserve=\"all\"/>");
|
||||
}
|
||||
writer.WriteLine(" </assembly>");
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/LinkXmlGenerator.cs.meta
vendored
Normal file
3
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/LinkXmlGenerator.cs.meta
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3360ff806a3d27d478e0e554ebbb291b
|
||||
timeCreated: 1722743236
|
||||
3
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Settings.meta
vendored
Normal file
3
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Settings.meta
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4481b9186fbddb04f96e2e6e56e9ebfc
|
||||
timeCreated: 1688277110
|
||||
13
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Settings/FantasySettings.cs
vendored
Normal file
13
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Settings/FantasySettings.cs
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace Fantasy
|
||||
{
|
||||
public class FantasySettings
|
||||
{
|
||||
[MenuItem("Fantasy/Fantasy Settings")]
|
||||
public static void OpenFantasySettings()
|
||||
{
|
||||
SettingsService.OpenProjectSettings("Project/Fantasy Settings");
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Settings/FantasySettings.cs.meta
vendored
Normal file
3
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Settings/FantasySettings.cs.meta
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a31e33b6eab0e847a6e836cf0f9835d
|
||||
timeCreated: 1686913667
|
||||
725
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Settings/FantasySettingsProvider.cs
vendored
Normal file
725
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Settings/FantasySettingsProvider.cs
vendored
Normal file
@@ -0,0 +1,725 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace Fantasy
|
||||
{
|
||||
public class FantasySettingsProvider : SettingsProvider
|
||||
{
|
||||
private SerializedObject _serializedObject;
|
||||
private SerializedProperty _autoCopyAssembly;
|
||||
private SerializedProperty _hotUpdatePath;
|
||||
private SerializedProperty _hotUpdateAssemblyDefinitions;
|
||||
private SerializedProperty _linkAssemblyDefinitions;
|
||||
private SerializedProperty _includeAssembly;
|
||||
private bool _showLinkXmlConfig = true; // 控制是否显示 Link.xml 配置
|
||||
public FantasySettingsProvider() : base("Project/Fantasy Settings", SettingsScope.Project) { }
|
||||
|
||||
public override void OnActivate(string searchContext, VisualElement rootElement)
|
||||
{
|
||||
Init();
|
||||
base.OnActivate(searchContext, rootElement);
|
||||
}
|
||||
|
||||
public override void OnDeactivate()
|
||||
{
|
||||
base.OnDeactivate();
|
||||
FantasySettingsScriptableObject.Save();
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
_serializedObject?.Dispose();
|
||||
_serializedObject = new SerializedObject(FantasySettingsScriptableObject.Instance);
|
||||
_autoCopyAssembly = _serializedObject.FindProperty("autoCopyAssembly");
|
||||
_hotUpdatePath = _serializedObject.FindProperty("hotUpdatePath");
|
||||
_hotUpdateAssemblyDefinitions = _serializedObject.FindProperty("hotUpdateAssemblyDefinitions");
|
||||
_linkAssemblyDefinitions = _serializedObject.FindProperty("linkAssemblyDefinitions");
|
||||
_includeAssembly = _serializedObject.FindProperty("includeAssembly");
|
||||
}
|
||||
|
||||
public override void OnGUI(string searchContext)
|
||||
{
|
||||
if (_serializedObject == null || !_serializedObject.targetObject)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
using (CreateSettingsWindowGUIScope())
|
||||
{
|
||||
_serializedObject!.Update();
|
||||
|
||||
// ============ Fantasy 框架集成检测 ============
|
||||
DrawCscRspInstallationSection();
|
||||
DrawSectionDivider();
|
||||
EditorGUILayout.Space(10);
|
||||
// ============ 程序集自动拷贝设置 ============
|
||||
EditorGUI.BeginChangeCheck();
|
||||
DrawAssemblyCopySection();
|
||||
DrawSectionDivider();
|
||||
// ============ Link.xml 生成设置 ============
|
||||
DrawLinkXmlSection();
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
_serializedObject.ApplyModifiedProperties();
|
||||
FantasySettingsScriptableObject.Save();
|
||||
EditorApplication.RepaintHierarchyWindow();
|
||||
}
|
||||
|
||||
base.OnGUI(searchContext);
|
||||
}
|
||||
}
|
||||
|
||||
private IDisposable CreateSettingsWindowGUIScope()
|
||||
{
|
||||
var unityEditorAssembly = System.Reflection.Assembly.GetAssembly(typeof(EditorWindow));
|
||||
var type = unityEditorAssembly.GetType("UnityEditor.SettingsWindow+GUIScope");
|
||||
return Activator.CreateInstance(type) as IDisposable;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制 csc.rsp 安装状态区域
|
||||
/// </summary>
|
||||
private void DrawCscRspInstallationSection()
|
||||
{
|
||||
bool isInstalled = CheckCscRspStatus(out bool fileExists, out bool hasDefine);
|
||||
|
||||
// 状态框
|
||||
if (isInstalled)
|
||||
{
|
||||
// 已安装 - 绿色背景框
|
||||
GUIStyle boxStyle = new GUIStyle(GUI.skin.box)
|
||||
{
|
||||
padding = new RectOffset(10, 10, 10, 10),
|
||||
margin = new RectOffset(0, 0, 5, 5)
|
||||
};
|
||||
|
||||
Color originalColor = GUI.color;
|
||||
GUI.color = new Color(0.7f, 1f, 0.7f); // 绿色背景
|
||||
|
||||
EditorGUILayout.BeginVertical(boxStyle);
|
||||
GUI.color = originalColor;
|
||||
|
||||
GUIStyle installedButtonStyle = new GUIStyle(GUI.skin.button)
|
||||
{
|
||||
fontSize = 13,
|
||||
fontStyle = FontStyle.Bold,
|
||||
fixedHeight = 35
|
||||
};
|
||||
|
||||
Color originalBgColor = GUI.backgroundColor;
|
||||
GUI.backgroundColor = new Color(0.3f, 0.8f, 0.3f); // 绿色
|
||||
GUI.enabled = false; // 禁用按钮,只显示状态
|
||||
GUILayout.Button("✓ FANTASY_UNITY 已安装", installedButtonStyle);
|
||||
GUI.enabled = true;
|
||||
GUI.backgroundColor = originalBgColor;
|
||||
|
||||
EditorGUILayout.Space(3);
|
||||
EditorGUILayout.HelpBox("编译器配置正确,框架功能已启用", MessageType.Info);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 未安装 - 橙黄色背景框
|
||||
GUIStyle boxStyle = new GUIStyle(GUI.skin.box)
|
||||
{
|
||||
padding = new RectOffset(10, 10, 10, 10),
|
||||
margin = new RectOffset(0, 0, 5, 5)
|
||||
};
|
||||
|
||||
Color originalColor = GUI.color;
|
||||
GUI.color = Color.red; // 橙黄色背景
|
||||
|
||||
EditorGUILayout.BeginVertical(boxStyle);
|
||||
GUI.color = originalColor;
|
||||
|
||||
EditorGUILayout.Space(8);
|
||||
|
||||
// 醒目的大按钮
|
||||
GUIStyle buttonStyle = new GUIStyle(GUI.skin.button)
|
||||
{
|
||||
fontSize = 13,
|
||||
fontStyle = FontStyle.Bold,
|
||||
fixedHeight = 35
|
||||
};
|
||||
|
||||
Color originalBgColor = GUI.backgroundColor;
|
||||
GUI.backgroundColor = new Color(0.3f, 0.8f, 1f);
|
||||
if (GUILayout.Button("点击安装 FANTASY_UNITY", buttonStyle))
|
||||
{
|
||||
InstallFantasyUnityDefine();
|
||||
}
|
||||
GUI.backgroundColor = originalBgColor;
|
||||
|
||||
EditorGUILayout.Space(3);
|
||||
EditorGUILayout.HelpBox("安装后可能需要重新编译项目才能生效", MessageType.Info);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测 csc.rsp 文件状态
|
||||
/// </summary>
|
||||
/// <param name="fileExists">文件是否存在</param>
|
||||
/// <param name="hasDefine">是否包含 FANTASY_UNITY 定义</param>
|
||||
/// <returns>是否已正确安装</returns>
|
||||
private bool CheckCscRspStatus(out bool fileExists, out bool hasDefine)
|
||||
{
|
||||
string cscRspPath = Path.Combine(Application.dataPath, "csc.rsp");
|
||||
fileExists = File.Exists(cscRspPath);
|
||||
hasDefine = false;
|
||||
|
||||
if (fileExists)
|
||||
{
|
||||
string content = File.ReadAllText(cscRspPath);
|
||||
// 使用正则表达式精确匹配 FANTASY_UNITY(确保是完整的单词,不是其他定义的一部分)
|
||||
// 匹配条件:FANTASY_UNITY 后面是分号、空白字符、换行或文件结束
|
||||
hasDefine = System.Text.RegularExpressions.Regex.IsMatch(
|
||||
content,
|
||||
@"\bFANTASY_UNITY\b"
|
||||
);
|
||||
}
|
||||
|
||||
return fileExists && hasDefine;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安装 FANTASY_UNITY 定义到 csc.rsp 文件
|
||||
/// </summary>
|
||||
private void InstallFantasyUnityDefine()
|
||||
{
|
||||
string cscRspPath = Path.Combine(Application.dataPath, "csc.rsp");
|
||||
|
||||
try
|
||||
{
|
||||
if (!File.Exists(cscRspPath))
|
||||
{
|
||||
// 创建新文件
|
||||
File.WriteAllText(cscRspPath, "-define:FANTASY_UNITY\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 读取现有内容
|
||||
string content = File.ReadAllText(cscRspPath);
|
||||
|
||||
// 使用正则表达式精确检测,避免误判(例如 FANTASY_UNITY123)
|
||||
bool hasFantasyUnity = System.Text.RegularExpressions.Regex.IsMatch(
|
||||
content,
|
||||
@"\bFANTASY_UNITY\b"
|
||||
);
|
||||
|
||||
if (!hasFantasyUnity)
|
||||
{
|
||||
// 查找是否已有 -define: 行
|
||||
string[] lines = content.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
bool defineLineFound = false;
|
||||
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
if (lines[i].TrimStart().StartsWith("-define:"))
|
||||
{
|
||||
// 添加到现有的 define 行
|
||||
if (lines[i].EndsWith(";"))
|
||||
{
|
||||
lines[i] = lines[i] + "FANTASY_UNITY";
|
||||
}
|
||||
else
|
||||
{
|
||||
lines[i] = lines[i] + ";FANTASY_UNITY";
|
||||
}
|
||||
defineLineFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (defineLineFound)
|
||||
{
|
||||
content = string.Join("\n", lines) + "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// 添加新的 define 行到文件开头
|
||||
content = "-define:FANTASY_UNITY\n" + content;
|
||||
}
|
||||
|
||||
File.WriteAllText(cscRspPath, content);
|
||||
}
|
||||
}
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
EditorUtility.DisplayDialog("成功", "FANTASY_UNITY 已经安装成功。\n\n重新编译后生效。", "确定");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"安装 FANTASY_UNITY 失败: {ex.Message}");
|
||||
EditorUtility.DisplayDialog("错误", $"安装失败:\n{ex.Message}", "确定");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制分隔线
|
||||
/// </summary>
|
||||
private void DrawSectionDivider()
|
||||
{
|
||||
EditorGUILayout.Space(5);
|
||||
|
||||
Rect rect = EditorGUILayout.GetControlRect(false, 1);
|
||||
rect.height = 1;
|
||||
|
||||
// 绘制细线
|
||||
EditorGUI.DrawRect(rect, new Color(0.5f, 0.5f, 0.5f, 0.3f));
|
||||
|
||||
EditorGUILayout.Space(5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制程序集自动拷贝设置区域
|
||||
/// </summary>
|
||||
private void DrawAssemblyCopySection()
|
||||
{
|
||||
// 标题
|
||||
GUIStyle titleStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
fontSize = 14,
|
||||
alignment = TextAnchor.MiddleLeft
|
||||
};
|
||||
EditorGUILayout.LabelField("程序集自动拷贝", titleStyle);
|
||||
EditorGUILayout.Space(5);
|
||||
|
||||
// 功能说明
|
||||
GUIStyle descStyle = new GUIStyle(EditorStyles.wordWrappedLabel)
|
||||
{
|
||||
fontSize = 11,
|
||||
normal = { textColor = Color.gray }
|
||||
};
|
||||
EditorGUILayout.LabelField("Unity 编译后自动将指定的程序集文件(DLL + PDB)复制到目标目录,用于热更新或其他用途", descStyle);
|
||||
EditorGUILayout.Space(8);
|
||||
|
||||
// 主开关区域
|
||||
GUIStyle boxStyle = new GUIStyle(GUI.skin.box)
|
||||
{
|
||||
padding = new RectOffset(12, 12, 12, 12),
|
||||
margin = new RectOffset(0, 0, 0, 8)
|
||||
};
|
||||
|
||||
EditorGUILayout.BeginVertical(boxStyle);
|
||||
|
||||
// 开关 - 更大更明显
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
GUIStyle bigToggleStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
fontSize = 13
|
||||
};
|
||||
|
||||
bool newValue = EditorGUILayout.ToggleLeft("启用自动拷贝", _autoCopyAssembly.boolValue, bigToggleStyle);
|
||||
|
||||
if (newValue != _autoCopyAssembly.boolValue)
|
||||
{
|
||||
_autoCopyAssembly.boolValue = newValue;
|
||||
}
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
if (_autoCopyAssembly.boolValue)
|
||||
{
|
||||
GUIStyle statusLabel = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
fontSize = 11,
|
||||
normal = { textColor = new Color(0f, 0.6f, 0f) }
|
||||
};
|
||||
EditorGUILayout.LabelField("● 已启用", statusLabel, GUILayout.Width(60));
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIStyle statusLabel = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
fontSize = 11,
|
||||
normal = { textColor = Color.gray }
|
||||
};
|
||||
EditorGUILayout.LabelField("○ 已禁用", statusLabel, GUILayout.Width(60));
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
// 如果启用了自动拷贝,显示详细配置
|
||||
if (_autoCopyAssembly.boolValue)
|
||||
{
|
||||
EditorGUILayout.Space(15);
|
||||
|
||||
// 步骤 1:设置输出目录
|
||||
DrawStepHeader("1", "设置输出目录");
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PropertyField(_hotUpdatePath, GUIContent.none);
|
||||
if (GUILayout.Button("选择文件夹", GUILayout.Width(80)))
|
||||
{
|
||||
string path = EditorUtility.OpenFolderPanel("选择程序集输出目录", _hotUpdatePath.stringValue, "");
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
_hotUpdatePath.stringValue = path;
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
// 路径状态提示
|
||||
if (string.IsNullOrEmpty(_hotUpdatePath.stringValue))
|
||||
{
|
||||
EditorGUILayout.Space(3);
|
||||
GUIStyle warningStyle = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
normal = { textColor = new Color(0.8f, 0.4f, 0f) }
|
||||
};
|
||||
EditorGUILayout.LabelField("⚠ 请先设置输出目录", warningStyle);
|
||||
}
|
||||
else if (!Directory.Exists(_hotUpdatePath.stringValue))
|
||||
{
|
||||
EditorGUILayout.Space(3);
|
||||
GUIStyle warningStyle = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
normal = { textColor = new Color(0.6f, 0.6f, 0f) }
|
||||
};
|
||||
EditorGUILayout.LabelField("ℹ 目录不存在,编译时将自动创建", warningStyle);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.Space(3);
|
||||
GUIStyle successStyle = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
normal = { textColor = new Color(0f, 0.6f, 0f) }
|
||||
};
|
||||
EditorGUILayout.LabelField("✓ 目录已配置", successStyle);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space(15);
|
||||
|
||||
// 步骤 2:选择要拷贝的程序集
|
||||
DrawStepHeader("2", "程序集列表");
|
||||
|
||||
GUIStyle hintStyle = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
fontSize = 10,
|
||||
normal = { textColor = Color.gray }
|
||||
};
|
||||
EditorGUILayout.LabelField("选择需要自动拷贝的热更新程序集", hintStyle);
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
// 程序集列表区域
|
||||
if (_hotUpdateAssemblyDefinitions.arraySize == 0)
|
||||
{
|
||||
// 空状态提示框
|
||||
Color originalColor = GUI.color;
|
||||
GUI.color = new Color(0.95f, 0.95f, 0.95f);
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
GUI.color = originalColor;
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
GUIStyle emptyIconStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
fontSize = 20,
|
||||
alignment = TextAnchor.MiddleCenter,
|
||||
normal = { textColor = new Color(0.6f, 0.6f, 0.6f) }
|
||||
};
|
||||
EditorGUILayout.LabelField("📦", emptyIconStyle);
|
||||
|
||||
GUIStyle emptyTextStyle = new GUIStyle(EditorStyles.label)
|
||||
{
|
||||
fontSize = 11,
|
||||
alignment = TextAnchor.MiddleCenter,
|
||||
normal = { textColor = Color.gray }
|
||||
};
|
||||
EditorGUILayout.LabelField("暂未添加任何程序集", emptyTextStyle);
|
||||
|
||||
EditorGUILayout.Space(5);
|
||||
|
||||
GUIStyle addHintStyle = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
fontSize = 10,
|
||||
alignment = TextAnchor.MiddleCenter,
|
||||
normal = { textColor = new Color(0.3f, 0.6f, 1f) }
|
||||
};
|
||||
EditorGUILayout.LabelField("点击下方的 + 按钮添加程序集", addHintStyle);
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
EditorGUILayout.Space(5);
|
||||
}
|
||||
|
||||
// 程序集列表
|
||||
EditorGUILayout.PropertyField(_hotUpdateAssemblyDefinitions, new GUIContent(""), true);
|
||||
|
||||
if (_hotUpdateAssemblyDefinitions.arraySize > 0)
|
||||
{
|
||||
EditorGUILayout.Space(5);
|
||||
GUIStyle successStyle = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
normal = { textColor = new Color(0f, 0.6f, 0f) }
|
||||
};
|
||||
EditorGUILayout.LabelField($"✓ 已添加 {_hotUpdateAssemblyDefinitions.arraySize} 个程序集", successStyle);
|
||||
}
|
||||
|
||||
// 配置完成状态总结
|
||||
bool isConfigured = !string.IsNullOrEmpty(_hotUpdatePath.stringValue) && _hotUpdateAssemblyDefinitions.arraySize > 0;
|
||||
|
||||
if (isConfigured)
|
||||
{
|
||||
Color originalColor = GUI.color;
|
||||
GUI.color = new Color(0.8f, 1f, 0.8f);
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
GUI.color = originalColor;
|
||||
|
||||
GUIStyle summaryStyle = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
fontSize = 11,
|
||||
normal = { textColor = new Color(0f, 0.5f, 0f) }
|
||||
};
|
||||
EditorGUILayout.LabelField($"✓ 配置完成!编译后将自动拷贝 {_hotUpdateAssemblyDefinitions.arraySize} 个程序集到目标目录", summaryStyle);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.Space(8);
|
||||
EditorGUILayout.HelpBox("启用后可在 Unity 编译完成时自动拷贝程序集文件", MessageType.Info);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制步骤标题
|
||||
/// </summary>
|
||||
private void DrawStepHeader(string stepNumber, string title)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
// 步骤编号
|
||||
GUIStyle stepStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
fontSize = 12,
|
||||
normal = { textColor = new Color(0.3f, 0.6f, 1f) }
|
||||
};
|
||||
EditorGUILayout.LabelField($"步骤 {stepNumber}:", stepStyle, GUILayout.Width(60));
|
||||
|
||||
// 步骤标题
|
||||
GUIStyle titleStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
fontSize = 12
|
||||
};
|
||||
EditorGUILayout.LabelField(title, titleStyle);
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUILayout.Space(5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 绘制 Link.xml 生成设置区域
|
||||
/// </summary>
|
||||
private void DrawLinkXmlSection()
|
||||
{
|
||||
// 标题
|
||||
GUIStyle titleStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
fontSize = 14,
|
||||
alignment = TextAnchor.MiddleLeft
|
||||
};
|
||||
EditorGUILayout.LabelField("Link.xml 代码裁剪配置", titleStyle);
|
||||
EditorGUILayout.Space(5);
|
||||
|
||||
// 功能说明
|
||||
GUIStyle descStyle = new GUIStyle(EditorStyles.wordWrappedLabel)
|
||||
{
|
||||
fontSize = 11,
|
||||
normal = { textColor = Color.gray }
|
||||
};
|
||||
EditorGUILayout.LabelField("配置 Link.xml 文件以防止 IL2CPP 编译时过度裁剪反射或动态调用的代码,确保运行时正常", descStyle);
|
||||
EditorGUILayout.Space(8);
|
||||
|
||||
GUIStyle boxStyle = new GUIStyle(GUI.skin.box)
|
||||
{
|
||||
padding = new RectOffset(12, 12, 12, 12),
|
||||
margin = new RectOffset(0, 0, 0, 8)
|
||||
};
|
||||
|
||||
EditorGUILayout.BeginVertical(boxStyle);
|
||||
|
||||
// 显示配置开关
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
GUIStyle bigToggleStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
fontSize = 13
|
||||
};
|
||||
|
||||
_showLinkXmlConfig = EditorGUILayout.ToggleLeft("显示配置", _showLinkXmlConfig, bigToggleStyle);
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
if (_showLinkXmlConfig)
|
||||
{
|
||||
GUIStyle statusLabel = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
fontSize = 11,
|
||||
normal = { textColor = new Color(0.3f, 0.6f, 1f) }
|
||||
};
|
||||
EditorGUILayout.LabelField("● 已展开", statusLabel, GUILayout.Width(60));
|
||||
}
|
||||
else
|
||||
{
|
||||
GUIStyle statusLabel = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
fontSize = 11,
|
||||
normal = { textColor = Color.gray }
|
||||
};
|
||||
EditorGUILayout.LabelField("○ 已折叠", statusLabel, GUILayout.Width(60));
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
// 如果显示配置,则展示详细内容
|
||||
if (_showLinkXmlConfig)
|
||||
{
|
||||
EditorGUILayout.Space(15);
|
||||
|
||||
// 程序集定义配置标题
|
||||
GUIStyle sectionTitleStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
fontSize = 13
|
||||
};
|
||||
EditorGUILayout.LabelField("需要保护的程序集", sectionTitleStyle);
|
||||
EditorGUILayout.Space(3);
|
||||
|
||||
GUIStyle hintStyle = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
fontSize = 10,
|
||||
normal = { textColor = Color.gray }
|
||||
};
|
||||
EditorGUILayout.LabelField("选择需要在 IL2CPP 编译时防止代码裁剪的程序集", hintStyle);
|
||||
EditorGUILayout.Space(3);
|
||||
|
||||
// 默认包含程序集说明
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(5);
|
||||
GUIStyle defaultInfoStyle = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
fontSize = 10,
|
||||
normal = { textColor = new Color(0.4f, 0.6f, 0.8f) }
|
||||
};
|
||||
EditorGUILayout.LabelField("ℹ 默认包含:Assembly-CSharp、Fantasy.Unity", defaultInfoStyle);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
// 程序集列表区域
|
||||
if (_linkAssemblyDefinitions.arraySize == 0)
|
||||
{
|
||||
// 空状态提示框
|
||||
Color originalColor = GUI.color;
|
||||
GUI.color = new Color(0.95f, 0.95f, 0.95f);
|
||||
EditorGUILayout.BeginVertical(GUI.skin.box);
|
||||
GUI.color = originalColor;
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
GUIStyle emptyIconStyle = new GUIStyle(EditorStyles.boldLabel)
|
||||
{
|
||||
fontSize = 20,
|
||||
alignment = TextAnchor.MiddleCenter,
|
||||
normal = { textColor = new Color(0.6f, 0.6f, 0.6f) }
|
||||
};
|
||||
EditorGUILayout.LabelField("📋", emptyIconStyle);
|
||||
|
||||
GUIStyle emptyTextStyle = new GUIStyle(EditorStyles.label)
|
||||
{
|
||||
fontSize = 11,
|
||||
alignment = TextAnchor.MiddleCenter,
|
||||
normal = { textColor = Color.gray }
|
||||
};
|
||||
EditorGUILayout.LabelField("暂未添加任何程序集", emptyTextStyle);
|
||||
|
||||
EditorGUILayout.Space(5);
|
||||
|
||||
GUIStyle addHintStyle = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
fontSize = 10,
|
||||
alignment = TextAnchor.MiddleCenter,
|
||||
normal = { textColor = new Color(0.3f, 0.6f, 1f) }
|
||||
};
|
||||
EditorGUILayout.LabelField("点击下方的 + 按钮添加程序集", addHintStyle);
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
EditorGUILayout.Space(5);
|
||||
}
|
||||
|
||||
// 程序集列表
|
||||
EditorGUILayout.PropertyField(_linkAssemblyDefinitions, new GUIContent(""), true);
|
||||
|
||||
if (_linkAssemblyDefinitions.arraySize > 0)
|
||||
{
|
||||
EditorGUILayout.Space(5);
|
||||
GUIStyle successStyle = new GUIStyle(EditorStyles.miniLabel)
|
||||
{
|
||||
normal = { textColor = new Color(0f, 0.6f, 0f) }
|
||||
};
|
||||
EditorGUILayout.LabelField($"✓ 已添加 {_linkAssemblyDefinitions.arraySize} 个程序集", successStyle);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space(15);
|
||||
|
||||
// 生成按钮区域
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.FlexibleSpace();
|
||||
|
||||
GUIStyle buttonStyle = new GUIStyle(GUI.skin.button)
|
||||
{
|
||||
fontSize = 13,
|
||||
fontStyle = FontStyle.Bold,
|
||||
fixedHeight = 35,
|
||||
fixedWidth = 200
|
||||
};
|
||||
|
||||
Color originalBgColor = GUI.backgroundColor;
|
||||
GUI.backgroundColor = new Color(0.4f, 0.7f, 1f);
|
||||
if (GUILayout.Button("生成 Link.xml 文件", buttonStyle))
|
||||
{
|
||||
LinkXmlGenerator.GenerateLinkXml();
|
||||
EditorUtility.DisplayDialog("操作成功", "Link.xml 文件已生成", "确定");
|
||||
}
|
||||
GUI.backgroundColor = originalBgColor;
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.Space(8);
|
||||
EditorGUILayout.HelpBox("点击上方开关展开配置", MessageType.Info);
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
static FantasySettingsProvider _provider;
|
||||
|
||||
[SettingsProvider]
|
||||
public static SettingsProvider CreateMyCustomSettingsProvider()
|
||||
{
|
||||
if (FantasySettingsScriptableObject.Instance && _provider == null)
|
||||
{
|
||||
_provider = new FantasySettingsProvider();
|
||||
using (var so = new SerializedObject(FantasySettingsScriptableObject.Instance))
|
||||
{
|
||||
_provider.keywords = GetSearchKeywordsFromSerializedObject(so);
|
||||
}
|
||||
}
|
||||
return _provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19a618703b49e3d4fbcd8223540a77f3
|
||||
timeCreated: 1688380387
|
||||
@@ -0,0 +1,25 @@
|
||||
using UnityEditor;
|
||||
using UnityEditor.Compilation;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace Fantasy
|
||||
{
|
||||
[ScriptableObjectPath("ProjectSettings/FantasySettings.asset")]
|
||||
public class FantasySettingsScriptableObject : ScriptableObjectSingleton<FantasySettingsScriptableObject>, ISerializationCallbackReceiver
|
||||
{
|
||||
[FormerlySerializedAs("AutoCopyAssembly")]
|
||||
public bool autoCopyAssembly = false;
|
||||
[FormerlySerializedAs("HotUpdatePath")]
|
||||
public string hotUpdatePath;
|
||||
[FormerlySerializedAs("HotUpdateAssemblyDefinitions")]
|
||||
public AssemblyDefinitionAsset[] hotUpdateAssemblyDefinitions;
|
||||
[FormerlySerializedAs("LinkAssemblyDefinitions")]
|
||||
public AssemblyDefinitionAsset[] linkAssemblyDefinitions;
|
||||
[FormerlySerializedAs("IncludeAssembly")]
|
||||
public string[] includeAssembly = new[] { "Assembly-CSharp", "Fantasy.Unity" };
|
||||
public void OnBeforeSerialize() { }
|
||||
public void OnAfterDeserialize() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6733837e208a20a488d61c50fb71919c
|
||||
timeCreated: 1688277120
|
||||
100
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Settings/ScriptableObjectSingleton.cs
vendored
Normal file
100
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/Settings/ScriptableObjectSingleton.cs
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
// ReSharper disable AssignNullToNotNullAttribute
|
||||
|
||||
namespace Fantasy
|
||||
{
|
||||
public class ScriptableObjectSingleton<T> : ScriptableObject where T : ScriptableObject
|
||||
{
|
||||
private static T _instance;
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = Load();
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private static T Load()
|
||||
{
|
||||
var scriptableObjectPath = GetScriptableObjectPath();
|
||||
|
||||
if (string.IsNullOrEmpty(scriptableObjectPath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var loadSerializedFileAndForget = InternalEditorUtility.LoadSerializedFileAndForget(scriptableObjectPath);
|
||||
|
||||
if (loadSerializedFileAndForget.Length <= 0)
|
||||
{
|
||||
return CreateInstance<T>();
|
||||
}
|
||||
|
||||
return loadSerializedFileAndForget[0] as T;
|
||||
}
|
||||
|
||||
public static void Save(bool saveAsText = true)
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
Debug.LogError("Cannot save ScriptableObjectSingleton: no instance!");
|
||||
return;
|
||||
}
|
||||
|
||||
var scriptableObjectPath = GetScriptableObjectPath();
|
||||
|
||||
if (string.IsNullOrEmpty(scriptableObjectPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var directoryName = Path.GetDirectoryName(scriptableObjectPath);
|
||||
|
||||
if (!Directory.Exists(directoryName))
|
||||
{
|
||||
Directory.CreateDirectory(directoryName);
|
||||
}
|
||||
|
||||
UnityEngine.Object[] obj = { _instance };
|
||||
InternalEditorUtility.SaveToSerializedFileAndForget(obj, scriptableObjectPath, saveAsText);
|
||||
}
|
||||
|
||||
private static string GetScriptableObjectPath()
|
||||
{
|
||||
var scriptableObjectPathAttribute = typeof(T).GetCustomAttribute(typeof(ScriptableObjectPathAttribute)) as ScriptableObjectPathAttribute;
|
||||
return scriptableObjectPathAttribute?.ScriptableObjectPath;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
|
||||
public class ScriptableObjectPathAttribute : Attribute
|
||||
{
|
||||
internal readonly string ScriptableObjectPath;
|
||||
|
||||
public ScriptableObjectPathAttribute(string scriptableObjectPath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(scriptableObjectPath))
|
||||
{
|
||||
throw new ArgumentException("Invalid relative path (it is empty)");
|
||||
}
|
||||
|
||||
if (scriptableObjectPath[0] == '/')
|
||||
{
|
||||
scriptableObjectPath = scriptableObjectPath.Substring(1);
|
||||
}
|
||||
|
||||
ScriptableObjectPath = scriptableObjectPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8963b5817140ad42a1a5cae9d6a4336
|
||||
timeCreated: 1688278016
|
||||
8
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/WSocket.meta
vendored
Normal file
8
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/WSocket.meta
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6603a5cb5b34f44fb04cfca6e80092d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
229
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/WSocket/SettingsWindow.cs
vendored
Normal file
229
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/WSocket/SettingsWindow.cs
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.Networking;
|
||||
using System.IO;
|
||||
using System;
|
||||
|
||||
namespace UnityWebSocket.Editor
|
||||
{
|
||||
internal class SettingsWindow : EditorWindow
|
||||
{
|
||||
static SettingsWindow window = null;
|
||||
[MenuItem("Tools/UnityWebSocket", priority = 100)]
|
||||
internal static void Open()
|
||||
{
|
||||
if (window != null)
|
||||
{
|
||||
window.Close();
|
||||
}
|
||||
|
||||
window = GetWindow<SettingsWindow>(true, "UnityWebSocket");
|
||||
window.minSize = window.maxSize = new Vector2(600, 310);
|
||||
window.Show();
|
||||
window.BeginCheck();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
DrawLogo();
|
||||
DrawVersion();
|
||||
DrawSeparator(80);
|
||||
DrawSeparator(186);
|
||||
DrawHelper();
|
||||
DrawFooter();
|
||||
}
|
||||
|
||||
Texture2D logoTex = null;
|
||||
private void DrawLogo()
|
||||
{
|
||||
if (logoTex == null)
|
||||
{
|
||||
logoTex = new Texture2D(66, 66);
|
||||
logoTex.LoadImage(Convert.FromBase64String(LOGO_BASE64.VALUE));
|
||||
for (int i = 0; i < 66; i++) for (int j = 0; j < 15; j++) logoTex.SetPixel(i, j, Color.clear);
|
||||
logoTex.Apply();
|
||||
}
|
||||
|
||||
var logoPos = new Rect(10, 10, 66, 66);
|
||||
GUI.DrawTexture(logoPos, logoTex);
|
||||
var title = "<color=#3A9AD8><b>UnityWebSocket</b></color>";
|
||||
var titlePos = new Rect(80, 20, 500, 50);
|
||||
GUI.Label(titlePos, title, TextStyle(24));
|
||||
}
|
||||
|
||||
private void DrawSeparator(int y)
|
||||
{
|
||||
EditorGUI.DrawRect(new Rect(10, y, 580, 1), Color.white * 0.5f);
|
||||
}
|
||||
|
||||
private GUIStyle TextStyle(int fontSize = 10, TextAnchor alignment = TextAnchor.UpperLeft, float alpha = 0.85f)
|
||||
{
|
||||
var style = new GUIStyle();
|
||||
style.fontSize = fontSize;
|
||||
style.normal.textColor = (EditorGUIUtility.isProSkin ? Color.white : Color.black) * alpha;
|
||||
style.alignment = alignment;
|
||||
style.richText = true;
|
||||
return style;
|
||||
}
|
||||
|
||||
private void DrawVersion()
|
||||
{
|
||||
GUI.Label(new Rect(440, 10, 150, 10), "Current Version: " + Settings.VERSION, TextStyle(alignment: TextAnchor.MiddleLeft));
|
||||
if (string.IsNullOrEmpty(latestVersion))
|
||||
{
|
||||
GUI.Label(new Rect(440, 30, 150, 10), "Checking for Updates...", TextStyle(alignment: TextAnchor.MiddleLeft));
|
||||
}
|
||||
else if (latestVersion == "unknown")
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.Label(new Rect(440, 30, 150, 10), "Latest Version: " + latestVersion, TextStyle(alignment: TextAnchor.MiddleLeft));
|
||||
if (Settings.VERSION == latestVersion)
|
||||
{
|
||||
if (GUI.Button(new Rect(440, 50, 150, 18), "Check Update"))
|
||||
{
|
||||
latestVersion = "";
|
||||
changeLog = "";
|
||||
BeginCheck();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GUI.Button(new Rect(440, 50, 150, 18), "Update to | " + latestVersion))
|
||||
{
|
||||
ShowUpdateDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowUpdateDialog()
|
||||
{
|
||||
var isOK = EditorUtility.DisplayDialog("UnityWebSocket",
|
||||
"Update UnityWebSocket now?\n" + changeLog,
|
||||
"Update Now", "Cancel");
|
||||
|
||||
if (isOK)
|
||||
{
|
||||
UpdateVersion();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVersion()
|
||||
{
|
||||
Application.OpenURL(Settings.GITHUB + "/releases");
|
||||
}
|
||||
|
||||
private void DrawHelper()
|
||||
{
|
||||
GUI.Label(new Rect(330, 200, 100, 18), "GitHub:", TextStyle(10, TextAnchor.MiddleRight));
|
||||
if (GUI.Button(new Rect(440, 200, 150, 18), "UnityWebSocket"))
|
||||
{
|
||||
Application.OpenURL(Settings.GITHUB);
|
||||
}
|
||||
|
||||
GUI.Label(new Rect(330, 225, 100, 18), "Report:", TextStyle(10, TextAnchor.MiddleRight));
|
||||
if (GUI.Button(new Rect(440, 225, 150, 18), "Report an Issue"))
|
||||
{
|
||||
Application.OpenURL(Settings.GITHUB + "/issues/new");
|
||||
}
|
||||
|
||||
GUI.Label(new Rect(330, 250, 100, 18), "Email:", TextStyle(10, TextAnchor.MiddleRight));
|
||||
if (GUI.Button(new Rect(440, 250, 150, 18), Settings.EMAIL))
|
||||
{
|
||||
var uri = new Uri(string.Format("mailto:{0}?subject={1}", Settings.EMAIL, "UnityWebSocket Feedback"));
|
||||
Application.OpenURL(uri.AbsoluteUri);
|
||||
}
|
||||
|
||||
GUI.Label(new Rect(330, 275, 100, 18), "QQ群:", TextStyle(10, TextAnchor.MiddleRight));
|
||||
if (GUI.Button(new Rect(440, 275, 150, 18), Settings.QQ_GROUP))
|
||||
{
|
||||
Application.OpenURL(Settings.QQ_GROUP_LINK);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawFooter()
|
||||
{
|
||||
EditorGUI.DropShadowLabel(new Rect(10, 230, 400, 20), "Developed by " + Settings.AUHTOR);
|
||||
EditorGUI.DropShadowLabel(new Rect(10, 250, 400, 20), "All rights reserved");
|
||||
}
|
||||
|
||||
UnityWebRequest req;
|
||||
string changeLog = "";
|
||||
string latestVersion = "";
|
||||
void BeginCheck()
|
||||
{
|
||||
EditorApplication.update -= VersionCheckUpdate;
|
||||
EditorApplication.update += VersionCheckUpdate;
|
||||
|
||||
req = UnityWebRequest.Get(Settings.GITHUB + "/releases/latest");
|
||||
req.SendWebRequest();
|
||||
}
|
||||
|
||||
private void VersionCheckUpdate()
|
||||
{
|
||||
#if UNITY_2020_3_OR_NEWER
|
||||
if (req == null
|
||||
|| req.result == UnityWebRequest.Result.ConnectionError
|
||||
|| req.result == UnityWebRequest.Result.DataProcessingError
|
||||
|| req.result == UnityWebRequest.Result.ProtocolError)
|
||||
#elif UNITY_2018_1_OR_NEWER
|
||||
if (req == null || req.isNetworkError || req.isHttpError)
|
||||
#else
|
||||
if (req == null || req.isError)
|
||||
#endif
|
||||
{
|
||||
EditorApplication.update -= VersionCheckUpdate;
|
||||
latestVersion = "unknown";
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.isDone)
|
||||
{
|
||||
EditorApplication.update -= VersionCheckUpdate;
|
||||
latestVersion = req.url.Substring(req.url.LastIndexOf("/") + 1).TrimStart('v');
|
||||
|
||||
if (Settings.VERSION != latestVersion)
|
||||
{
|
||||
var text = req.downloadHandler.text;
|
||||
var st = text.IndexOf("content=\"" + latestVersion);
|
||||
st = st > 0 ? text.IndexOf("\n", st) : -1;
|
||||
var end = st > 0 ? text.IndexOf("\" />", st) : -1;
|
||||
if (st > 0 && end > st)
|
||||
{
|
||||
changeLog = text.Substring(st + 1, end - st - 1).Trim();
|
||||
changeLog = changeLog.Replace("\r", "");
|
||||
changeLog = changeLog.Replace("\n", "\n- ");
|
||||
changeLog = "\nCHANGE LOG: \n- " + changeLog + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
Repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class LOGO_BASE64
|
||||
{
|
||||
internal const string VALUE = "iVBORw0KGgoAAAANSUhEUgAAAEIAAABCCAMAAADUivDaAAAAq1BMVEUAAABKmtcvjtYzl" +
|
||||
"9szmNszl9syl9k0mNs0mNwzmNs0mNszl9szl9s0mNs0mNwzmNw0mNwyltk0mNw0mNwzl9s0mNsymNs0mNszmNwzmNwzm" +
|
||||
"NszmNs0mNwzl9w0mNwzmNw0mNs0mNs0mNwzl9wzmNs0mNwzmNs0mNwzl90zmNszmNszl9szmNsxmNszmNszmNw0mNwzm" +
|
||||
"Nw0mNs2neM4pe41mt43ouo2oOY5qfM+UHlaAAAAMnRSTlMAAwXN3sgI+/069MSCK6M/MA74h9qfFHB8STWMJ9OSdmNcI" +
|
||||
"8qya1IeF+/U0EIa57mqmFTYJe4AAAN3SURBVFjD7ZbpkppAFEa/bgVBREF2kEVGFNeZsM77P1kadURnJkr8k1Qlx1Khu" +
|
||||
"/pw7+2lwH/+YcgfMBBLG7VocwDamzH+wJBB8Qhjve2f0TdrGwjei6o4Ub/nM/APw5Z7vvSB/qrCrqbD6fBEVtigeMxks" +
|
||||
"fX9zWbj+z1jhqgSBplQ50eGo4614WXlRAzgrRhmtSfvxAn7pB0N5ObaKKZZuU5/d37IBcBgUQwqDuf7Z2gUmVAl4NGNr" +
|
||||
"/UeHxV5n39ulbaKLI86h6HilmM5M1aN126lpNhtl59yeTsp8nUMvpNC1J3bh5FtfVRk+bJrJunn5d4U4piJ/Vw9eXgsj" +
|
||||
"4ZpZaCjg9waZkIpnBWLJ44OwoNu60F2UnSaEkKv4XnAlCpm6B4F/aKMDiyGi2L8SEEAVdxNLuzmgV7nFwObEe2xQVuX+" +
|
||||
"RV1lWetga3w+cN1sXgvm4cJH8OEgZC1DPKhfF/BIymmQrMjq/x65FUeEkDup8GxoexZmznHCvANtXU/CAq13yimhQGtm" +
|
||||
"H4VCPnBBL1fTKo3CqEcvq7Lb/OwHxWTYlyw+JmjKoVvDLVOQB4pVsM8K8smgvLCxZDlIijwyOEc+nr/msMwK0+GQWGBd" +
|
||||
"tmhjv8icTds1s2ammaFh04QLLe69NK7guP6mTDMaw3o6nAX/Z7EXUskPSvWEWg4srVlp5NTDXv9Lce9HGN5eeG4nj5Yz" +
|
||||
"ACteU2wQLo4MBtJfd1nw5nG1/s9zwUQ6pykL1TQjqdeuvQW0naz2XKLYL4Cwzr4vj+OQdD96CSp7Lrynp4aeFF0xdm5q" +
|
||||
"6OFtFfPv7URxpWJNjd/N+3+I9+1klMav12Qtgbt9R2JaIopjkzaPtOFq4KxUpqfUMSFnQrySWjLoQzRZS4HMH84ME1ej" +
|
||||
"S1YJpQZ3B+sR1uCQJSBdGdCk1eAEgORR88KK05W8dh2MA+A/SKCYu3mCJ0Ek7HBx4HHeuwYy5G3x8hSMTJcOMFbinCsn" +
|
||||
"hO1V1aszGULvA0g4UFsb4VA0hAFcyo6cgLsAoT7uUtGAH5wQKQle0wuLyxLTaNyJEYwxw4wSljLK1TP8CAaOyhBMMEsj" +
|
||||
"OBoXgo7VGElFkSWL+vef1RF2YNXeRWYzQBTpkhC8KaZHhuIogArkQLKClBZjU26B2IZgGz+cpZkHl8g3fYUaW/YP2kb2" +
|
||||
"M/V97JY/vZN859n+QmO7XtC9Bf2jAAAAABJRU5ErkJggg==";
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/WSocket/SettingsWindow.cs.meta
vendored
Normal file
11
Assets/Scripts/ThirdParty/Fantasy.Unity/Editor/Runtime/WSocket/SettingsWindow.cs.meta
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c797632152a42a04e944c54c3bdacad8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user