com.alicizax.unity.framework/Editor/UI/Helper/IUIGeneratorRuleHelper.cs
2025-11-11 10:57:35 +08:00

173 lines
7.1 KiB
C#

using System;
using System.IO;
using System.Text;
using AlicizaX.UI.Runtime;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
namespace AlicizaX.UI.Editor
{
public interface IUIGeneratorRuleHelper
{
string GetPrivateComponentByNameRule(string regexName, string componetName, EBindType bindType);
string GetPublicComponentByNameRule(string variableName);
string GetClassGenerateName(GameObject targetObject, UIScriptGenerateData scriptGenerateData);
string GetUIResourceSavePath(GameObject targetObject, UIScriptGenerateData scriptGenerateData);
void WriteUIScriptContent(string className, string scriptContent, UIScriptGenerateData scriptGenerateData);
bool CheckCanGenerate(GameObject targetObject, UIScriptGenerateData scriptGenerateData);
}
public class DefaultIuiGeneratorRuleHelper : IUIGeneratorRuleHelper
{
public string GetPrivateComponentByNameRule(string regexName, string componentName, EBindType bindType)
{
string endPrefix = bindType == EBindType.ListCom ? "List" : string.Empty;
var common = UIGenerateConfiguration.Instance.UIGenerateCommonData;
int endNameIndex = componentName.IndexOf(common.ComCheckEndName, StringComparison.Ordinal);
string componentSuffix = endNameIndex >= 0 ? componentName.Substring(endNameIndex + 1) : componentName;
return $"m{regexName}{componentSuffix}{endPrefix}";
}
public string GetPublicComponentByNameRule(string variableName)
{
if (string.IsNullOrEmpty(variableName)) return variableName;
if (variableName.Length > 1)
return variableName.Substring(1);
return variableName;
}
public string GetClassGenerateName(GameObject targetObject, UIScriptGenerateData scriptGenerateData)
{
var config = UIGenerateConfiguration.Instance.UIGenerateCommonData;
string prefix = config.GeneratePrefix ?? "ui";
return $"{prefix}_{targetObject.name}";
}
public string GetUIResourceSavePath(GameObject targetObject, UIScriptGenerateData scriptGenerateData)
{
if (targetObject == null)
return $"\"{nameof(targetObject)}\"";
string defaultPath = targetObject.name;
string assetPath = UIGenerateQuick.GetPrefabAssetPath(targetObject);
if (string.IsNullOrEmpty(assetPath) || !assetPath.StartsWith("Assets/", StringComparison.Ordinal))
return defaultPath;
assetPath = assetPath.Replace('\\', '/');
switch (scriptGenerateData.LoadType)
{
case EUIResLoadType.Resources:
{
string resourcesRoot = scriptGenerateData.UIPrefabRootPath; // 例如 "Assets/Resources/UI"
string relPath = GetResourcesRelativePath(assetPath, resourcesRoot);
if (relPath == null)
{
Debug.LogWarning($"[UI生成] 资源 {assetPath} 不在配置的 Resources 根目录下: {resourcesRoot}");
return defaultPath;
}
return relPath;
}
case EUIResLoadType.AssetBundle:
{
string bundleRoot = scriptGenerateData.UIPrefabRootPath; // 例如 "Assets/Bundles/UI"
try
{
var defaultPackage = YooAsset.Editor.AssetBundleCollectorSettingData.Setting.GetPackage("DefaultPackage");
if (defaultPackage != null && defaultPackage.EnableAddressable)
return defaultPath;
}
catch
{
}
if (!assetPath.StartsWith(bundleRoot, StringComparison.OrdinalIgnoreCase))
{
Debug.LogWarning($"[UI生成] 资源 {assetPath} 不在配置的 AssetBundle 根目录下: {bundleRoot}");
return defaultPath;
}
return Path.ChangeExtension(assetPath, null);
}
default:
return defaultPath;
}
}
private string GetResourcesRelativePath(string assetPath, string resourcesRoot)
{
if (string.IsNullOrEmpty(assetPath) || string.IsNullOrEmpty(resourcesRoot)) return null;
assetPath = assetPath.Replace('\\', '/');
resourcesRoot = resourcesRoot.Replace('\\', '/');
if (!assetPath.StartsWith(resourcesRoot, StringComparison.OrdinalIgnoreCase))
return null;
string relPath = assetPath.Substring(resourcesRoot.Length).TrimStart('/');
return Path.ChangeExtension(relPath, null);
}
public void WriteUIScriptContent(string className, string scriptContent, UIScriptGenerateData scriptGenerateData)
{
if (string.IsNullOrEmpty(className)) throw new ArgumentNullException(nameof(className));
if (scriptContent == null) throw new ArgumentNullException(nameof(scriptContent));
if (scriptGenerateData == null) throw new ArgumentNullException(nameof(scriptGenerateData));
string scriptFolderPath = scriptGenerateData.GenerateHolderCodePath;
string scriptFilePath = Path.Combine(scriptFolderPath, className + ".cs");
if (!Directory.Exists(scriptFolderPath))
{
Directory.CreateDirectory(scriptFolderPath);
}
if (File.Exists(scriptFilePath))
{
string oldText = File.ReadAllText(scriptFilePath, Encoding.UTF8);
if (oldText.Equals(scriptContent, StringComparison.Ordinal))
{
// 文件未变更:标记并等待脚本 reload 去做附加
EditorPrefs.SetString("Generate", className);
UIScriptGeneratorHelper.CheckHasAttach();
return;
}
}
File.WriteAllText(scriptFilePath, scriptContent, Encoding.UTF8);
EditorPrefs.SetString("Generate", className);
AssetDatabase.Refresh();
}
public bool CheckCanGenerate(GameObject targetObject, UIScriptGenerateData scriptGenerateData)
{
if (targetObject == null || scriptGenerateData == null) return false;
string assetPath = UIGenerateQuick.GetPrefabAssetPath(targetObject);
if (string.IsNullOrEmpty(assetPath) || !assetPath.StartsWith("Assets/", StringComparison.Ordinal))
return false; // 不在 Assets 下
assetPath = assetPath.Replace('\\', '/');
bool result = assetPath.StartsWith(scriptGenerateData.UIPrefabRootPath, StringComparison.OrdinalIgnoreCase);
if (!result)
{
Debug.LogWarning($"UI存储位置与配置生成规则不符合 请检查对应配置的UIPrefabRootPath\n[AssetPath]{assetPath}\n[ConfigPath]{scriptGenerateData.UIPrefabRootPath}");
}
return result;
}
}
}