minigame-tuanjie-transform-sdk/Editor/Playable/WXPlayableEditorSettingHelper.cs

363 lines
12 KiB
C#
Raw Normal View History

2025-06-19 15:41:14 +08:00
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace WeChatWASM
{
[InitializeOnLoad]
public class WXPlayableSettingsHelperInterface
{
public static WXPlayableSettingsHelper helper = new WXPlayableSettingsHelper();
}
public class WXPlayableSettingsHelper
{
public static string projectRootPath;
private static WXPlayableEditorScriptObject config;
private static bool m_EnablePerfTool = false;
private static string _dstCache;
public static bool UseIL2CPP
{
get
{
#if TUANJIE_2022_3_OR_NEWER
return PlayerSettings.GetScriptingBackend(BuildTargetGroup.WeixinMiniGame) == ScriptingImplementation.IL2CPP;
#else
return true;
#endif
}
}
public WXPlayableSettingsHelper()
{
projectRootPath = System.IO.Path.GetFullPath(Application.dataPath + "/../");
_dstCache = "";
}
public void OnFocus()
{
loadData();
}
public void OnLostFocus()
{
saveData();
}
public void OnDisable()
{
EditorUtility.SetDirty(config);
}
private Vector2 scrollRoot;
private bool foldBaseInfo = true;
private bool foldDebugOptions = true;
public void OnSettingsGUI(EditorWindow window)
{
scrollRoot = EditorGUILayout.BeginScrollView(scrollRoot);
GUIStyle linkStyle = new GUIStyle(GUI.skin.label);
linkStyle.normal.textColor = Color.yellow;
linkStyle.hover.textColor = Color.yellow;
linkStyle.stretchWidth = false;
linkStyle.alignment = TextAnchor.UpperLeft;
linkStyle.wordWrap = true;
foldBaseInfo = EditorGUILayout.Foldout(foldBaseInfo, "基本信息");
if (foldBaseInfo)
{
EditorGUILayout.BeginVertical("frameBox", GUILayout.ExpandWidth(true));
this.formInput("appid", "小游戏试玩AppID");
this.formInput("projectName", "小游戏试玩项目名");
this.formIntPopup("orientation", "游戏方向", new[] { "Portrait", "Landscape" }, new[] { 0, 1, 2, 3 });
this.formInput("memorySize", "UnityHeap预留内存(?)", "单位MB预分配内存值超休闲游戏256/中轻度496/重度游戏768需预估游戏最大UnityHeap值以防止内存自动扩容带来的峰值尖刺。预估方法请查看GIT文档《优化Unity WebGL的内存》");
GUILayout.BeginHorizontal();
string targetDst = "dst";
if (!formInputData.ContainsKey(targetDst))
{
formInputData[targetDst] = "";
}
EditorGUILayout.LabelField(string.Empty, GUILayout.Width(10));
GUILayout.Label(new GUIContent("导出路径(?)", "支持输入相对于项目根目录的相对路径wxbuild"), GUILayout.Width(140));
formInputData[targetDst] = GUILayout.TextField(formInputData[targetDst], GUILayout.MaxWidth(EditorGUIUtility.currentViewWidth - 270));
if (GUILayout.Button(new GUIContent("打开"), GUILayout.Width(40)))
{
if (!formInputData[targetDst].Trim().Equals(string.Empty))
{
EditorUtility.RevealInFinder(GetAbsolutePath(formInputData[targetDst]));
}
GUIUtility.ExitGUI();
}
if (GUILayout.Button(new GUIContent("选择"), GUILayout.Width(40)))
{
var dstPath = EditorUtility.SaveFolderPanel("选择你的游戏导出目录", string.Empty, string.Empty);
if (dstPath != string.Empty)
{
formInputData[targetDst] = dstPath;
this.saveData();
}
GUIUtility.ExitGUI();
}
GUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
}
foldDebugOptions = EditorGUILayout.Foldout(foldDebugOptions, "调试编译选项");
if (foldDebugOptions)
{
EditorGUILayout.BeginVertical("frameBox", GUILayout.ExpandWidth(true));
this.formCheckbox("developBuild", "Development Build", "", false, null, OnDevelopmentBuildToggleChanged);
this.formCheckbox("il2CppOptimizeSize", "Il2Cpp Optimize Size(?)", "对应于Il2CppCodeGeneration选项勾选时使用OptimizeSize(默认推荐)生成代码小15%左右取消勾选则使用OptimizeSpeed。游戏中大量泛型集合的高频访问建议OptimizeSpeed在使用HybridCLR等第三方组件时只能用OptimizeSpeed。(Dotnet Runtime模式下该选项无效)", !UseIL2CPP);
this.formCheckbox("profilingFuncs", "Profiling Funcs");
this.formCheckbox("webgl2", "WebGL2.0(beta)");
EditorGUILayout.EndVertical();
}
EditorGUILayout.EndScrollView();
}
public void OnBuildButtonGUI(EditorWindow window)
{
GUIStyle linkStyle = new GUIStyle(GUI.skin.label);
linkStyle.normal.textColor = Color.yellow;
linkStyle.hover.textColor = Color.yellow;
linkStyle.stretchWidth = false;
linkStyle.alignment = TextAnchor.UpperLeft;
linkStyle.wordWrap = true;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(string.Empty, GUILayout.MinWidth(10));
if (GUILayout.Button(new GUIContent("生成并转换"), GUILayout.Width(100), GUILayout.Height(25)))
{
this.saveData();
if (WXPlayableConvertCore.DoExport() == WXConvertCore.WXExportError.SUCCEED)
{
window.ShowNotification(new GUIContent("转换完成"));
}
GUIUtility.ExitGUI();
}
EditorGUILayout.EndHorizontal();
}
private void OnDevelopmentBuildToggleChanged(bool InNewValue)
{
// 针对non-dev build取消性能分析工具的集成
if (!InNewValue)
{
this.setData("enablePerfAnalysis", false);
}
}
private string SDKFilePath;
private void loadData()
{
SDKFilePath = Path.Combine(UnityUtil.GetWxSDKRootPath(), "Runtime", "wechat-playable-default", "unity-sdk", "index.js");
config = UnityUtil.GetPlayableEditorConf();
_dstCache = config.ProjectConf.DST;
this.setData("projectName", config.ProjectConf.projectName);
this.setData("appid", config.ProjectConf.Appid);
this.setData("orientation", (int)config.ProjectConf.Orientation);
this.setData("dst", _dstCache);
this.setData("developBuild", config.CompileOptions.DevelopBuild);
this.setData("il2CppOptimizeSize", config.CompileOptions.Il2CppOptimizeSize);
this.setData("profilingFuncs", config.CompileOptions.profilingFuncs);
this.setData("webgl2", config.CompileOptions.Webgl2);
this.setData("customNodePath", config.CompileOptions.CustomNodePath);
this.setData("memorySize", config.ProjectConf.MemorySize.ToString());
}
private void saveData()
{
config.ProjectConf.projectName = this.getDataInput("projectName");
config.ProjectConf.Appid = this.getDataInput("appid");
config.ProjectConf.Orientation = (WXScreenOritation)this.getDataPop("orientation");
_dstCache = this.getDataInput("dst");
config.ProjectConf.DST = GetAbsolutePath(_dstCache);
config.CompileOptions.DevelopBuild = this.getDataCheckbox("developBuild");
config.CompileOptions.Il2CppOptimizeSize = this.getDataCheckbox("il2CppOptimizeSize");
config.CompileOptions.profilingFuncs = this.getDataCheckbox("profilingFuncs");
config.CompileOptions.CustomNodePath = this.getDataInput("customNodePath");
config.CompileOptions.Webgl2 = this.getDataCheckbox("webgl2");
config.ProjectConf.MemorySize = int.Parse(this.getDataInput("memorySize"));
}
private Dictionary<string, string> formInputData = new Dictionary<string, string>();
private Dictionary<string, int> formIntPopupData = new Dictionary<string, int>();
private Dictionary<string, bool> formCheckboxData = new Dictionary<string, bool>();
private string getDataInput(string target)
{
if (this.formInputData.ContainsKey(target))
return this.formInputData[target];
return "";
}
private int getDataPop(string target)
{
if (this.formIntPopupData.ContainsKey(target))
return this.formIntPopupData[target];
return 0;
}
private bool getDataCheckbox(string target)
{
if (this.formCheckboxData.ContainsKey(target))
return this.formCheckboxData[target];
return false;
}
private void formCheckbox(string target, string label, string help = null, bool disable = false, Action<bool> setting = null, Action<bool> onValueChanged = null)
{
if (!formCheckboxData.ContainsKey(target))
{
formCheckboxData[target] = false;
}
GUILayout.BeginHorizontal();
EditorGUILayout.LabelField(string.Empty, GUILayout.Width(10));
if (help == null)
{
GUILayout.Label(label, GUILayout.Width(140));
}
else
{
GUILayout.Label(new GUIContent(label, help), GUILayout.Width(140));
}
EditorGUI.BeginDisabledGroup(disable);
// Toggle the checkbox value based on the disable condition
bool newValue = EditorGUILayout.Toggle(disable ? false : formCheckboxData[target]);
// Update the checkbox data if the value has changed and invoke the onValueChanged action
if (newValue != formCheckboxData[target])
{
formCheckboxData[target] = newValue;
onValueChanged?.Invoke(newValue);
}
if (setting != null)
{
EditorGUILayout.LabelField("", GUILayout.Width(10));
// 配置按钮
if (GUILayout.Button(new GUIContent("设置"), GUILayout.Width(40), GUILayout.Height(18)))
{
setting?.Invoke(true);
}
EditorGUILayout.LabelField("", GUILayout.MinWidth(10));
}
EditorGUI.EndDisabledGroup();
if (setting == null)
EditorGUILayout.LabelField(string.Empty);
GUILayout.EndHorizontal();
}
private void setData(string target, string value)
{
if (formInputData.ContainsKey(target))
{
formInputData[target] = value;
}
else
{
formInputData.Add(target, value);
}
}
private void setData(string target, bool value)
{
if (formCheckboxData.ContainsKey(target))
{
formCheckboxData[target] = value;
}
else
{
formCheckboxData.Add(target, value);
}
}
private void setData(string target, int value)
{
if (formIntPopupData.ContainsKey(target))
{
formIntPopupData[target] = value;
}
else
{
formIntPopupData.Add(target, value);
}
}
private void formInput(string target, string label, string help = null)
{
if (!formInputData.ContainsKey(target))
{
formInputData[target] = "";
}
GUILayout.BeginHorizontal();
EditorGUILayout.LabelField(string.Empty, GUILayout.Width(10));
if (help == null)
{
GUILayout.Label(label, GUILayout.Width(140));
}
else
{
GUILayout.Label(new GUIContent(label, help), GUILayout.Width(140));
}
formInputData[target] = GUILayout.TextField(formInputData[target], GUILayout.MaxWidth(EditorGUIUtility.currentViewWidth - 195));
GUILayout.EndHorizontal();
}
private void formIntPopup(string target, string label, string[] options, int[] values)
{
if (!formIntPopupData.ContainsKey(target))
{
formIntPopupData[target] = 0;
}
GUILayout.BeginHorizontal();
EditorGUILayout.LabelField(string.Empty, GUILayout.Width(10));
GUILayout.Label(label, GUILayout.Width(140));
formIntPopupData[target] = EditorGUILayout.IntPopup(formIntPopupData[target], options, values, GUILayout.MaxWidth(EditorGUIUtility.currentViewWidth - 195));
GUILayout.EndHorizontal();
}
public static bool IsAbsolutePath(string path)
{
// 检查是否为空或空白
if (string.IsNullOrWhiteSpace(path))
{
return false;
}
// 在 Windows 上,检查驱动器字母或网络路径
if (Application.platform == RuntimePlatform.WindowsEditor && Path.IsPathRooted(path))
{
return true;
}
// 在 Unix/Linux 和 macOS 上,检查是否以 '/' 开头
if (Application.platform == RuntimePlatform.OSXEditor && path.StartsWith("/"))
{
return true;
}
return false; // 否则为相对路径
}
public static string GetAbsolutePath(string path)
{
if (IsAbsolutePath(path))
{
return path;
}
return Path.Combine(projectRootPath, path);
}
}
}