diff --git a/ConfigUIElement/Lrss3.ConfigUIElement.asmdef b/ConfigUIElement/Lrss3.ConfigUIElement.asmdef deleted file mode 100644 index 23414fc..0000000 --- a/ConfigUIElement/Lrss3.ConfigUIElement.asmdef +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "Lrss3.ConfigUIElement", - "rootNamespace": "", - "references": [ - "GUID:6055be8ebefd69e48b49212b09b47b2f", - "GUID:b1727b829ae4f0641acc8ad28ed624c2", - "GUID:343deaaf83e0cee4ca978e7df0b80d21" - ], - "includePlatforms": [], - "excludePlatforms": [], - "allowUnsafeCode": false, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [], - "noEngineReferences": false -} \ No newline at end of file diff --git a/ConfigUIElement/Lrss3.ConfigUIElement.asmdef.meta b/ConfigUIElement/Lrss3.ConfigUIElement.asmdef.meta deleted file mode 100644 index a21b44d..0000000 --- a/ConfigUIElement/Lrss3.ConfigUIElement.asmdef.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 25409440eb1d34849a42df21f5989356 -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ConfigUIElement/Scripts.meta b/ConfigUIElement/Scripts.meta deleted file mode 100644 index e6945f4..0000000 --- a/ConfigUIElement/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: d53a566643e99d74292ec8e451eb7356 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ConfigUIElement/Scripts/Element/ConfigButton.cs b/ConfigUIElement/Scripts/Element/ConfigButton.cs deleted file mode 100644 index 2632488..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigButton.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.UI; - -namespace LRC -{ - public class ConfigButton : ConfigSelectableItem - { - #region 属性字段 - - public Button targetButton; - - public override bool AllowInput - { - get => base.AllowInput; - set - { - if (targetButton != null) - targetButton.interactable = !value; - base.AllowInput = value; - } - } - - #endregion - - #region 实现 - - protected override void SetValue(object newValue) - { - throw new System.NotImplementedException(); - } - - public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false) - { - base.RefreshValueWithoutEvent(newValue, forceSet); - } - - private bool _doOnce = false; - protected override void Initialization_ChildConstruction(UIBehaviour component) - { - base.Initialization_ChildConstruction(component); - - var name = component.transform.name; - if (name is not "button") return; - if (_doOnce) - { - Debug.LogError("存在重复命名的属性模块:" + name); - return; - } - if (component is Button button) - { - _doOnce = true; - if (targetButton != null) - targetButton = button; - } - } - - #endregion - } -} \ No newline at end of file diff --git a/ConfigUIElement/Scripts/Element/ConfigDigitalInputField.cs b/ConfigUIElement/Scripts/Element/ConfigDigitalInputField.cs deleted file mode 100644 index 890062c..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigDigitalInputField.cs +++ /dev/null @@ -1,153 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using TMPro; -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.UI; - -namespace LRC -{ - /// - /// 一种数值增减输入框,将使用浮点值作为默认 - /// - public class ConfigDigitalInputField : ConfigSelectableItem - { - #region 属性字段 - -#if UNITY_EDITOR - public float editorInput; -#endif - - public TMP_InputField targetInput; - - public Button digitalAddButton; - public Button digitalSubButton; - - public double maxValue = 114514; - public double minValue = -114515; - public int digits = 6; - - /// - /// 增量 - /// - public double delta = 1; - - public override bool AllowInput - { - get => base.AllowInput; - set - { - if (targetInput != null) - targetInput.readOnly = !value; - if (digitalAddButton != null) - digitalAddButton.interactable = value; - if (digitalSubButton != null) - digitalSubButton.interactable = value; - base.AllowInput = value; - } - } - - #endregion - - #region 生命周期 - - protected override void OnValidate() - { - base.OnValidate(); -#if UNITY_EDITOR - if (targetInput != null) - targetInput.text = editorInput.ToString(); -#endif - } - - protected override void Awake() - { - base.Awake(); - if (ReferenceEquals(targetInput, null)) - { - Debug.LogError($"{name}配置项目条目的基本元素不存在"); - return; - } - targetInput.onSelect.AddListener(a => - { - WhenStartEdit(); - }); - targetInput.onValueChanged.AddListener(o => - { - double value = 0; - if (double.TryParse(o, out value)) - { - SetValue(value); - } - }); - targetInput.onEndEdit.AddListener(delegate - { - WhenEndEdit(); - }); - if (!ReferenceEquals(digitalAddButton, null)) - digitalAddButton.onClick.AddListener(delegate - { - SetValue(CastDigitalNumber(Value) + delta); - RefreshFormatValue(Value); - }); - if (!ReferenceEquals(digitalSubButton, null)) - digitalSubButton.onClick.AddListener(delegate - { - SetValue(CastDigitalNumber(Value) - delta); - RefreshFormatValue(Value); - }); - } - - #endregion - - #region 实现 - - protected override void SetValue(object newValue) - { - base.SetValue(CastDigitalNumber(newValue, minValue, maxValue, digits)); - } - - public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false) - { - base.RefreshValueWithoutEvent(CastDigitalNumber(newValue, minValue, maxValue, digits), forceSet); - } - - protected override void Initialization_ChildConstruction(UIBehaviour component) - { - base.Initialization_ChildConstruction(component); - - - if (component is TMP_InputField inputField) - { - if (targetInput != null) - targetInput = inputField; - } - else if(component is Button button) - { - var name = component.transform.name; - switch (name) - { - case "subbutton": - case "SubButton": - if (digitalSubButton != null) - digitalSubButton = button; - break; - case "addbutton": - case "AddButton": - if (digitalAddButton != null) - digitalAddButton = button; - break; - } - } - } - - protected override void RefreshFormatValue(object newValue) - { - base.RefreshFormatValue(newValue); - targetInput.text = CastDigitalNumber(newValue).ToString(numberFormat); - } - - #endregion - } -} diff --git a/ConfigUIElement/Scripts/Element/ConfigDigitalInputField.cs.meta b/ConfigUIElement/Scripts/Element/ConfigDigitalInputField.cs.meta deleted file mode 100644 index 679e580..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigDigitalInputField.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d84fd414ac6743e46909249427b18364 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ConfigUIElement/Scripts/Element/ConfigDropdown.cs b/ConfigUIElement/Scripts/Element/ConfigDropdown.cs deleted file mode 100644 index 0086ea1..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigDropdown.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using TMPro; -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.Serialization; -using UnityEngine.UI; - -namespace LRC -{ - public class ConfigDropdown : ConfigSelectableItem - { - #region 属性字段 - - public TMP_Dropdown targetDropdown; - - #endregion - - #region 生命周期 - - protected override void Awake() - { - base.Awake(); - targetDropdown.onValueChanged.AddListener(index => - { - SetValue(index); - }); - } - - public void InitializationDropdown(IEnumerable options) - { - targetDropdown.options = options - .Select(option => new TMP_Dropdown.OptionData(option)).ToList(); - targetDropdown.RefreshShownValue(); - if (IsValueInitNull) - RefreshValueWithoutEvent(0); - } - - #endregion - - #region 实现 - - protected override void SetValue(object newValue) - { - base.SetValue(CastIntNumber(newValue)); - } - - public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false) - { - base.RefreshValueWithoutEvent(CastIntNumber(newValue), forceSet); - } - - protected override void Initialization_ChildConstruction(UIBehaviour component) - { - base.Initialization_ChildConstruction(component); - - var name = component.transform.name; - if (name is not "dropdown") return; - if (component is TMP_Dropdown dropdown) - { - if (targetDropdown != null) - targetDropdown = dropdown; - } - } - - protected override void RefreshFormatValue(object newValue) - { - base.RefreshFormatValue(newValue); - if (newValue == null) - return; - targetDropdown.value = CastIntNumber(newValue); - targetDropdown.RefreshShownValue(); - } - - #endregion - } -} \ No newline at end of file diff --git a/ConfigUIElement/Scripts/Element/ConfigDropdown.cs.meta b/ConfigUIElement/Scripts/Element/ConfigDropdown.cs.meta deleted file mode 100644 index 42dee45..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigDropdown.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 471d16b38f4449a46b9fcf5b312f65d0 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ConfigUIElement/Scripts/Element/ConfigSelectableItem.cs b/ConfigUIElement/Scripts/Element/ConfigSelectableItem.cs deleted file mode 100644 index 72221bf..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigSelectableItem.cs +++ /dev/null @@ -1,712 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using TMPro; -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.Serialization; -using UnityEngine.UI; -using XericLibrary.Runtime.CustomEditor; -using XericLibrary.Runtime.MacroLibrary; - -namespace LRC -{ - /// - /// 一种用于基础面板设置条目的类 - /// - /// 在此类中提供了双向的属性委托修改,并且拥有脏标记。 - /// 该类在初始化时以输入为优先。 - /// 脏标记仅当界面首次发生改变时进行记录,并不会影响值。 - /// - /// - public abstract class ConfigSelectableItem : MonoBehaviour - { - #region 静态事件 - - private static event Action ForceUpdateAllConfigEvent; - /// - /// 强制所有激活的成员产生请求更新的事件(比如初始化时,外部更新时) - /// - /// - public static void ForceUpdateAll(bool resetDirty = false, bool forceSet = false) - { - ForceUpdateAllConfigEvent?.Invoke(resetDirty, forceSet); - } - - private static event Action ForceSetAllSourceValueEvent; - /// - /// 强制所有激活的成员产生请求设置的事件(比如按下应用按钮时) - /// - public static void ForceSetAllSourceValue() - { - ForceSetAllSourceValueEvent?.Invoke(); - } - - /// - /// 数值遭到修改时 - /// - public static event Action OnAnyValueDirty; - - /// - /// 当数值收到修改时,产生事件,其中值的含义是修改前的值 - /// - public static event Action OnAnyValueChange; - - #endregion - - #region 静态成员 - - /// - /// 所有有效的配置项目,当项目被隐藏(不处于激活状态时)就会从列表中删除。 - /// - private static readonly List ConfigItemList = new List(); - - /// - /// 项目列表有效成员的数量 - /// - public static int ConfigItemListCount => ConfigItemList.Count; - - /// - /// 获取 - /// - /// - /// - public static ConfigSelectableItem GetConfigItemByIndex(int index) => ConfigItemList[index]; - public static IEnumerable ConfigItemLists => ConfigItemList; - - private static bool autoUpdateValueAll; - /// - /// 自动更新所有数值 - /// - public static bool AutoUpdateValueAll - { - get => autoUpdateValueAll; - set - { - foreach (var item in ConfigItemList) - item.autoUpdateValue = value; - autoUpdateValueAll = value; - } - } - - #endregion - - #region 状态 - - /// - /// 数值遭到修改时,标记脏,这样在后续的应用中有可以保存的变化 - /// - /// 建议:这是可选的 - /// 这会立刻发生在值修改时,且比OnValueChange更早,但在复位之前只会调用一次。 - /// - /// - public event Action OnValueDirty; - - /// - /// 当数值收到修改时,产生事件,其中值的含义是修改前的值 - /// - /// 建议:这是可选的 - /// 这会立刻发生在值修改时,所以如果需要进行页面刷新的话,建议进行等待 - /// - /// - public event Action OnValueChange; - - /// - /// 当数值结束修改时 - /// - public event Action OnEndEdit; - /// - /// 当前属性请求获取属性值 - /// - /// 建议:这是必要的 - /// 当发生刷新事件时,将产生调用。 - /// 含义是将外部的值设定到此。 - /// - /// - public event Func GetSourceValue; - - /// - /// 当前属性请求设置属性值 - /// - /// 建议:这是必要的 - /// 当被应用时,比如调用了ForceSetAllSourceValue,将产生调用。 - /// 含义是将此处的界面值返回到属性中。 - /// 警告:不要在这里面调用ForceSetAllSourceValue,SetSourceValueRequest等方法, - /// 这会造成死循环以及内存溢出等问题。 - /// - /// - public event Action SetSourceValue; - - /// - /// 当前属性的自动更新请求获取 - /// - /// 建议:这是条件可选的 - /// 当被管理的目标中存在Toggle时(对应autoUpdateValueToggle项目) - /// 此处将用于从外部的值是否勾选值设定到此 - /// - /// - public event Func GetSourceValueAutoUpdate; - - /// - /// 当前属性的自动更新请求设置 - /// - /// 建议:这是条件可选的 - /// 当被管理的目标中存在Toggle时(对应autoUpdateValueToggle项目) - /// 此处将用于设置到外部的是否勾选值设定到此 - /// - /// - public event Action SetSourceValueAutoUpdate; - - - - /// - /// 请求此属性设置值(将值应用到寄存中) - /// - public void SetSourceValueRequest() - { - SetSourceValue?.Invoke(this, Value); - } - - #endregion - - #region 属性字段 - - /// - /// 项目对应的标记tag - /// - [Rename("映射标记")] - public string configTag; - - /// - /// 设定是否有效。 - /// 如果无效,则不允许输入 - /// - [SerializeField] - [Rename("允许输入")] - private bool allowInput = true; - - /// - /// 自动更新数值 - /// - [SerializeField] - [Rename("主动更新")] - private bool autoUpdateValue = true; - - /// - /// 允许阻塞自动更新,表示此项目可以脱离自动更新状态选框的状态运行 - /// - [SerializeField] - [Rename("允许阻塞自动更新")] - private bool allowBlockUpdate = true; - - /// - /// 阻塞自动更新,一般由程序自动根据焦点更新 - /// - [SerializeField] - [Rename("阻塞自动更新")] - private bool forceBlockUpdate = false; - - /// - /// 格式化文本 - /// - public string numberFormat = "0.##"; - - /// - /// 项目标题组件 - /// - public TextMeshProUGUI titleLabel; -#if UNITY_EDITOR - [SerializeField] -#endif - private string titleTextContext; - - /// - /// 帮助文本组件 - /// - public TextMeshProUGUI helpLabel; -#if UNITY_EDITOR - [SerializeField] -#endif - private string helpTextContext; - - /// - /// 单位文本组件 - /// - public TextMeshProUGUI unitLabel; -#if UNITY_EDITOR - [SerializeField] -#endif - private string unitTextContext; - - /// - /// 条目前的选框,与autoUpdateValue对应 - /// - [Rename("自动更新状态选框")] - public Toggle autoUpdateValueToggle; - - /// - /// 反转选框状态 - /// - [Rename("反转自动更新按钮状态")] - public bool autoUpdateValueToggleReversalState; - - [Rename("反转自动更新状态")] - public bool autoUpdateValueReversalState; - - /// - /// 脏属性自动复位。 - /// 当属性被重新开关时,将取消脏状态 - /// - [Rename("脏标记自动复位")] - public bool dirtyAutoReset = false; - - // ==== 属性 ==== // - - /// - /// 设定是否输入有效 - /// - public virtual bool AllowInput - { - get => allowInput; - set => allowInput = value; - } - - /// - /// 此属性项目已经初始化 - /// - [HideInInspector] - public bool IsValueInitNull { get; private set; } = true; - - // [Obsolete("请使用访问器")] - private bool _isDirty; - /// - /// 脏属性标记,首次脏会进行广播 - /// - private bool IsDirty - { - get => _isDirty; - set - { - if (_isDirty) - { - if (!value) - _isDirty = false; - return; - } - if (!value) return; - - _isDirty = true; - OnAnyValueDirty?.Invoke(this); - OnValueDirty?.Invoke(this); - } - } - - /// - /// 设定自动更新状态,并同步选框 - /// - /// 为了书写方便,保存的状态是和外部暂存值一致, - /// 此访问器将作为本地状态的标准访问。 - /// - /// 访问将自动进行转换,而设置则不进行转换, - /// 所以应当使用此访问器进行设置或内部访问,而与外部通讯应当使用字段。 - /// - /// 如果需要将此内部判断状态转为界面状态: - /// 应当先通过autoUpdateValueReversalState转为暂存值, - /// 然后再通过autoUpdateValueToggleReversalState转为界面值。 - /// - /// - public bool AutoUpdateValue - { - get => autoUpdateValueReversalState ^ autoUpdateValue; - set - { - autoUpdateValue = value; - if (autoUpdateValueToggle != null) - autoUpdateValueToggle.isOn = autoUpdateValueToggleReversalState ^ value; - } - } - - /// - /// 设定阻塞自动更新 - /// - public bool ForceBlockUpdate - { - get => forceBlockUpdate; - set => forceBlockUpdate = value; - } - - /// - /// 项目标题 - /// - public string TitleName - { - get => titleLabel.text; - set => titleLabel.text = value; - } - - /// - /// 帮助文本,再默认情况下应该是不显示的通过赋予空文本来关闭显示 - /// - public string HelpName - { - get - { - if (helpLabel != null) return helpLabel.text; - return null; - } - set - { - if (helpLabel != null) - { - if (value != null) - { - helpLabel.text = value; - helpLabel.gameObject.SetActive(true); - } - else - helpLabel.gameObject.SetActive(false); - } - } - } - - public string UnitName - { - get => unitLabel.text; - set => unitLabel.text = value; - } - - [SerializeField] - // [Obsolete("请使用访问器")] - private object _value; - - /// - /// 项目值 - /// - public object Value - { - get => _value; - protected set - { - if (IsValueInitNull && value != null) - IsValueInitNull = false; - _value = value; - } - } - - // ==== 暂存 ==== // - - public FieldInfo FieldInfo; - - public Type FieldType; - - #endregion - - #region 生命周期 - - protected virtual void OnValidate() - { - if (titleLabel != null) - TitleName = titleTextContext; - if (helpLabel != null) - HelpName = helpTextContext; - if (unitLabel != null) - UnitName = unitTextContext; - } - - protected virtual void Awake() - { - foreach (var child in transform.GetChildren()) - { - var component = child.GetComponent(); - if (component != null) - Initialization_ChildConstruction(component); - } - - Initialization_EventBinding(); - } - - protected virtual void OnEnable() - { - ConfigItemList.Add(this); - ForceUpdateAllConfigEvent += ForceUpdate; - ForceSetAllSourceValueEvent += SetSourceValueRequest; - - if (dirtyAutoReset) - IsDirty = false; - } - - protected virtual void OnDisable() - { - ConfigItemList.Remove(this); - ForceUpdateAllConfigEvent -= ForceUpdate; - ForceSetAllSourceValueEvent -= SetSourceValueRequest; - } - - protected virtual void Start() - { - ForceUpdate(true); - } - - private void Update() - { - if (IsValueInitNull || (AutoUpdateValue && !(allowBlockUpdate && forceBlockUpdate))) - { - ForceUpdate(); - } - } - - private void OnDestroy() - { - ForceUpdateAllConfigEvent -= ForceUpdate; - } - - #endregion - - #region 换算与转换 - - protected static double CastDigitalNumber(object newValue) - { - if (double.TryParse(newValue.ToString(), out var value)) - { - return value; - } - return -1; - } - - /// - /// 转换到数值类型(数值钳制与四舍五入) - /// - /// - /// - /// - /// - /// - protected static double CastDigitalNumber(object newValue, double minValue, double maxValue, int digits) - { - // var resultValue = newValue switch - // { - // bool boolValue => boolValue ? 1 : 0, - // short intValue => intValue, - // int intValue => intValue, - // long intValue => intValue, - // float floatValue => Math.Round(floatValue, digits), - // double doubleValue => Math.Round(doubleValue, digits), - // _ => 0 - // }; -#if UNITY_EDITOR - if (newValue == null) - { - Debug.LogError($"参数转换错误:目标是一个空值,请在发生空值时提前退出"); - return -1; - } -#endif - if (double.TryParse(newValue.ToString(), out var value)) - { - var resultValue = Math.Round(value, digits); - return Math.Clamp(resultValue, minValue, maxValue); - } - Debug.LogError($"参数转换错误:{newValue}可能不是一个有效的数值"); - return -1; - } - - protected static int CastIntNumber(object newValue) - { - var resultValue = Convert.ToInt32(newValue); - return resultValue; - } - - protected static Vector2 CastVector2(object newValue) - { - return newValue switch - { - Vector2 vec2Value => vec2Value, - System.Numerics.Vector2 sysVec2Value => new Vector2(sysVec2Value.X, sysVec2Value.Y), - _ => Vector2.zero - }; - } - - protected static Vector3 CastVector3(object newValue) - { - return newValue switch - { - Vector3 vec3Value => vec3Value, - System.Numerics.Vector3 sysVec3Value => new Vector3(sysVec3Value.X, sysVec3Value.Y, sysVec3Value.Z), - _ => Vector3.zero - }; - } - - #endregion - - #region 初始化方法 - - /// - /// 可选的基本初始化 - /// - /// 设定自动更新 - protected void Initialization(bool autoUpdateValue = true) - { - AutoUpdateValue = autoUpdateValue; - } - - private bool _doOnce = false; - /// - /// 构建属性,在初始化过程中,通过识别项目来构建域 - /// - protected virtual void Initialization_ChildConstruction(UIBehaviour component) - { - // 跟踪节点的名称 - var name = component.gameObject.name; - // 初始化自动更新对勾 - if (name == "toggle" && component is Toggle toggle) - { - if (autoUpdateValueToggle == null) - autoUpdateValueToggle = toggle; - return; - } - if (name is not ("title" or "name")) return; - if (_doOnce) - { - Debug.LogError("存在重复命名的属性模块:" + name); - return; - } - if (component is TextMeshProUGUI textMeshProUGUI) - { - _doOnce = true; - if (titleLabel != null) - titleLabel = textMeshProUGUI; - } - } - - /// - /// 构建事件,在初始化结束前,需要对所有动态绑定的按键进行事件绑定 - /// - protected virtual void Initialization_EventBinding() - { - // 无论如何,事件需要被注册 - if (autoUpdateValueToggle != null) - { - autoUpdateValueToggle.onValueChanged.AddListener(a => - { - autoUpdateValue = autoUpdateValueToggleReversalState ^ a; - // 访问器将会自动转换,所以使用字段 - SetSourceValueAutoUpdate?.Invoke(autoUpdateValue); - // 可能不会脏 - // OnValueDirty?.Invoke(this); - }); - } - } - - #endregion - - #region 更新方法 - - /// - /// 更新函数 - /// - /// 在其他任意时刻调用时,将强制刷新其中的功能,如果已经是脏属性则不会有任何行为。 - /// 更新是指从本地数据中更新,这会立刻产生值获取回调。 - /// - /// - public virtual void ForceUpdate(bool resetDirty = false, bool forceSet = false) - { - if (resetDirty) - IsDirty = false; - var value = GetSourceValue?.Invoke(this); - if (value == null) - return ; - RefreshValueWithoutEvent(value, forceSet); - RefreshAutoUpdateValue(); - } - - /// - /// 设置值,并触发更改事件,通常由界面发起所以不会主动更新界面 - /// - /// - protected virtual void SetValue(object newValue) - { - if (Value == newValue) - return; - var lastValue = Value; - // 如果不允许输入,将复位为现在的值 - if (!allowInput) - RefreshValueWithoutEvent(Value); - else - { - Value = newValue; - IsDirty = true; - - OnAnyValueChange?.Invoke(this, lastValue); - OnValueChange?.Invoke(this, lastValue); - } - } - - /// - /// 设置值,不触发更改时的事件,但应该进行界面数值更新。 - /// - /// - /// - public virtual void RefreshValueWithoutEvent(object newValue, bool forceSet = false) - { - if (!AutoUpdateValue && !forceSet) - return; - if (newValue == null) - return; - if (Value != null && (Value.ToString() == newValue.ToString())) - return; - Value = newValue; - RefreshFormatValue(newValue); - } - - /// - /// 更新自动更新状态 - /// - protected void RefreshAutoUpdateValue() - { - var isSourceValueAutoUpdate = GetSourceValueAutoUpdate?.Invoke(this); - if (isSourceValueAutoUpdate != null) - AutoUpdateValue = isSourceValueAutoUpdate.Value; - } - - /// - /// 刷新格式化文本,在触发刷新时将产生更新 - /// - protected virtual void RefreshFormatValue(object newValue) - { - - } - - protected void WhenStartEdit() - { - // Debug.Log("开始编辑"); - ForceBlockUpdate = true; - } - - /// - /// 数值输入完毕,或焦点移除时调用。 - /// - protected void WhenEndEdit() - { - // Debug.Log("结束编辑"); - ForceBlockUpdate = false; - OnEndEdit?.Invoke(this, Value); - } - - #endregion - - #region 外观设定 - - /// - /// 销毁自动更新复选框,并设定当前是否允许自动更新 - /// - /// - public void DestroyAutoUpdateValue(bool autoUpdateValue) - { - Destroy(autoUpdateValueToggle.gameObject); - this.autoUpdateValue = autoUpdateValueReversalState ^ autoUpdateValue; - } - - #endregion - - } -} \ No newline at end of file diff --git a/ConfigUIElement/Scripts/Element/ConfigSelectableItem.cs.meta b/ConfigUIElement/Scripts/Element/ConfigSelectableItem.cs.meta deleted file mode 100644 index 2fdb05f..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigSelectableItem.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3e3c729eeb8e03f459a9c95dc6e239d8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ConfigUIElement/Scripts/Element/ConfigTextInputField.cs b/ConfigUIElement/Scripts/Element/ConfigTextInputField.cs deleted file mode 100644 index 0db11a9..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigTextInputField.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using TMPro; -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.UI; - -namespace LRC -{ - /// - /// 一种普通文本输入框 - /// - public class ConfigTextInputField : ConfigSelectableItem - { - #region 属性字段 - -#if UNITY_EDITOR - public string editorInput; -#endif - - public TMP_InputField targetInput; - - - public override bool AllowInput - { - get => base.AllowInput; - set - { - if (targetInput != null) - targetInput.readOnly = !value; - base.AllowInput = value; - } - } - - #endregion - - #region 生命周期 - - protected override void OnValidate() - { - base.OnValidate(); -#if UNITY_EDITOR - if (targetInput != null) - targetInput.text = editorInput; -#endif - } - - protected override void Awake() - { - base.Awake(); - targetInput.onSelect.AddListener(a => - { - WhenStartEdit(); - }); - targetInput.onValueChanged.AddListener(o => - { - if(double.TryParse(o, out var value)) - SetValue(value); - }); - targetInput.onEndEdit.AddListener(delegate - { - WhenEndEdit(); - }); - } - - #endregion - - #region 实现 - - protected override void SetValue(object newValue) - { - base.SetValue(newValue); - } - - public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false) - { - base.RefreshValueWithoutEvent(newValue, forceSet); - } - - protected override void Initialization_ChildConstruction(UIBehaviour component) - { - base.Initialization_ChildConstruction(component); - - if (component is TMP_InputField inputField) - { - if (targetInput != null) - targetInput = inputField; - } - } - - protected override void RefreshFormatValue(object newValue) - { - base.RefreshFormatValue(newValue); - targetInput.text = newValue.ToString(); - } - - #endregion - } -} diff --git a/ConfigUIElement/Scripts/Element/ConfigTextInputField.cs.meta b/ConfigUIElement/Scripts/Element/ConfigTextInputField.cs.meta deleted file mode 100644 index 85bee7b..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigTextInputField.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c9b27b4ed9920c947b157c1d7702372c -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ConfigUIElement/Scripts/Element/ConfigToggleGroup.cs b/ConfigUIElement/Scripts/Element/ConfigToggleGroup.cs deleted file mode 100644 index d795027..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigToggleGroup.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using UnityEngine.EventSystems; -using UnityEngine.Serialization; -using UnityEngine.UI; - -namespace LRC -{ - /// - /// 单选项控制组,将返回一个代表当前有效单选项索引作为值。 - /// - public class ConfigToggleGroup : ConfigSelectableItem - { - #region 属性字段 - - public ToggleGroup targetToggle; - - public List toggles; - - #endregion - - #region 生命周期 - - protected override void Awake() - { - base.Awake(); - - for (int i = 0; i < toggles.Count; i++) - { - void BuildInGroupInit() - { - var index = i; - var toggle = toggles[i]; - toggle.onValueChanged.AddListener(a => - { - if (a) - SetValue(index); - }); - } - BuildInGroupInit(); - } - } - - #endregion - - #region 实现 - - protected override void SetValue(object newValue) - { - base.SetValue(CastIntNumber(newValue)); - } - - public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false) - { - base.RefreshValueWithoutEvent(CastIntNumber(newValue), forceSet); - } - - protected override void Initialization_ChildConstruction(UIBehaviour component) - { - base.Initialization_ChildConstruction(component); - - if (component is Toggle toggle && - !toggles.Contains(toggle)) - toggles.Add(toggle); - } - - protected override void RefreshFormatValue(object newValue) - { - base.RefreshFormatValue(newValue); - var newIndex = CastIntNumber(newValue); - // var index = 0; - // foreach (var toggle in targetToggle.ActiveToggles()) - // { - // if (newIndex != index++) - // continue; - // toggle.isOn = true; - // Debug.Log(TitleName +":设置布尔项目"); - // } - toggles[newIndex].SetIsOnWithoutNotify(true); - } - - #endregion - } -} \ No newline at end of file diff --git a/ConfigUIElement/Scripts/Element/ConfigToggleGroup.cs.meta b/ConfigUIElement/Scripts/Element/ConfigToggleGroup.cs.meta deleted file mode 100644 index 727e57d..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigToggleGroup.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 1b1b61fd3a211734eb3d51cedcbe579f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ConfigUIElement/Scripts/Element/ConfigTypeOverrideAttribute.cs b/ConfigUIElement/Scripts/Element/ConfigTypeOverrideAttribute.cs deleted file mode 100644 index 8ee1393..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigTypeOverrideAttribute.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using UnityEngine; - -namespace LRC -{ - [AttributeUsage(AttributeTargets.Field)] - public class ConfigTypeOverrideAttribute : PropertyAttribute - { - public readonly string TypeName; - - public ConfigTypeOverrideAttribute(string name) - { - TypeName = name; - } - - /// - /// 尝试获取其中的rename定义名称 - /// - /// - /// 通过特性获取的名称,如果没有则为原生的名称 - /// 是否成功通过特性获取名称,否则是普通类型名称 - public static bool TryGetMemberName(FieldInfo field, out string name) - { - if (field.GetCustomAttribute(typeof(ConfigTypeOverrideAttribute)) is ConfigTypeOverrideAttribute rename) - { - name = rename.TypeName; - return true; - } - - name = field.FieldType.Name; - return false; - } - - } -} \ No newline at end of file diff --git a/ConfigUIElement/Scripts/Element/ConfigTypeOverrideAttribute.cs.meta b/ConfigUIElement/Scripts/Element/ConfigTypeOverrideAttribute.cs.meta deleted file mode 100644 index 261b8ee..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigTypeOverrideAttribute.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a130623ae66ff564a9e14580549d2858 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ConfigUIElement/Scripts/Element/ConfigVec2InputField.cs b/ConfigUIElement/Scripts/Element/ConfigVec2InputField.cs deleted file mode 100644 index 68f6078..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigVec2InputField.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using TMPro; -using UnityEngine.EventSystems; -using UnityEngine.UI; - -namespace LRC -{ - public class ConfigVec2InputField : ConfigSelectableItem - { - #region 属性字段 - -#if UNITY_EDITOR - public Vector2 editorInput; -#endif - - public TMP_InputField targetInputX; - public TMP_InputField targetInputY; - - public override bool AllowInput - { - get => base.AllowInput; - set - { - if (targetInputX != null) - targetInputX.readOnly = !value; - if (targetInputY != null) - targetInputY.readOnly = value; - base.AllowInput = value; - } - } - - #endregion - - #region 生命周期 - protected override void OnValidate() - { - base.OnValidate(); -#if UNITY_EDITOR - if (targetInputX != null) - targetInputX.text = editorInput.x.ToString(); - if (targetInputY != null) - targetInputY.text = editorInput.y.ToString(); -#endif - } - protected override void Awake() - { - base.Awake(); - - targetInputX.onSelect.AddListener(a => - { - WhenStartEdit(); - }); - targetInputY.onSelect.AddListener(a => - { - WhenStartEdit(); - }); - targetInputX.onValueChanged.AddListener(a => - { - var value = CastVector3(Value); - value.x = float.Parse(a); - SetValue(value); - }); - targetInputY.onValueChanged.AddListener(a => - { - var value = CastVector3(Value); - value.y = float.Parse(a); - SetValue(value); - }); - targetInputX.onEndEdit.AddListener(delegate - { - WhenEndEdit(); - }); - targetInputY.onEndEdit.AddListener(delegate - { - WhenEndEdit(); - }); - } - - #endregion - - #region 实现 - - protected override void SetValue(object newValue) - { - base.SetValue(CastVector2(newValue)); - } - - public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false) - { - base.RefreshValueWithoutEvent(CastVector2(newValue), forceSet); - } - - protected override void Initialization_ChildConstruction(UIBehaviour component) - { - base.Initialization_ChildConstruction(component); - - var name = component.transform.name; - if (component is not TMP_InputField inputField) - return; - switch (name) - { - case "inputx": - case "inputX": - if (targetInputX != null) - targetInputX = inputField; - break; - case "inputy": - case "inputY": - if (targetInputY != null) - targetInputY = inputField; - break; - default: - break; - } - } - - protected override void RefreshFormatValue(object newValue) - { - base.RefreshFormatValue(newValue); - var value = CastVector2(newValue); - targetInputX.text = value.x.ToString(numberFormat); - targetInputY.text = value.y.ToString(numberFormat); - } - - #endregion - } -} \ No newline at end of file diff --git a/ConfigUIElement/Scripts/Element/ConfigVec2InputField.cs.meta b/ConfigUIElement/Scripts/Element/ConfigVec2InputField.cs.meta deleted file mode 100644 index 07e4cad..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigVec2InputField.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 118ff8f18137da54087c6d572fc5db75 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ConfigUIElement/Scripts/Element/ConfigVec3InputField.cs b/ConfigUIElement/Scripts/Element/ConfigVec3InputField.cs deleted file mode 100644 index af55352..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigVec3InputField.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using UnityEngine; -using TMPro; -using UnityEngine.EventSystems; -using UnityEngine.UI; - -namespace LRC -{ - - public class ConfigVec3InputField : ConfigSelectableItem - { - #region 属性字段 - -#if UNITY_EDITOR - public Vector3 editorInput; -#endif - - public TMP_InputField targetInputX; - public TMP_InputField targetInputY; - public TMP_InputField targetInputZ; - - public override bool AllowInput - { - get => base.AllowInput; - set - { - if (targetInputX != null) - targetInputX.readOnly = !value; - if (targetInputY != null) - targetInputY.readOnly = value; - if (targetInputZ != null) - targetInputZ.readOnly = value; - base.AllowInput = value; - } - } - - #endregion - - #region 生命周期 - - protected override void OnValidate() - { - base.OnValidate(); -#if UNITY_EDITOR - if (targetInputX != null) - targetInputX.text = editorInput.x.ToString(); - if (targetInputY != null) - targetInputY.text = editorInput.y.ToString(); - if (targetInputZ != null) - targetInputZ.text = editorInput.z.ToString(); -#endif - } - - protected override void Awake() - { - base.Awake(); - - targetInputX.onSelect.AddListener(a => - { - WhenStartEdit(); - }); - targetInputY.onSelect.AddListener(a => - { - WhenStartEdit(); - }); - targetInputZ.onSelect.AddListener(a => - { - WhenStartEdit(); - }); - targetInputX.onValueChanged.AddListener(a => - { - var value = CastVector3(Value); - value.x = float.Parse(a); - SetValue(value); - }); - targetInputY.onValueChanged.AddListener(a => - { - var value = CastVector3(Value); - value.y = float.Parse(a); - SetValue(value); - }); - targetInputZ.onValueChanged.AddListener(a => - { - var value = CastVector3(Value); - value.z = float.Parse(a); - SetValue(value); - }); - targetInputX.onEndEdit.AddListener(delegate - { - WhenEndEdit(); - }); - targetInputY.onEndEdit.AddListener(delegate - { - WhenEndEdit(); - }); - targetInputZ.onEndEdit.AddListener(delegate - { - WhenEndEdit(); - }); - } - - #endregion - - #region 实现 - - protected override void SetValue(object newValue) - { - base.SetValue(CastVector3(newValue)); - } - - public override void RefreshValueWithoutEvent(object newValue, bool forceSet = false) - { - base.RefreshValueWithoutEvent(CastVector3(newValue), forceSet); - } - - protected override void Initialization_ChildConstruction(UIBehaviour component) - { - base.Initialization_ChildConstruction(component); - - var name = component.transform.name; - if (component is not TMP_InputField inputField) - return; - switch (name) - { - case "inputx": - case "inputX": - if (targetInputX != null) - targetInputX = inputField; - break; - case "inputy": - case "inputY": - if (targetInputY != null) - targetInputY = inputField; - break; - case "inputz": - case "inputZ": - if (targetInputZ != null) - targetInputZ = inputField; - break; - default: - break; - } - } - - protected override void RefreshFormatValue(object newValue) - { - base.RefreshFormatValue(newValue); - var value = CastVector3(newValue); - targetInputX.text = value.x.ToString(numberFormat); - targetInputY.text = value.y.ToString(numberFormat); - targetInputZ.text = value.z.ToString(numberFormat); - } - - #endregion - } -} \ No newline at end of file diff --git a/ConfigUIElement/Scripts/Element/ConfigVec3InputField.cs.meta b/ConfigUIElement/Scripts/Element/ConfigVec3InputField.cs.meta deleted file mode 100644 index e16d034..0000000 --- a/ConfigUIElement/Scripts/Element/ConfigVec3InputField.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: b6e1779348dcc2b48a6f009b828e9b5d -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Editor/XericLibraryEditor.dll b/Editor/XericLibraryEditor.dll index b02c253..a44c54c 100644 Binary files a/Editor/XericLibraryEditor.dll and b/Editor/XericLibraryEditor.dll differ diff --git a/Runtime/CentralizeLog.dll b/Runtime/CentralizeLog.dll deleted file mode 100644 index bdb08e2..0000000 Binary files a/Runtime/CentralizeLog.dll and /dev/null differ diff --git a/Runtime/CentralizeLog.dll.meta b/Runtime/CentralizeLog.dll.meta deleted file mode 100644 index 2c16b3b..0000000 --- a/Runtime/CentralizeLog.dll.meta +++ /dev/null @@ -1,33 +0,0 @@ -fileFormatVersion: 2 -guid: c754cc17629bc0f4cac54d1417f746b3 -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 1 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - Any: - second: - enabled: 1 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - DefaultValueInitialized: true - - first: - Windows Store Apps: WindowsStoreApps - second: - enabled: 0 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/RescissionRework.dll b/Runtime/RescissionRework.dll deleted file mode 100644 index 05c0383..0000000 Binary files a/Runtime/RescissionRework.dll and /dev/null differ diff --git a/Runtime/RescissionRework.dll.meta b/Runtime/RescissionRework.dll.meta deleted file mode 100644 index 758c6ca..0000000 --- a/Runtime/RescissionRework.dll.meta +++ /dev/null @@ -1,33 +0,0 @@ -fileFormatVersion: 2 -guid: dad679042ecb6164d815157fcf4dd580 -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 1 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - Any: - second: - enabled: 1 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - DefaultValueInitialized: true - - first: - Windows Store Apps: WindowsStoreApps - second: - enabled: 0 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/ConfigUIElement.meta b/Runtime/UI/TmpText.meta similarity index 77% rename from ConfigUIElement.meta rename to Runtime/UI/TmpText.meta index c012416..6ec62ab 100644 --- a/ConfigUIElement.meta +++ b/Runtime/UI/TmpText.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 7758a0679c9038144a4b0d007d44618f +guid: 85f1b523843f5884bb9f6b47500bccd0 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Runtime/UI/TmpText/TMPHyperlinkManager.cs b/Runtime/UI/TmpText/TMPHyperlinkManager.cs new file mode 100644 index 0000000..b9184b1 --- /dev/null +++ b/Runtime/UI/TmpText/TMPHyperlinkManager.cs @@ -0,0 +1,164 @@ +锘縰sing System; +using System.Collections.Generic; +using Sirenix.OdinInspector; +using TMPro; +using UnityEngine; +using UnityEngine.Events; +using XericLibrary.Runtime.MacroLibrary; +using XericLibrary.Runtime.Type; + +namespace Deconstruction.UI.TmpText +{ + /// + /// TMP瓒呴摼鎺ョ偣鍑荤鐞嗙粍浠 + /// + public class TMPHyperlinkManager : MonoBehaviour + { + /// + /// 鐢诲竷缁勪欢 + /// +#if ODIN_INSPECTOR + [LabelText("鐢诲竷*")] +#endif + [Tooltip("缁勪欢鍙负绌猴紝灏嗚嚜鍔ㄥ悜涓婃煡鎵")] + [SerializeField] public Canvas canvas; + +#if ODIN_INSPECTOR + [LabelText("鐐瑰嚮瓒呴摼鎺ユ椂鍥炶皟")] +#endif + [SerializeField] + private UnityEvent _onClickLink; + public Action onClickLink; + + /// + /// 褰撳墠鎽勫儚鏈 + /// + private Camera _camera; + /// + /// 瀛樺偍閾炬帴ID涓庡搴斿洖璋冨嚱鏁扮殑鏄犲皠 + /// + private Dictionary _linkCallbacks = new Dictionary(); + + protected void Awake() + { + if (canvas == null) + transform.GetParents().Startup(transform).GetComponent(out canvas); + if (canvas == null) + { + Debug.LogError("TMP鏂囨湰瀵硅薄蹇呴』鍦–anvas涓嬫墠鑳戒娇鐢ㄨ秴閾炬帴鍔熻兘"); + return; + } + + if (canvas.renderMode == RenderMode.ScreenSpaceOverlay) + _camera = null; + else + _camera = canvas.worldCamera; + + + } + + /// + /// 娉ㄥ唽閾炬帴鍥炶皟鍑芥暟 + /// + public void RegisterLinkCallback(string linkID, Action callback) + { + if (_linkCallbacks.ContainsKey(linkID)) + { + Debug.LogWarning($"閾炬帴ID '{linkID}' 宸插瓨鍦紝灏嗚鐩栦箣鍓嶇殑鍥炶皟鍑芥暟"); + _linkCallbacks[linkID] = callback; + } + else + { + _linkCallbacks.Add(linkID, callback); + } + } + + /// + /// 娉ㄩ攢閾炬帴鍥炶皟鍑芥暟 + /// + public void UnregisterLinkCallback(string linkID) + { + if (_linkCallbacks.ContainsKey(linkID)) + { + _linkCallbacks.Remove(linkID); + } + } + + /// + /// 澶勭悊閾炬帴鐐瑰嚮浜嬩欢 + /// + public void HandleLinkClick(string linkID) + { + if (_linkCallbacks.TryGetValue(linkID, out Action callback)) + { + callback?.Invoke(); + Debug.Log($"鎵ц閾炬帴 '{linkID}' 鐨勫洖璋冨嚱鏁"); + } + else + { + Debug.LogWarning($"鏈壘鍒伴摼鎺D '{linkID}' 鐨勫洖璋冨嚱鏁"); + } + } + + + /// + /// 妫鏌ュ潗鏍囦笅鐨勮秴閾炬帴绱㈠紩 + /// + /// + /// + /// + internal int CheckLinkIndex(TMP_Text text, Vector3 position) + { + return TMP_TextUtilities.FindIntersectingLink(text, position, _camera); + } + /// + /// 妫鏌ュ潗鏍囦笅鐨勮秴閾炬帴id淇℃伅 + /// + /// + /// + /// + /// + internal bool CheckLinkInfo(TMP_Text text, Vector3 position, out TMP_LinkInfo linkInfo) + { + var index = CheckLinkIndex(text, position); + if (index != -1) + { + linkInfo = text.textInfo.linkInfo[index]; + return true; + } + linkInfo = default; + return false; + } + /// + /// 妫鏌ュ潗鏍囦笅鐨勮秴閾炬帴id + /// + /// + /// + /// + /// + internal bool CheckLinkID(TMP_Text text, Vector3 position, out string linkID) + { + if (CheckLinkInfo(text, position, out var info)) + { + linkID = info.GetLinkID(); + return true; + } + linkID = string.Empty; + return false; + } + + /// + /// 褰撲换鎰弔mp瀵硅薄瓒呴摼鎺ョ偣鍑绘椂璋冪敤锛屼粠杩欓噷鍙戦佷簨浠 + /// + /// + internal void OnAnyLinkClick(string linkID) + { + onClickLink?.Invoke(linkID); + _onClickLink.Invoke(linkID); + Debug.Log($"click link{linkID}"); + // 杩欓噷涓嶉渶瑕佸鐞嗘姤閿欙紝搴斿綋鐢卞彂閫佹秷鎭殑鎴愬憳澶勭悊 + } + + // todo 涓诲姩鏌ユ壘鎵鏈夌殑tmp缁勪欢锛屾垨鏄瓑缁勪欢鍞ら啋鍚庡尯绠$悊瀹冧滑锛岀敤鏉ヨ幏寰楁墍鏈夌殑甯︽湁鏍囪鐨勮秴閾炬帴缁勪欢 + } +} \ No newline at end of file diff --git a/ConfigUIElement/Scripts/Element/ConfigButton.cs.meta b/Runtime/UI/TmpText/TMPHyperlinkManager.cs.meta similarity index 83% rename from ConfigUIElement/Scripts/Element/ConfigButton.cs.meta rename to Runtime/UI/TmpText/TMPHyperlinkManager.cs.meta index 699ed51..f8902aa 100644 --- a/ConfigUIElement/Scripts/Element/ConfigButton.cs.meta +++ b/Runtime/UI/TmpText/TMPHyperlinkManager.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 73f7a373611d15741b1093e0669abea9 +guid: 6b48ffc6688579846a29db364326940a MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Runtime/UI/TmpText/TMPHyperlinkReceiver.cs b/Runtime/UI/TmpText/TMPHyperlinkReceiver.cs new file mode 100644 index 0000000..4e3236c --- /dev/null +++ b/Runtime/UI/TmpText/TMPHyperlinkReceiver.cs @@ -0,0 +1,67 @@ +锘縰sing System; +using Sirenix.OdinInspector; +using TMPro; +using UnityEngine; +using UnityEngine.Events; +using UnityEngine.EventSystems; +using XericLibrary.Runtime.MacroLibrary; + +namespace Deconstruction.UI.TmpText +{ + /// + /// 闄勫姞鍒癟MP鏂囨湰瀵硅薄鐨勭粍浠讹紝鐢ㄤ簬鎹曡幏鐐瑰嚮浜嬩欢骞惰浆鍙戠粰绠$悊鍣 + /// + [RequireComponent(typeof(TextMeshProUGUI))] + public class TMPHyperlinkReceiver : MonoBehaviour, IPointerClickHandler + { + private TextMeshProUGUI _tmpText; + +#if ODIN_INSPECTOR + [LabelText("瓒呴摼鎺ョ鐞嗗櫒*")] +#endif + [Tooltip("缁勪欢鍙负绌猴紝灏嗚嚜鍔ㄥ悜涓婃煡鎵")] + public TMPHyperlinkManager manager; + +#if ODIN_INSPECTOR + [LabelText("鐐瑰嚮瓒呴摼鎺ユ椂鍥炶皟")] +#endif + [SerializeField] + private UnityEvent _onClickLink; + public Action onClickLink; + + private void Awake() + { + _tmpText = GetComponent(); + if (manager == null) + transform.GetParents().Startup(transform).GetComponent(out manager); + if (manager == null) + throw new Exception("TMP鏂囨湰瓒呴摼鎺ラ泦鎴愭崟鑾风粍浠跺繀椤绘斁鍦ㄥ叿鏈夌鐞嗗櫒鐨勭埗绾т笅"); + } + + public void OnPointerClick(PointerEventData eventData) + { + ClickPoint(eventData.position); + } + + /// + /// 鍦ㄥ潗鏍囧鐐瑰嚮瓒呴摼鎺ユ枃鏈 + /// + /// + public void ClickPoint(Vector3 position) + { + if (!manager.CheckLinkID(_tmpText, position, out var linkID)) + return; + try + { + onClickLink?.Invoke(linkID); + _onClickLink.Invoke(linkID); + manager.OnAnyLinkClick(linkID); + } + catch (Exception e) + { + Debug.LogError($"鐐瑰嚮 {_tmpText.text.LimitStringLength(32)} 鐨勮秴閾炬帴 {linkID} 鏃跺嚭閿欙細\n{e.Message}\n{e.Data}", this); + } + } + } + +} \ No newline at end of file diff --git a/Runtime/UI/TmpText/TMPHyperlinkReceiver.cs.meta b/Runtime/UI/TmpText/TMPHyperlinkReceiver.cs.meta new file mode 100644 index 0000000..9fefeac --- /dev/null +++ b/Runtime/UI/TmpText/TMPHyperlinkReceiver.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bb6cf745165c40f4ad82a5303ec21696 +timeCreated: 1750765466 \ No newline at end of file diff --git a/Runtime/XericLayout.dll b/Runtime/XericLayout.dll deleted file mode 100644 index a4af84d..0000000 Binary files a/Runtime/XericLayout.dll and /dev/null differ diff --git a/Runtime/XericLayout.dll.meta b/Runtime/XericLayout.dll.meta deleted file mode 100644 index 5caeed0..0000000 --- a/Runtime/XericLayout.dll.meta +++ /dev/null @@ -1,33 +0,0 @@ -fileFormatVersion: 2 -guid: 3f1521b0317329a40980ac84e1253425 -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 1 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - Any: - second: - enabled: 1 - settings: {} - - first: - Editor: Editor - second: - enabled: 0 - settings: - DefaultValueInitialized: true - - first: - Windows Store Apps: WindowsStoreApps - second: - enabled: 0 - settings: - CPU: AnyCPU - userData: - assetBundleName: - assetBundleVariant: diff --git a/Runtime/XericLibrary.dll b/Runtime/XericLibrary.dll index 339a02c..5ea1454 100644 Binary files a/Runtime/XericLibrary.dll and b/Runtime/XericLibrary.dll differ diff --git a/ConfigUIElement/Scripts/Element.meta b/Runtime/XericLibrary.pdb.meta similarity index 67% rename from ConfigUIElement/Scripts/Element.meta rename to Runtime/XericLibrary.pdb.meta index c557d15..c6ba7a2 100644 --- a/ConfigUIElement/Scripts/Element.meta +++ b/Runtime/XericLibrary.pdb.meta @@ -1,6 +1,5 @@ fileFormatVersion: 2 -guid: d98e03d6c3f900341838908516882fd0 -folderAsset: yes +guid: 5f497a3b416599744ba515971811704f DefaultImporter: externalObjects: {} userData: