2026-06-09 01:43:55 -04:00
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
|
|
|
|
using DG.Tweening;
|
|
|
|
|
|
using Ichni.RhythmGame;
|
|
|
|
|
|
using TMPro;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using UnityEngine.Events;
|
|
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Ichni.Editor
|
|
|
|
|
|
{
|
|
|
|
|
|
public abstract class DynamicUIElement : MonoBehaviour
|
|
|
|
|
|
{
|
|
|
|
|
|
Inspector Inspector => EditorManager.instance.uiManager.inspector;
|
|
|
|
|
|
|
|
|
|
|
|
public TMP_Text title;
|
|
|
|
|
|
public CanvasGroup canvasGroup;
|
|
|
|
|
|
public IBaseElement connectedBaseElement;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 参数名,通过反射获取饿修改对应变量的值
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public string parameterName;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 缓存的 LayoutElement,用于 InspectorBuilder 的 Flexible 布局模式。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private LayoutElement _layoutElement;
|
|
|
|
|
|
|
|
|
|
|
|
public virtual void Initialize(IBaseElement baseElement, string title, string parameterName)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (canvasGroup == null) canvasGroup = gameObject.AddComponent<CanvasGroup>();
|
2026-06-09 07:00:19 -04:00
|
|
|
|
|
|
|
|
|
|
// [对象池安全] 重置 CanvasGroup 状态,防止上次 EnabledIf 设置的禁用状态泄漏到新的元素实例
|
|
|
|
|
|
canvasGroup.interactable = true;
|
|
|
|
|
|
canvasGroup.alpha = 1f;
|
|
|
|
|
|
canvasGroup.blocksRaycasts = true;
|
|
|
|
|
|
|
2026-06-09 01:43:55 -04:00
|
|
|
|
this.connectedBaseElement = baseElement;
|
|
|
|
|
|
this.parameterName = parameterName;
|
|
|
|
|
|
if (title != string.Empty)
|
|
|
|
|
|
{
|
2026-06-09 07:00:19 -04:00
|
|
|
|
// [对象池安全] 确保标题 GameObject 处于激活状态,
|
|
|
|
|
|
// 防止上次以空标题使用时 SetActive(false) 的状态泄漏
|
|
|
|
|
|
this.title.gameObject.SetActive(true);
|
2026-06-09 01:43:55 -04:00
|
|
|
|
this.title.text = title;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
this.title.gameObject.SetActive(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public DynamicUIElement Mark(string mark = "Default", IHaveInspection inspection = null)
|
|
|
|
|
|
{
|
|
|
|
|
|
inspection ??= Inspector;
|
|
|
|
|
|
if (mark == "Default")
|
|
|
|
|
|
{
|
|
|
|
|
|
mark = title.text;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inspection.MarkedElements.TryAdd(mark, this);
|
|
|
|
|
|
return this;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 设置此元素在 Flexible 布局中的尺寸。
|
|
|
|
|
|
/// 由 InspectorBuilder 或 Drawer 在元素创建后调用。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void SetLayoutSize(float preferredWidth, float preferredHeight)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (_layoutElement == null)
|
|
|
|
|
|
_layoutElement = GetComponent<LayoutElement>();
|
|
|
|
|
|
if (_layoutElement == null)
|
|
|
|
|
|
_layoutElement = gameObject.AddComponent<LayoutElement>();
|
|
|
|
|
|
|
|
|
|
|
|
_layoutElement.preferredWidth = preferredWidth;
|
|
|
|
|
|
_layoutElement.preferredHeight = preferredHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 禁用指定 Selectable 组件的导航(统一处理,避免各 Generate 方法重复编写)。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static void DisableNavigation(Selectable selectable)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (selectable != null)
|
|
|
|
|
|
selectable.navigation = new Navigation { mode = Navigation.Mode.None };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 批量禁用多个 Selectable 的导航。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public static void DisableNavigation(params Selectable[] selectables)
|
|
|
|
|
|
{
|
|
|
|
|
|
var nav = new Navigation { mode = Navigation.Mode.None };
|
|
|
|
|
|
foreach (var s in selectables)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (s != null)
|
|
|
|
|
|
s.navigation = nav;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public abstract DynamicUIElement AddListenerFunction(UnityAction action);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public interface IHaveAutoUpdate
|
|
|
|
|
|
{
|
|
|
|
|
|
public bool isAutoUpdate { get; set; }
|
|
|
|
|
|
public bool isReceiving { get; set; }
|
|
|
|
|
|
public void SetAutoUpdate(bool enable);
|
|
|
|
|
|
|
|
|
|
|
|
public void UpdateContent()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isAutoUpdate && isReceiving)
|
|
|
|
|
|
{
|
|
|
|
|
|
ApplyContent();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void ApplyContent();
|
|
|
|
|
|
}
|
|
|
|
|
|
public interface IHaveTagLink
|
|
|
|
|
|
{
|
|
|
|
|
|
public IBaseElement connectedBaseElement { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
// public void GetApply()
|
|
|
|
|
|
// {
|
|
|
|
|
|
// EditorManager.instance.projectInformation.tagManager.SyncTagedElement(connectedBaseElement);
|
|
|
|
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|