2025-04-10 15:32:00 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Reflection;
|
2025-09-26 09:58:51 +08:00
|
|
|
|
using Deconstruction.UI.Interface;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
using TMPro;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.Events;
|
2025-09-26 09:58:51 +08:00
|
|
|
|
using UnityEngine.Pool;
|
|
|
|
|
|
using UnityEngine.Serialization;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
|
using XericLibrary.Runtime.CustomEditor;
|
2025-06-07 10:48:24 +08:00
|
|
|
|
|
|
|
|
|
|
#if ODIN_INSPECTOR
|
2025-04-10 15:32:00 +08:00
|
|
|
|
using Sirenix.OdinInspector;
|
2025-06-07 10:48:24 +08:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if UNITY_EDITOR && ODIN_INSPECTOR
|
2025-04-10 15:32:00 +08:00
|
|
|
|
using Sirenix.Utilities.Editor;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2025-06-07 10:48:24 +08:00
|
|
|
|
using Object = UnityEngine.Object;
|
|
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
namespace XericLibrary.Runtime.MacroLibrary
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// UI相关的扩展
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static class MacroUI
|
|
|
|
|
|
{
|
|
|
|
|
|
#region toggle 扩展
|
|
|
|
|
|
|
2025-05-24 16:01:59 +08:00
|
|
|
|
private static FieldInfo togglesFieldInfo = typeof(ToggleGroup).GetField("m_Toggles",
|
|
|
|
|
|
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
2025-04-10 15:32:00 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取给定单选项组中的所有单选项目
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <code>
|
|
|
|
|
|
/// 注意:操作具有一定的危险性,你可以自行制作这个列表对象的拷贝,但注意不要直接对返回的列表对象进行操作。
|
|
|
|
|
|
/// </code>
|
|
|
|
|
|
/// <param name="toggleGroup"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
/// <exception cref="ArgumentNullException"></exception>
|
|
|
|
|
|
/// <exception cref="InvalidOperationException"></exception>
|
|
|
|
|
|
/// <exception cref="InvalidCastException"></exception>
|
2025-04-10 15:32:00 +08:00
|
|
|
|
public static List<Toggle> GetToggles(this ToggleGroup toggleGroup)
|
|
|
|
|
|
{
|
2025-05-24 16:01:59 +08:00
|
|
|
|
if (toggleGroup == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new ArgumentNullException(nameof(toggleGroup));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (togglesFieldInfo == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new InvalidOperationException("Unable to access the 'm_Toggles' field.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var toggles = togglesFieldInfo.GetValue(toggleGroup) as List<Toggle>;
|
|
|
|
|
|
if (toggles == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new InvalidCastException("The 'm_Toggles' field is not of type List<Toggle>.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return toggles;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
// return (List<Toggle>)togglesFieldInfo.GetValue(toggleGroup);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取当前单选项组中激活的索引
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="toggleGroup"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
[Obsolete("索引依赖单选项自身在大纲中的顺序,在运行时顺序可能与编辑时不一致,请使用ToggleMapping")]
|
|
|
|
|
|
public static int GetActiveToggleIndex(this ToggleGroup toggleGroup)
|
|
|
|
|
|
{
|
|
|
|
|
|
var index = -1;
|
|
|
|
|
|
foreach (var toggle in toggleGroup.GetToggles())
|
|
|
|
|
|
{
|
|
|
|
|
|
index++;
|
|
|
|
|
|
if (toggle.isOn)
|
|
|
|
|
|
return index;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取当前单选项组的数量
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="toggleGroup"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static int GetToggleCount(this ToggleGroup toggleGroup)
|
|
|
|
|
|
{
|
|
|
|
|
|
return toggleGroup.GetToggles().Count;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 在单选项组上注册一个事件,当组中的任意成员变成激活状态时调用(其他的不会发生调用)。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="toggleGroup"></param>
|
|
|
|
|
|
/// <param name="onToggleChange"></param>
|
|
|
|
|
|
public static void OnToggleGroupChangeEvent(this ToggleGroup toggleGroup, Action<Toggle> onToggleChange)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var toggle in toggleGroup.GetToggles())
|
|
|
|
|
|
{
|
|
|
|
|
|
toggle.onValueChanged.AddListener(a =>
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!a) return;
|
|
|
|
|
|
onToggleChange?.Invoke(toggle);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 清空单选项组中的所有事件(与注册所有事件对应,但那个事件没法单独注销)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="toggleGroup"></param>
|
|
|
|
|
|
public static void RemoveToggleGroupChangeEvent(this ToggleGroup toggleGroup)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var toggle in toggleGroup.GetToggles())
|
|
|
|
|
|
{
|
|
|
|
|
|
toggle.onValueChanged.RemoveAllListeners();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
#region toggle 索引
|
|
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
[Serializable]
|
|
|
|
|
|
public class ToggleValueMapping<T> : ToggleMapping
|
|
|
|
|
|
{
|
|
|
|
|
|
#region 事件委托
|
|
|
|
|
|
|
|
|
|
|
|
public Action<Toggle, T> OnAnyToggleValueSwitchOn;
|
2025-11-10 11:53:03 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
#endregion
|
2025-11-10 11:53:03 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
#region 字段属性
|
|
|
|
|
|
|
|
|
|
|
|
#if ODIN_INSPECTOR
|
|
|
|
|
|
[SerializeField, LabelText("编辑单选项目值")]
|
|
|
|
|
|
#endif
|
|
|
|
|
|
private List<T> toggleValue;
|
2025-11-10 11:53:03 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
public override void BakeToggleGroupItems()
|
|
|
|
|
|
{
|
|
|
|
|
|
base.BakeToggleGroupItems();
|
|
|
|
|
|
if (toggleValue is not { Count: > 0 } || toggleValue.Count != toggleList.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
toggleValue = new List<T>();
|
|
|
|
|
|
for (var i = 0; i < toggleList.Count; i++)
|
|
|
|
|
|
toggleValue.Add(default(T));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public T GetValueByIndex(int index)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (toggleValue is not { Count: > 0 } || index < 0 || index >= toggleValue.Count)
|
|
|
|
|
|
return default;
|
|
|
|
|
|
return toggleValue[index];
|
|
|
|
|
|
}
|
2025-11-10 11:53:03 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
protected override void ToggleRegister(Toggle t)
|
|
|
|
|
|
{
|
|
|
|
|
|
base.ToggleRegister(t);
|
|
|
|
|
|
OnAnyToggleValueSwitchOn?.Invoke(t, GetValueByIndex(GetIndex(t)));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-10 11:53:03 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// toggle映射集
|
|
|
|
|
|
/// <code>
|
|
|
|
|
|
/// toggle映射集必须使用unity序列化管理,否则和直接使用toggleGroup没区别,目的是解决toggleGroup在打包后大纲视图的索引可能发生错位的问题。
|
|
|
|
|
|
/// </code>
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Serializable]
|
2025-09-26 09:58:51 +08:00
|
|
|
|
public class ToggleMapping : IEnumerable<Toggle>, IHierarchyControl
|
2025-04-10 15:32:00 +08:00
|
|
|
|
{
|
|
|
|
|
|
#region 事件委托
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 在单选项目切换时产生回调,返回选中的单选项目在组中的引用
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public Action<Toggle> OnAnyToggleSwitchOn;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 在单选项目切换时产生回调,返回选中的单选项目在组中的索引
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public Action<int> OnAnyToggleIndexSwitchOn;
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 字段属性
|
2025-09-26 09:58:51 +08:00
|
|
|
|
|
2025-06-07 10:48:24 +08:00
|
|
|
|
#if ODIN_INSPECTOR
|
2025-09-26 09:58:51 +08:00
|
|
|
|
[LabelText("单选组")]
|
2025-06-07 10:48:24 +08:00
|
|
|
|
#endif
|
|
|
|
|
|
public ToggleGroup ToggleGroup;
|
2025-09-26 09:58:51 +08:00
|
|
|
|
#if ODIN_INSPECTOR
|
|
|
|
|
|
[LabelText("编辑单选项目顺序")]
|
2025-06-07 10:48:24 +08:00
|
|
|
|
#endif
|
2025-09-26 09:58:51 +08:00
|
|
|
|
[SerializeField]
|
|
|
|
|
|
protected List<Toggle> toggleList = new List<Toggle>();
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
protected bool ToggleListInvalid => toggleList is not { Count: > 0 };
|
2025-11-10 11:53:03 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
public List<Toggle> ToggleList
|
|
|
|
|
|
{
|
|
|
|
|
|
get
|
|
|
|
|
|
{
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
|
if (!Application.isPlaying)
|
|
|
|
|
|
return toggleList;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
if (_mappingDirty || ToggleListInvalid)
|
|
|
|
|
|
{
|
|
|
|
|
|
BakeToggleGroupItems();
|
|
|
|
|
|
_mappingDirty = false;
|
|
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
if (_noInit)
|
|
|
|
|
|
{
|
2026-02-27 08:58:00 +08:00
|
|
|
|
_noInit = false;
|
2025-09-26 09:58:51 +08:00
|
|
|
|
Initialize();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return toggleList;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
2025-09-26 09:58:51 +08:00
|
|
|
|
/// 获取索引下的单选项组件
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// </summary>
|
2025-09-26 09:58:51 +08:00
|
|
|
|
/// <param name="index"></param>
|
|
|
|
|
|
public Toggle this[int index] => ToggleList[index];
|
|
|
|
|
|
|
|
|
|
|
|
public int Count => ToggleList.Count;
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
2025-09-26 09:58:51 +08:00
|
|
|
|
/// 直接获取缓存选中索引
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// </summary>
|
2025-09-26 09:58:51 +08:00
|
|
|
|
public int CurrentSelectIndex => _nowSelectToggleIndex;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 选中项目实例
|
|
|
|
|
|
/// </summary>
|
2025-11-10 11:53:03 +08:00
|
|
|
|
public Toggle CurrentSelectToggle => _nowSelectToggleIndex < 0 || _nowSelectToggleIndex > ToggleList.Count
|
|
|
|
|
|
? null
|
|
|
|
|
|
: ToggleList[_nowSelectToggleIndex];
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
2025-09-26 09:58:51 +08:00
|
|
|
|
/// 允许清空选项的选中状态
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// </summary>
|
2025-09-26 09:58:51 +08:00
|
|
|
|
public bool AllowSwitchOff
|
2025-04-10 15:32:00 +08:00
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
get => ToggleGroup.allowSwitchOff;
|
|
|
|
|
|
set => ToggleGroup.allowSwitchOff = value;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
2025-11-10 11:53:03 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
// 映射关系脏
|
|
|
|
|
|
private bool _mappingDirty = false;
|
|
|
|
|
|
|
|
|
|
|
|
// 未初始化
|
|
|
|
|
|
private bool _noInit = true;
|
|
|
|
|
|
|
|
|
|
|
|
// 当前选中的项目
|
|
|
|
|
|
private int _nowSelectToggleIndex = -1;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
|
2025-11-10 11:53:03 +08:00
|
|
|
|
// 在任意选项选中时复位允许反选toggle的功能
|
|
|
|
|
|
private bool _resetAllowToggleOffAtAnyIsOn;
|
|
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
#region 结构更新
|
2025-04-10 15:32:00 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-09-26 09:58:51 +08:00
|
|
|
|
/// 烘焙单选项组
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// </summary>
|
2025-09-26 09:58:51 +08:00
|
|
|
|
/// <code>
|
|
|
|
|
|
/// 注意不要再这里面使用ToggleList
|
|
|
|
|
|
/// </code>
|
|
|
|
|
|
#if ODIN_INSPECTOR
|
|
|
|
|
|
[HorizontalGroup("GetGroup"), Button("GetGroup")]
|
|
|
|
|
|
#endif
|
|
|
|
|
|
public virtual void BakeToggleGroupItems()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ToggleGroup == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ToggleListInvalid)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError("未指定单选项目组中的任何引用成员,无法初始化");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-04-10 15:32:00 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
var validToggle = toggleList.FirstOrDefault(a => a.group != null);
|
|
|
|
|
|
if (validToggle != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
ToggleGroup = validToggle.group;
|
|
|
|
|
|
Debug.LogWarning("未指定单选项目组中的任何引用成员,但使用成员代偿");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError("未指定单选项目组中的任何引用成员,且无法利用成员代偿");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-10 15:32:00 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
List<Toggle> tempToggleList = null;
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
|
if (!Application.isPlaying)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!ToggleGroup.gameObject.activeInHierarchy)
|
|
|
|
|
|
{
|
|
|
|
|
|
var tempParents = ToggleGroup.transform.GetParents()
|
|
|
|
|
|
.Select(a => a.GetActivity()).ToList();
|
|
|
|
|
|
ToggleGroup.gameObject.SetActivityInHierarchy(true);
|
|
|
|
|
|
tempToggleList = ToggleGroup.GetToggles();
|
|
|
|
|
|
ToggleGroup.transform.GetParents()
|
|
|
|
|
|
.Zip(tempParents, (go, act) => (go, act))
|
|
|
|
|
|
.ForEachDo(a => a.go.SetActivity(a.act));
|
|
|
|
|
|
if (tempToggleList is not { Count: > 0 })
|
|
|
|
|
|
Debug.LogError("无法获取ToggleGroup中的成员,可能由于toggleGroup被隐藏导致其无法初始化");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
tempToggleList = ToggleGroup.GetToggles();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
#endif
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!ToggleGroup.gameObject.activeInHierarchy && ToggleListInvalid)
|
|
|
|
|
|
Debug.LogError(
|
|
|
|
|
|
$"当前运行状态导致无法直接获取ToggleGroup中的成员,且运行时我无法自行决定目标ToggleGroup({ToggleGroup.name})所属生命周期,请提前在编辑器中对相关状态进行烘焙");
|
|
|
|
|
|
else
|
|
|
|
|
|
tempToggleList = ToggleGroup.GetToggles();
|
|
|
|
|
|
}
|
2025-11-10 11:53:03 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
// 需要注意的是,这里不能随意释放掉原来的选项列表
|
|
|
|
|
|
if (tempToggleList is { Count: > 0 })
|
|
|
|
|
|
toggleList = tempToggleList;
|
|
|
|
|
|
}
|
|
|
|
|
|
#if ODIN_INSPECTOR
|
|
|
|
|
|
[HorizontalGroup("GetGroup"), Button("GetGroup(Sort)")]
|
|
|
|
|
|
#endif
|
|
|
|
|
|
public void BakeSortToggelGroupItems()
|
2025-04-10 15:32:00 +08:00
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
BakeToggleGroupItems();
|
|
|
|
|
|
if (ToggleListInvalid)
|
|
|
|
|
|
toggleList = MacroSort.FullCharacterOrderSort(toggleList, a => a.name)
|
|
|
|
|
|
.ToList();
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
2025-09-26 09:58:51 +08:00
|
|
|
|
#if ODIN_INSPECTOR
|
|
|
|
|
|
[HorizontalGroup("GetGroup"), Button("GetGroup(Reverse Sort)")]
|
|
|
|
|
|
#endif
|
|
|
|
|
|
public void BakeReverseSortToggelGroupItems()
|
2025-04-10 15:32:00 +08:00
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
BakeToggleGroupItems();
|
|
|
|
|
|
if (ToggleListInvalid)
|
|
|
|
|
|
toggleList = MacroSort.FullCharacterOrderSort(toggleList, a => a.name)
|
|
|
|
|
|
.Reverse()
|
|
|
|
|
|
.ToList();
|
|
|
|
|
|
}
|
|
|
|
|
|
#if ODIN_INSPECTOR
|
2025-11-10 11:53:03 +08:00
|
|
|
|
[HorizontalGroup("GetGroup"), Button("SaveGroup")] [DisableInEditorMode]
|
2025-09-26 09:58:51 +08:00
|
|
|
|
#endif
|
2025-11-10 11:53:03 +08:00
|
|
|
|
[Obsolete("正常流程单选项组中的标签已经呈现了必要对象,无需重新设置")]
|
2025-09-26 09:58:51 +08:00
|
|
|
|
public void SetToggelGroupItems()
|
|
|
|
|
|
{
|
2025-11-10 11:53:03 +08:00
|
|
|
|
if (!ToggleGroup.gameObject.activeInHierarchy)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning("编组尚未激活,成员与实际可能存在差异。");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-09-26 09:58:51 +08:00
|
|
|
|
var realToggleGroup = ToggleGroup.GetToggles();
|
|
|
|
|
|
if (ToggleListInvalid || toggleList.Count != realToggleGroup.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError("编组无效,或编组成员与实际不符");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
Debug.Log("编组设置成功");
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Initialize()
|
|
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
// 啥也没有,压根没用这部分功能,用不着初始化。
|
|
|
|
|
|
if (ToggleGroup == null && toggleList.Count <= 0)
|
2025-04-10 15:32:00 +08:00
|
|
|
|
return;
|
2025-09-26 09:58:51 +08:00
|
|
|
|
// 防呆
|
2025-04-10 15:32:00 +08:00
|
|
|
|
if (toggleList.Count <= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var toggles = ToggleGroup.GetToggles();
|
|
|
|
|
|
if (toggles.Count != toggleList.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
toggleList = toggles;
|
|
|
|
|
|
Debug.LogWarning($"在初始化单选项组时,{ToggleGroup.name}并未预先指定索引顺序,将默认使用大纲顺序。");
|
|
|
|
|
|
}
|
2025-09-26 09:58:51 +08:00
|
|
|
|
|
|
|
|
|
|
if (toggles.Count <= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogWarning("在初始化单选项组时,目标单选项组为空");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 防空
|
|
|
|
|
|
toggleList = toggleList.Where(a => a != null).ToList();
|
|
|
|
|
|
|
|
|
|
|
|
// 防傻
|
|
|
|
|
|
if (ToggleGroup == null)
|
|
|
|
|
|
ToggleGroup = toggleList.FirstOrDefault(a => a.group != null)?.group;
|
|
|
|
|
|
if (ToggleGroup == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
ToggleGroup = toggleList[0].transform.parent.gameObject.AddComponent<ToggleGroup>();
|
|
|
|
|
|
foreach (var toggle in toggleList)
|
|
|
|
|
|
toggle.group = ToggleGroup;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
// 事件初始化
|
2025-09-26 09:58:51 +08:00
|
|
|
|
for (var i = 0; i < toggleList.Count; i++)
|
2025-04-10 15:32:00 +08:00
|
|
|
|
{
|
|
|
|
|
|
var toggle = toggleList[i];
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
ToggleAddEvent(toggle);
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
if (_nowSelectToggleIndex < 0 && toggle.isOn)
|
|
|
|
|
|
_nowSelectToggleIndex = i;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
if (_noInit)
|
2026-02-27 08:58:00 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 如果不允许为空的情况下还为空,那就默认标记一个
|
|
|
|
|
|
if (!ToggleGroup.allowSwitchOff && _nowSelectToggleIndex < 0)
|
|
|
|
|
|
SetToggleOnWithoutNotify(0);
|
2025-09-26 09:58:51 +08:00
|
|
|
|
SetToggelGroupItems();
|
2026-02-27 08:58:00 +08:00
|
|
|
|
}
|
2025-11-10 11:53:03 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
_mappingDirty = false;
|
|
|
|
|
|
_noInit = false;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 初始化 和 增删改查
|
|
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 添加一个toggle
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="t"></param>
|
|
|
|
|
|
/// <returns>返回toggle的索引</returns>
|
|
|
|
|
|
public int AddToggle(Toggle t)
|
|
|
|
|
|
{
|
|
|
|
|
|
ToggleAddEvent(t);
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
var resultIndex = ToggleList.Count;
|
|
|
|
|
|
ToggleList.Add(t);
|
2025-04-10 15:32:00 +08:00
|
|
|
|
return resultIndex;
|
|
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 移除一个toggle,这不会影响其他toggle的索引,但此处移除的位置会为空。
|
|
|
|
|
|
/// <code>
|
2025-09-26 09:58:51 +08:00
|
|
|
|
/// 注意mapping管理的toggle在移除后会被清空事件
|
|
|
|
|
|
/// 此举这不会销毁toggle。
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// </code>
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="t"></param>
|
|
|
|
|
|
/// <returns>是否成功移除toggle</returns>
|
|
|
|
|
|
public bool RemoveToggle(Toggle t)
|
|
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
var index = ToggleList.IndexOf(t);
|
2025-04-10 15:32:00 +08:00
|
|
|
|
if (index < 0)
|
|
|
|
|
|
return false;
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
|
|
|
|
|
t.onValueChanged.RemoveAllListeners();
|
2025-09-26 09:58:51 +08:00
|
|
|
|
ToggleList[index] = null;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 清除toggle
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="allowDestroy">是否同时销毁所有toggle</param>
|
|
|
|
|
|
public void CleanToggle(bool allowDestroy)
|
|
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
foreach (var t in ToggleList)
|
2025-04-10 15:32:00 +08:00
|
|
|
|
{
|
|
|
|
|
|
t.onValueChanged.RemoveAllListeners();
|
|
|
|
|
|
if (allowDestroy)
|
|
|
|
|
|
Object.Destroy(t);
|
|
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
ToggleList.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 事件流程
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 强制标记映射关系脏,在下次运行时将自动按需更新
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void SetDirty()
|
|
|
|
|
|
{
|
|
|
|
|
|
_mappingDirty = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 查找当前选中实例在列表中的索引位置
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public int CurrentSelectToggleIndex()
|
|
|
|
|
|
{
|
|
|
|
|
|
for (var i = 0; i < ToggleList.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!ToggleList[i].isOn) continue;
|
|
|
|
|
|
_nowSelectToggleIndex = i;
|
|
|
|
|
|
return _nowSelectToggleIndex;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return -1;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// toggle注册的事件,只有当按下时才需要调用此事件。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="t"></param>
|
|
|
|
|
|
private void ToggleAddEvent(Toggle t)
|
|
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
t.onValueChanged.RemoveListener(Listener);
|
|
|
|
|
|
t.onValueChanged.AddListener(Listener);
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
void Listener(bool b)
|
2025-04-10 15:32:00 +08:00
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
if (b) ToggleRegister(t);
|
|
|
|
|
|
}
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// toggle注册的事件,只有当按下时才需要调用此事件。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="t"></param>
|
2025-09-26 09:58:51 +08:00
|
|
|
|
protected virtual void ToggleRegister(Toggle t)
|
2025-04-10 15:32:00 +08:00
|
|
|
|
{
|
2025-11-10 11:53:03 +08:00
|
|
|
|
TryResetToggleGroupAutoOff();
|
2025-09-26 09:58:51 +08:00
|
|
|
|
_nowSelectToggleIndex = GetIndex(t);
|
2025-04-10 15:32:00 +08:00
|
|
|
|
OnAnyToggleSwitchOn?.Invoke(t);
|
2025-09-26 09:58:51 +08:00
|
|
|
|
OnAnyToggleIndexSwitchOn?.Invoke(_nowSelectToggleIndex);
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取toggle代表的索引
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="target"></param>
|
|
|
|
|
|
/// <returns>如果这个toggle不存在于当前的单选项组中,返回-1</returns>
|
|
|
|
|
|
public int GetIndex(Toggle target)
|
|
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
if (target == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError("无法查询空toggle的索引");
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var index = ToggleList.IndexOf(target);
|
|
|
|
|
|
if (index >= 0)
|
|
|
|
|
|
return index;
|
|
|
|
|
|
Debug.LogError($"无法查询 {target.name} 在当前单选项组中的索引。");
|
|
|
|
|
|
return 0;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取toggle代表的索引, 如果toggle不存在于这个映射集中,将返回否
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="target"></param>
|
|
|
|
|
|
/// <param name="index"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public bool TryGetIndex(Toggle target, out int index)
|
|
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
index = ToggleList.IndexOf(target);
|
2025-04-10 15:32:00 +08:00
|
|
|
|
return index >= 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置单选项激活
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="target"></param>
|
|
|
|
|
|
public void SetToggleOn(Toggle target)
|
|
|
|
|
|
{
|
|
|
|
|
|
target.isOn = true;
|
2025-11-10 11:53:03 +08:00
|
|
|
|
TryResetToggleGroupAutoOff();
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置单选项激活
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="index"></param>
|
|
|
|
|
|
public void SetToggleOn(int index)
|
|
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
if (0 <= index && index < ToggleList.Count)
|
2025-04-10 15:32:00 +08:00
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
SetToggleOn(ToggleList[index]);
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置单选项激活
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="target"></param>
|
|
|
|
|
|
public void SetToggleOnWithoutNotify(Toggle target)
|
|
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
_nowSelectToggleIndex = GetIndex(target);
|
2025-11-10 11:53:03 +08:00
|
|
|
|
TryResetToggleGroupAutoOff();
|
2025-04-10 15:32:00 +08:00
|
|
|
|
target.SetIsOnWithoutNotify(true);
|
|
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置单选项激活
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="index"></param>
|
|
|
|
|
|
public void SetToggleOnWithoutNotify(int index)
|
|
|
|
|
|
{
|
2025-11-10 11:53:03 +08:00
|
|
|
|
if (0 <= index && index < ToggleList.Count)
|
2025-04-10 15:32:00 +08:00
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
SetToggleOnWithoutNotify(ToggleList[index]);
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-11-10 11:53:03 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 将整个单选项组复位,这同时会标记单选项组上的允许取消操作。
|
|
|
|
|
|
/// 在下次选中标签时,会自动复位这个标记,确保全部反选的状态仅出现一次。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
#if ODIN_INSPECTOR
|
|
|
|
|
|
[Button("ResetAllToggleOff")]
|
|
|
|
|
|
#endif
|
|
|
|
|
|
public void ResetGroupAllToggleOff()
|
|
|
|
|
|
{
|
|
|
|
|
|
_nowSelectToggleIndex = -1;
|
|
|
|
|
|
if (ToggleGroup == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError("单选项组不存在...");
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!ToggleGroup.allowSwitchOff)
|
|
|
|
|
|
{
|
|
|
|
|
|
_resetAllowToggleOffAtAnyIsOn = true;
|
|
|
|
|
|
ToggleGroup.allowSwitchOff = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
ToggleList.ForEachDo(a => a.SetIsOnWithoutNotify(false));
|
|
|
|
|
|
}
|
2025-04-10 15:32:00 +08:00
|
|
|
|
|
2025-11-10 11:53:03 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 如果此次按下是发生在全部反选之后的首次操作,那么关闭允许关闭的操作。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void TryResetToggleGroupAutoOff()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_resetAllowToggleOffAtAnyIsOn)
|
|
|
|
|
|
{
|
|
|
|
|
|
_resetAllowToggleOffAtAnyIsOn = false;
|
|
|
|
|
|
ToggleGroup.allowSwitchOff = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 清除映射结构(不会清除toggle实例)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void Clear()
|
|
|
|
|
|
{
|
|
|
|
|
|
ToggleGroup.RemoveToggleGroupChangeEvent();
|
2025-09-26 09:58:51 +08:00
|
|
|
|
ToggleList.Clear();
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 清除映射结构,并销毁所有toggle组件
|
|
|
|
|
|
/// </summary>
|
2025-09-26 09:58:51 +08:00
|
|
|
|
public void DestroyAllToggle()
|
2025-04-10 15:32:00 +08:00
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
for (int i = ToggleList.Count - 1; i >= 0; i--)
|
2025-04-10 15:32:00 +08:00
|
|
|
|
{
|
2025-09-26 09:58:51 +08:00
|
|
|
|
Object.Destroy(ToggleList[i]);
|
2025-04-10 15:32:00 +08:00
|
|
|
|
}
|
2025-05-24 16:01:59 +08:00
|
|
|
|
|
2025-04-10 15:32:00 +08:00
|
|
|
|
Clear();
|
|
|
|
|
|
}
|
2025-11-10 11:53:03 +08:00
|
|
|
|
|
2025-09-26 09:58:51 +08:00
|
|
|
|
|
|
|
|
|
|
public IEnumerator<Toggle> GetEnumerator()
|
|
|
|
|
|
{
|
|
|
|
|
|
return ToggleList.GetEnumerator();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
|
|
|
|
{
|
|
|
|
|
|
return GetEnumerator();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 额外方法
|
|
|
|
|
|
|
|
|
|
|
|
public bool GetActive() => ToggleList.Any(a => a.gameObject.activeSelf);
|
|
|
|
|
|
|
|
|
|
|
|
public bool GetActiveInHierarchy() => ToggleList.Any(a => a.gameObject.activeInHierarchy);
|
|
|
|
|
|
|
|
|
|
|
|
public void SetActive(bool active)
|
|
|
|
|
|
{
|
|
|
|
|
|
ToggleGroup.gameObject.SetActivity(active);
|
|
|
|
|
|
ToggleList.ForEachDo(a => a.gameObject.SetActive(active));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void SetActiveInHierarchy(bool active)
|
|
|
|
|
|
{
|
|
|
|
|
|
ToggleGroup.gameObject.SetActivity(active);
|
|
|
|
|
|
ToggleList.ForEachDo(a => a.gameObject.SetActivityInHierarchy(active));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 过时
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 清除映射结构,并销毁所有toggle组件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Obsolete("方法命名不规范,改为使用DestroyAllToggle")]
|
|
|
|
|
|
public void RemoveAllToggle()
|
|
|
|
|
|
=> DestroyAllToggle();
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 当前选中的toggle索引,依赖缓存,对于绕过该容器的单选项控制行为可能存在追踪不准确的问题。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Obsolete("命名过时")]
|
|
|
|
|
|
public int NowSelectToggleIndex => CurrentSelectIndex;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 当前选中的toggle
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
[Obsolete("命名规范过时")]
|
|
|
|
|
|
public Toggle NowSelectToggle => CurrentSelectToggle;
|
2025-04-10 15:32:00 +08:00
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 按钮扩展
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 所有按钮注册一个事件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="buttons"></param>
|
|
|
|
|
|
/// <param name="targetEvent"></param>
|
|
|
|
|
|
public static void RegisterOnClickEvent(this IEnumerable<Button> buttons, UnityAction targetEvent)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var button in buttons)
|
|
|
|
|
|
{
|
|
|
|
|
|
button.onClick.AddListener(targetEvent);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 所有按钮注销一个事件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="buttons"></param>
|
|
|
|
|
|
/// <param name="targetEvent"></param>
|
|
|
|
|
|
public static void LogoutOnClickEvent(this IEnumerable<Button> buttons, UnityAction targetEvent)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var button in buttons)
|
|
|
|
|
|
{
|
|
|
|
|
|
button.onClick.RemoveListener(targetEvent);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置所有按钮的可交互性
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="buttons"></param>
|
|
|
|
|
|
/// <param name="interactable"></param>
|
|
|
|
|
|
public static void SetButtonInteractable(this IEnumerable<Button> buttons, bool interactable)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var button in buttons)
|
|
|
|
|
|
{
|
|
|
|
|
|
button.interactable = interactable;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 文本组件扩展
|
|
|
|
|
|
|
|
|
|
|
|
public static void SetText(this IEnumerable<TextMeshProUGUI> texts, string text)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var t in texts)
|
|
|
|
|
|
{
|
|
|
|
|
|
t.text = text;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region UI变换获取扩展
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 获取一个组件的矩形变换组件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="target"></param>
|
|
|
|
|
|
/// <typeparam name="T"></typeparam>
|
|
|
|
|
|
/// <returns></returns>
|
2025-05-24 16:01:59 +08:00
|
|
|
|
public static RectTransform RectTransform<T>(this T target)
|
|
|
|
|
|
where T : Component
|
2025-04-10 15:32:00 +08:00
|
|
|
|
=> target.transform as RectTransform;
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|