框架结构优化解耦
This commit is contained in:
parent
af4b77e2c3
commit
784016415e
@ -5,7 +5,10 @@
|
||||
"GUID:6546d7765b4165b40850b3667f981c26",
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||
"GUID:760f1778adc613f49a4394fb41ff0bbc",
|
||||
"GUID:75b6f2078d190f14dbda4a5b747d709c"
|
||||
"GUID:75b6f2078d190f14dbda4a5b747d709c",
|
||||
"GUID:1619e00706139ce488ff80c0daeea8e7",
|
||||
"GUID:fb064c8bf96bac94e90d2f39090daa94",
|
||||
"GUID:acfef7cabed3b0a42b25edb1cd4fa259"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
|
||||
@ -1,19 +1,126 @@
|
||||
#if TEXTMESHPRO_SUPPORT
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AlicizaX.Localization;
|
||||
using AlicizaX.Localization.Editor;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
|
||||
namespace UnityEngine.UI
|
||||
{
|
||||
internal readonly struct TableSelectionData
|
||||
{
|
||||
public readonly int Id;
|
||||
public readonly string CombineKey; // SectionName/Key → 菜单层级
|
||||
public readonly string CombineValue; // SectionName.Key → 存储用
|
||||
|
||||
public TableSelectionData(int id, string combineKey, string combineValue)
|
||||
{
|
||||
Id = id;
|
||||
CombineKey = combineKey;
|
||||
CombineValue = combineValue;
|
||||
}
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(UXTextMeshPro), true)]
|
||||
[CanEditMultipleObjects]
|
||||
internal class UXTextMeshProEditor : TMPro.EditorUtilities.TMP_EditorPanelUI
|
||||
{
|
||||
private SerializedProperty text;
|
||||
private SerializedProperty localizationID;
|
||||
private SerializedProperty m_localizationKey;
|
||||
|
||||
private List<GameLocaizationTable> allTables = new();
|
||||
private Dictionary<int, TableSelectionData> allTableNames = new();
|
||||
private Dictionary<string, string> previewLabelDic = new();
|
||||
private List<string> allSelection = new();
|
||||
private int selectedSelectionIndex = 0;
|
||||
|
||||
public override VisualElement CreateInspectorGUI()
|
||||
{
|
||||
RefreshAllTables();
|
||||
return base.CreateInspectorGUI();
|
||||
}
|
||||
|
||||
private void RefreshAllTables()
|
||||
{
|
||||
allTables.Clear();
|
||||
string[] guids = AssetDatabase.FindAssets("t:GameLocaizationTable");
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
GameLocaizationTable table = AssetDatabase.LoadAssetAtPath<GameLocaizationTable>(assetPath);
|
||||
if (table != null)
|
||||
{
|
||||
allTables.Add(table);
|
||||
}
|
||||
}
|
||||
|
||||
InitAllTables();
|
||||
}
|
||||
|
||||
private void InitAllTables()
|
||||
{
|
||||
allTableNames.Clear();
|
||||
allSelection.Clear();
|
||||
previewLabelDic.Clear();
|
||||
allSelection.Add("None");
|
||||
allTableNames.TryAdd(0, new TableSelectionData(0, "None", string.Empty));
|
||||
|
||||
var localizationLanguage = allTables.Select(e => e.Languages.Find(t => t.LanguageName == LocalizationConfiguration.Instance.GenerateScriptCodeFirstConfig)).ToList();
|
||||
foreach (var localization in localizationLanguage)
|
||||
{
|
||||
foreach (var item in localization.Strings)
|
||||
{
|
||||
previewLabelDic.TryAdd(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var table in allTables)
|
||||
{
|
||||
foreach (var sheet in table.TableSheet)
|
||||
{
|
||||
foreach (var selection in sheet.SectionSheet)
|
||||
{
|
||||
string combineKey = $"{table.name}/{sheet.SectionName}/{selection.Key}";
|
||||
string combineValue = $"{sheet.SectionName}.{selection.Key}";
|
||||
int id = selection.Id;
|
||||
allTableNames.TryAdd(id, new TableSelectionData(id, combineKey, combineValue));
|
||||
allSelection.Add(combineKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected string GetPreviewLabel()
|
||||
{
|
||||
return previewLabelDic.TryGetValue(m_localizationKey.stringValue, out var label)
|
||||
? label
|
||||
: "None";
|
||||
}
|
||||
|
||||
|
||||
protected void FindSelectSelection()
|
||||
{
|
||||
selectedSelectionIndex = 0;
|
||||
if (allTableNames.TryGetValue(localizationID.intValue, out TableSelectionData data))
|
||||
{
|
||||
int idx = allSelection.FindIndex(t => t == data.CombineKey);
|
||||
if (idx >= 0)
|
||||
selectedSelectionIndex = idx;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnEnable()
|
||||
{
|
||||
text = serializedObject.FindProperty("m_text");
|
||||
localizationID = serializedObject.FindProperty("m_localizationID");
|
||||
m_localizationKey = serializedObject.FindProperty("m_localizationKey");
|
||||
|
||||
RefreshAllTables();
|
||||
FindSelectSelection();
|
||||
|
||||
base.OnEnable();
|
||||
}
|
||||
|
||||
@ -21,13 +128,125 @@ namespace UnityEngine.UI
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
// m_localizationKey 只读
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.PropertyField(m_localizationKey);
|
||||
EditorGUILayout.LabelField("Text", GetPreviewLabel());
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
EditorGUILayout.PropertyField(localizationID);
|
||||
// 检查是否找不到对应 ID 的 key
|
||||
if (localizationID.intValue > 0 && !allTableNames.ContainsKey(localizationID.intValue))
|
||||
{
|
||||
EditorGUILayout.HelpBox($"已选择的多语言 Key (ID={localizationID.intValue}) 已被删除,但仍然保留该 ID。", MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// 下拉按钮
|
||||
if (GUILayout.Button(allSelection[selectedSelectionIndex], EditorStyles.popup))
|
||||
{
|
||||
var mousePos = GUIUtility.GUIToScreenPoint(Event.current.mousePosition);
|
||||
SearchWindow.Open(
|
||||
new SearchWindowContext(mousePos),
|
||||
ScriptableObject.CreateInstance<LocalizationSearchProvider>().Init(allSelection, ApplySelection)
|
||||
);
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
base.OnInspectorGUI();
|
||||
}
|
||||
|
||||
private void ApplySelection(string selectedKey)
|
||||
{
|
||||
if (selectedKey == "None")
|
||||
{
|
||||
localizationID.intValue = 0;
|
||||
m_localizationKey.stringValue = string.Empty;
|
||||
selectedSelectionIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var kvp in allTableNames)
|
||||
{
|
||||
if (kvp.Value.CombineKey == selectedKey)
|
||||
{
|
||||
localizationID.intValue = kvp.Value.Id;
|
||||
m_localizationKey.stringValue = kvp.Value.CombineValue;
|
||||
selectedSelectionIndex = allSelection.IndexOf(kvp.Value.CombineKey);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
internal class LocalizationSearchProvider : ScriptableObject, ISearchWindowProvider
|
||||
{
|
||||
private List<string> options;
|
||||
private System.Action<string> onSelect;
|
||||
|
||||
public LocalizationSearchProvider Init(List<string> options, System.Action<string> onSelect)
|
||||
{
|
||||
this.options = options;
|
||||
this.onSelect = onSelect;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context)
|
||||
{
|
||||
var tree = new List<SearchTreeEntry>
|
||||
{
|
||||
new SearchTreeGroupEntry(new GUIContent("Localization Keys"), 0)
|
||||
};
|
||||
|
||||
foreach (var option in options)
|
||||
{
|
||||
if (option == "None")
|
||||
{
|
||||
tree.Add(new SearchTreeEntry(new GUIContent("None")) { level = 1, userData = "None" });
|
||||
}
|
||||
else
|
||||
{
|
||||
// `/` 自动分层
|
||||
string[] parts = option.Split('/');
|
||||
if (parts.Length == 1)
|
||||
{
|
||||
tree.Add(new SearchTreeEntry(new GUIContent(parts[0])) { level = 1, userData = option });
|
||||
}
|
||||
else
|
||||
{
|
||||
// 前面的部分作为 group
|
||||
for (int i = 0; i < parts.Length - 1; i++)
|
||||
{
|
||||
// 确保 group 唯一
|
||||
string groupName = string.Join("/", parts, 0, i + 1);
|
||||
if (!tree.Exists(e => e.content.text == parts[i] && e.level == i + 1))
|
||||
{
|
||||
tree.Add(new SearchTreeGroupEntry(new GUIContent(parts[i])) { level = i + 1 });
|
||||
}
|
||||
}
|
||||
|
||||
// 最后部分作为 Entry
|
||||
tree.Add(new SearchTreeEntry(new GUIContent(parts[^1])) { level = parts.Length, userData = option });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
public bool OnSelectEntry(SearchTreeEntry searchTreeEntry, SearchWindowContext context)
|
||||
{
|
||||
if (searchTreeEntry.userData is string key)
|
||||
{
|
||||
onSelect?.Invoke(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4,7 +4,9 @@
|
||||
"references": [
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||
"GUID:80ecb87cae9c44d19824e70ea7229748",
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c"
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c",
|
||||
"GUID:1619e00706139ce488ff80c0daeea8e7",
|
||||
"GUID:189d55e03d78888459720d730f4d2424"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
3
Runtime/UXComponent/Button.meta
Normal file
3
Runtime/UXComponent/Button.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e8bd5b405994da288d5a14f65ceb81b
|
||||
timeCreated: 1758683565
|
||||
3
Runtime/UXComponent/Group.meta
Normal file
3
Runtime/UXComponent/Group.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4474c46008f24d2ab4817687760f7c45
|
||||
timeCreated: 1758683576
|
||||
8
Runtime/UXComponent/Hotkey.meta
Normal file
8
Runtime/UXComponent/Hotkey.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24fbe05aa8721e14db91f27f5f5cfe6a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
66
Runtime/UXComponent/Hotkey/HotkeyBindComponent.cs
Normal file
66
Runtime/UXComponent/Hotkey/HotkeyBindComponent.cs
Normal file
@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using AlicizaX.UI.Runtime;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX.UI.Extension.UXComponent.Hotkey
|
||||
{
|
||||
public class HotkeyBindComponent : MonoBehaviour
|
||||
{
|
||||
private UIHolderObjectBase _holderObjectBase;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_holderObjectBase = GetComponent<UIHolderObjectBase>();
|
||||
_holderObjectBase.OnWindowShowEvent += BindHotKeys;
|
||||
_holderObjectBase.OnWindowClosedEvent += UnBindHotKeys;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_holderObjectBase.OnWindowShowEvent -= BindHotKeys;
|
||||
_holderObjectBase.OnWindowClosedEvent -= UnBindHotKeys;
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
[InlineButton("SetHotKeyButtons")]
|
||||
#endif
|
||||
[SerializeField]
|
||||
[HideLabel]
|
||||
private UXButton[] hotButtons;
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void SetHotKeyButtons()
|
||||
{
|
||||
var btns = transform.GetComponentsInChildren<UXButton>(true);
|
||||
var hotBtnList = new List<UXButton>();
|
||||
for (int i = 0; i < btns.Length; i++)
|
||||
{
|
||||
if (btns[i].HasHotKeyRefrenced())
|
||||
{
|
||||
hotBtnList.Add(btns[i]);
|
||||
}
|
||||
}
|
||||
|
||||
hotButtons = hotBtnList.ToArray();
|
||||
}
|
||||
#endif
|
||||
|
||||
internal void BindHotKeys()
|
||||
{
|
||||
for (int i = 0; i < hotButtons.Length; i++)
|
||||
{
|
||||
hotButtons[i].BindHotKey();
|
||||
}
|
||||
}
|
||||
|
||||
internal void UnBindHotKeys()
|
||||
{
|
||||
for (int i = 0; i < hotButtons.Length; i++)
|
||||
{
|
||||
hotButtons[i].UnBindHotKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/UXComponent/Hotkey/HotkeyBindComponent.cs.meta
Normal file
3
Runtime/UXComponent/Hotkey/HotkeyBindComponent.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdcda7a93f3c4639a0cb68dd00509bb1
|
||||
timeCreated: 1758683821
|
||||
3
Runtime/UXComponent/Image.meta
Normal file
3
Runtime/UXComponent/Image.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d4b70cfbd2d7436085d694af49f29b79
|
||||
timeCreated: 1758683583
|
||||
@ -6,7 +6,8 @@ namespace UnityEngine.UI
|
||||
{
|
||||
public class UXTextMeshPro : TextMeshProUGUI
|
||||
{
|
||||
[SerializeField] private string m_localizationID = "";
|
||||
[SerializeField] private int m_localizationID;
|
||||
[SerializeField] private string m_localizationKey = "";
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
@ -17,9 +18,9 @@ namespace UnityEngine.UI
|
||||
|
||||
protected void ChangeLanguage()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(m_localizationID) && !"None".Equals(m_localizationID) && UXComponentExtensionsHelper.LocalizationHelper != null)
|
||||
if (!string.IsNullOrEmpty(m_localizationKey) && !"None".Equals(m_localizationKey) && UXComponentExtensionsHelper.LocalizationHelper != null)
|
||||
{
|
||||
text = UXComponentExtensionsHelper.LocalizationHelper.GetString(m_localizationID);
|
||||
text = UXComponentExtensionsHelper.LocalizationHelper.GetString(m_localizationKey);
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +30,7 @@ namespace UnityEngine.UI
|
||||
/// <param name="localizationID"></param>
|
||||
public void SetLocalization(string localizationID)
|
||||
{
|
||||
m_localizationID = localizationID;
|
||||
m_localizationKey = localizationID;
|
||||
ChangeLanguage();
|
||||
}
|
||||
}
|
||||
|
||||
43
Runtime/UXComponent/UXUIAnimation.cs
Normal file
43
Runtime/UXComponent/UXUIAnimation.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using AlicizaX.UI.Runtime;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AlicizaX.UI.Extension.UXComponent
|
||||
{
|
||||
[RequireComponent(typeof(AnimationFlow.Runtime.AnimationFlow))]
|
||||
public class UXUIAnimation : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private AnimationFlow.Runtime.AnimationFlow animationFlow;
|
||||
[SerializeField] private string ShowAnimationName = "Show";
|
||||
[SerializeField] private string HideAnimationName = "Close";
|
||||
private UIHolderObjectBase _holderObjectBase;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
animationFlow = GetComponent<AnimationFlow.Runtime.AnimationFlow>();
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_holderObjectBase = GetComponent<UIHolderObjectBase>();
|
||||
_holderObjectBase.OnWindowShowEvent += ShowAnimation;
|
||||
_holderObjectBase.OnWindowClosedEvent += CloseAnimation;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_holderObjectBase.OnWindowShowEvent -= ShowAnimation;
|
||||
_holderObjectBase.OnWindowClosedEvent -= CloseAnimation;
|
||||
}
|
||||
|
||||
internal void ShowAnimation()
|
||||
{
|
||||
animationFlow.Play(ShowAnimationName);
|
||||
}
|
||||
|
||||
internal void CloseAnimation()
|
||||
{
|
||||
animationFlow.Play(HideAnimationName);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/UXComponent/UXUIAnimation.cs.meta
Normal file
3
Runtime/UXComponent/UXUIAnimation.cs.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 72bd03ed7aed41ad81879dbb4dc96f71
|
||||
timeCreated: 1758701015
|
||||
Loading…
Reference in New Issue
Block a user