This commit is contained in:
MuHua-123
2025-03-07 19:20:55 +08:00
parent c8f1873939
commit 5e819d5257
98 changed files with 389 additions and 180 deletions
@@ -8,7 +8,7 @@ namespace MuHua {
/// <summary>
/// UI项
/// </summary>
public abstract class UIItem<Data> {
public abstract class ModuleUIItem<Data> : ModuleUIPanel {
/// <summary> 选择事件 </summary>
public static event Action<Data> OnSelect;
/// <summary> 触发事件 </summary>
@@ -16,12 +16,9 @@ namespace MuHua {
/// <summary> 绑定的数据 </summary>
public readonly Data value;
/// <summary> 绑定的元素 </summary>
public readonly VisualElement element;
/// <summary> UI项 </summary>
public UIItem(Data value, VisualElement element) {
public ModuleUIItem(Data value, VisualElement element) : base(element) {
this.value = value;
this.element = element;
OnSelect += UIItem_OnSelect;
}
@@ -6,22 +6,20 @@ using UnityEngine.UIElements;
namespace MuHua {
/// <summary>
/// UI容器
/// UI容器
/// </summary>
public class UIContainer<Item, Data> where Item : UIItem<Data> {
public readonly VisualElement container;
public class ModuleUIItems<Item, Data> : ModuleUIPanel where Item : ModuleUIItem<Data> {
public readonly VisualTreeAsset templateAsset;
public readonly Func<Data, VisualElement, Item> generate;
public List<Item> uiItems = new List<Item>();
/// <summary> UI容器 </summary>
public UIContainer(VisualElement container, VisualTreeAsset templateAsset, Func<Data, VisualElement, Item> generate) {
this.container = container;
public ModuleUIItems(VisualElement element, VisualTreeAsset templateAsset, Func<Data, VisualElement, Item> generate) : base(element) {
this.templateAsset = templateAsset;
this.generate = generate;
}
/// <summary> 释放资源 </summary>
public void Release() {
container.Clear();
element.Clear();
uiItems.ForEach(obj => obj.Release());
uiItems = new List<Item>();
}
@@ -34,7 +32,7 @@ namespace MuHua {
public void Create(Data data) {
VisualElement element = templateAsset.Instantiate();
Item item = generate(data, element);
container.Add(item.element);
this.element.Add(item.element);
uiItems.Add(item);
}
}
@@ -0,0 +1,20 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
namespace MuHua {
/// <summary>
/// 页面模块
/// </summary>
public class ModuleUIPage : MonoBehaviour {
/// <summary> 绑定文档 </summary>
public UIDocument document;
/// <summary> 根目录文档 </summary>
public VisualElement root => document.rootVisualElement;
/// <summary> 添加UI元素 </summary>
public void Add(VisualElement child) => root.Add(child);
/// <summary> 查询UI元素 </summary>
public T Q<T>(string name = null, string className = null) where T : VisualElement => root.Q<T>(name, className);
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a20e816476c4c5d4b83e112be2e08697
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,16 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
namespace MuHua {
/// <summary>
/// UI控件
/// </summary>
public class ModuleUIPanel {
/// <summary> 绑定的元素 </summary>
public readonly VisualElement element;
/// <summary> UI控件 </summary>
public ModuleUIPanel(VisualElement element) => this.element = element;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 97e1bf60274de61419b2d9588340cafa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 90a36026f648a6f45add234bc15d5548
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,30 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
namespace MuHua {
public class UIFloatField : FloatField {
public new class UxmlFactory : UxmlFactory<UIFloatField, UxmlTraits> { }
public new class UxmlTraits : FloatField.UxmlTraits { }
public VisualElement inputElement;
public VisualElement textElement;
public UIFloatField() {
ClearClassList();
AddToClassList("input-field");
labelElement.ClearClassList();
labelElement.AddToClassList("unity-text-element");
labelElement.AddToClassList("input-field-label");
inputElement = this.Q<VisualElement>("unity-text-input");
inputElement.ClearClassList();
inputElement.AddToClassList("input-field-box");
textElement = inputElement.Q<VisualElement>("");
textElement.ClearClassList();
textElement.AddToClassList("unity-text-element");
textElement.AddToClassList("input-field-text");
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7046acdb2e5ef0c458969a4022ee9ab4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,28 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
namespace MuHua {
public class UILongField : LongField {
public new class UxmlFactory : UxmlFactory<UILongField, UxmlTraits> { }
public new class UxmlTraits : LongField.UxmlTraits { }
public UILongField() {
ClearClassList();
AddToClassList("input-field");
labelElement.ClearClassList();
labelElement.AddToClassList("unity-text-element");
labelElement.AddToClassList("input-field-label");
VisualElement inputElement = this.Q<VisualElement>("unity-text-input");
inputElement.ClearClassList();
inputElement.AddToClassList("input-field-box");
VisualElement textElement = inputElement.Q<VisualElement>("");
textElement.ClearClassList();
textElement.AddToClassList("unity-text-element");
textElement.AddToClassList("input-field-text");
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1d30b5caf969d9b4ab1464d329cf16ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,55 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
namespace MuHua {
public class UITextField : TextField {
public new class UxmlFactory : UxmlFactory<UITextField, UxmlTraits> { }
public new class UxmlTraits : TextField.UxmlTraits {
public UxmlStringAttributeDescription DefaultPrompt = new UxmlStringAttributeDescription {
name = "default-prompt"
};
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc) {
base.Init(ve, bag, cc);
UITextField textField = (UITextField)ve;
textField.DefaultPrompt = DefaultPrompt.GetValueFromBag(bag, cc);
textField.SetDefaultPrompt();
}
}
public string DefaultPrompt { get; set; }
public VisualElement inputElement => this.Q<VisualElement>("unity-text-input");
public VisualElement textElement => inputElement.Q<VisualElement>("");
public UITextField() {
ClearClassList();
AddToClassList("input-field");
labelElement.ClearClassList();
labelElement.AddToClassList("unity-text-element");
labelElement.AddToClassList("input-field-label");
inputElement.ClearClassList();
inputElement.AddToClassList("input-field-box");
textElement.ClearClassList();
textElement.AddToClassList("unity-text-element");
textElement.AddToClassList("input-field-text");
RegisterCallback<FocusInEvent>((evt) => { PrepareInput(); });
RegisterCallback<FocusOutEvent>((evt) => { SetDefaultPrompt(); });
}
public void PrepareInput() {
textElement.RemoveFromClassList("input-field-text-d");
if (text != DefaultPrompt) { return; }
text = "";
}
public void SetDefaultPrompt() {
textElement.RemoveFromClassList("input-field-text-d");
if (value != "") { return; }
text = DefaultPrompt;
textElement.AddToClassList("input-field-text-d");
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3bbf7cc5bf423304dbb4eac4f82b2bee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -8,9 +8,7 @@ namespace MuHua {
/// <summary>
/// 滚动视图
/// </summary>
public class UIScrollView {
/// <summary> 绑定的元素 </summary>
public readonly VisualElement element;
public class UIScrollView : ModuleUIPanel {
/// <summary> 绑定的画布 </summary>
public readonly VisualElement canvas;
/// <summary> 元素方向 </summary>
@@ -31,8 +29,8 @@ namespace MuHua {
public readonly VisualElement ScrollerHorizontal;
public readonly VisualElement ScrollerVertical;
public UIScrollView(VisualElement element, VisualElement canvas, UIDirection direction = UIDirection.HorizontalAndVertical, UIDirection sh = UIDirection.FromLeftToRight, UIDirection sv = UIDirection.FromTopToBottom) {
this.element = element;
public UIScrollView(VisualElement element, VisualElement canvas, UIDirection direction = UIDirection.HorizontalAndVertical,
UIDirection sh = UIDirection.FromLeftToRight, UIDirection sv = UIDirection.FromTopToBottom) : base(element) {
this.canvas = canvas;
this.direction = direction;
@@ -73,7 +71,8 @@ namespace MuHua {
float wheel = Mathf.Clamp(evt.delta.y, -1, 1);
if (direction == UIDirection.Horizontal) {
UpdateValue(new Vector2(value.x - wheel, value.y));
} else {
}
else {
UpdateValue(new Vector2(value.x, value.y - wheel));
}
}
@@ -8,9 +8,7 @@ namespace MuHua {
/// <summary>
/// 滚动条
/// </summary>
public class UIScroller {
/// <summary> 绑定的元素 </summary>
public readonly VisualElement element;
public class UIScroller : ModuleUIPanel {
/// <summary> 绑定的画布 </summary>
public readonly VisualElement canvas;
/// <summary> 元素方向 </summary>
@@ -27,8 +25,7 @@ namespace MuHua {
public readonly VisualElement Dragger;
public UIScroller(VisualElement element, VisualElement canvas, UIDirection direction = UIDirection.FromLeftToRight) {
this.element = element;
public UIScroller(VisualElement element, VisualElement canvas, UIDirection direction = UIDirection.FromLeftToRight) : base(element) {
this.canvas = canvas;
this.direction = direction;
@@ -8,9 +8,7 @@ namespace MuHua {
/// <summary>
/// 滑块
/// </summary>
public class UISlider {
/// <summary> 绑定的元素 </summary>
public readonly VisualElement element;
public class UISlider : ModuleUIPanel {
/// <summary> 绑定的画布 </summary>
public readonly VisualElement canvas;
/// <summary> 元素方向 </summary>
@@ -29,8 +27,7 @@ namespace MuHua {
public readonly VisualElement Tracker;
public readonly VisualElement Dragger;
public UISlider(VisualElement element, VisualElement canvas, UIDirection direction = UIDirection.FromLeftToRight) {
this.element = element;
public UISlider(VisualElement element, VisualElement canvas, UIDirection direction = UIDirection.FromLeftToRight) : base(element) {
this.canvas = canvas;
this.direction = direction;
@@ -0,0 +1,68 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
#if ENABLE_INPUT_SYSTEM && UNITY_INPUT_SYSTEM_PACKAGE
using UnityEngine.InputSystem;
#endif
namespace MuHua {
/// <summary>
/// 悬浮窗口
/// </summary>
public abstract class UIWindow : ModuleUIPanel {
/// <summary> 绑定的画布 </summary>
public readonly VisualElement canvas;
private bool isDownMove;
private Vector3 pointerPosition;
private Vector3 originalPosition;
public VisualElement Window => element.Q<VisualElement>("Window");
public VisualElement Top => element.Q<VisualElement>("Top");
public VisualElement Container => element.Q<VisualElement>("Container");
public Label Title => element.Q<Label>("Title");
public Button Close => element.Q<Button>("Close");
public UIWindow(VisualElement element, VisualElement canvas) : base(element) {
this.canvas = canvas;
Top.RegisterCallback<PointerDownEvent>(TopDown);
canvas.RegisterCallback<PointerUpEvent>((evt) => isDownMove = false);
canvas.RegisterCallback<PointerLeaveEvent>((evt) => isDownMove = false);
Close.clicked += () => { SetActive(false); };
}
/// <summary> 按下Top </summary>
private void TopDown(PointerDownEvent evt) {
isDownMove = true;
pointerPosition = UITool.GetMousePosition();
originalPosition = Window.transform.position;
}
/// <summary> 设置活动状态 </summary>
public virtual void SetActive(bool active) {
Window.EnableInClassList("window-hidden", !active);
}
/// <summary> 更新状态 </summary>
public virtual void Update() {
if (!isDownMove) { return; }
Vector3 mousePosition = UITool.GetMousePosition();
Vector3 offset = mousePosition - pointerPosition;
Vector3 position = originalPosition + new Vector3(offset.x, -offset.y);
float width = canvas.resolvedStyle.width - Window.resolvedStyle.width;
float height = canvas.resolvedStyle.height - Window.resolvedStyle.height;
position.x = Mathf.Clamp(position.x, 0, width);
position.y = Mathf.Clamp(position.y, 0, height);
Window.transform.position = position;
}
}
}
@@ -1,77 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
#if ENABLE_INPUT_SYSTEM && UNITY_INPUT_SYSTEM_PACKAGE
using UnityEngine.InputSystem;
#endif
namespace MuHua
{
/// <summary>
/// 悬浮窗口
/// </summary>
public abstract class UIFloatingWindow
{
/// <summary> 绑定的元素 </summary>
public readonly VisualElement element;
/// <summary> 绑定的画布 </summary>
public readonly VisualElement canvas;
private bool isDownMove;
private Vector3 pointerPosition;
private Vector3 originalPosition;
public VisualElement Window => element.Q<VisualElement>("Window");
public VisualElement Top => element.Q<VisualElement>("Top");
public VisualElement Container => element.Q<VisualElement>("Container");
public Label Title => element.Q<Label>("Title");
public Button Close => element.Q<Button>("Close");
public UIFloatingWindow(VisualElement element, VisualElement canvas)
{
this.element = element;
this.canvas = canvas;
Top.RegisterCallback<PointerDownEvent>(TopDown);
canvas.RegisterCallback<PointerUpEvent>((evt) => isDownMove = false);
canvas.RegisterCallback<PointerLeaveEvent>((evt) => isDownMove = false);
Close.clicked += () => { SetActive(false); };
}
/// <summary> 按下Top </summary>
private void TopDown(PointerDownEvent evt)
{
isDownMove = true;
pointerPosition = UITool.GetMousePosition();
originalPosition = Window.transform.position;
}
/// <summary> 设置活动状态 </summary>
public virtual void SetActive(bool active)
{
Window.EnableInClassList("window-hidden", !active);
}
/// <summary> 更新状态 </summary>
public virtual void Update()
{
if (!isDownMove) { return; }
Vector3 mousePosition = UITool.GetMousePosition();
Vector3 offset = mousePosition - pointerPosition;
Vector3 position = originalPosition + new Vector3(offset.x, -offset.y);
float width = canvas.resolvedStyle.width - Window.resolvedStyle.width;
float height = canvas.resolvedStyle.height - Window.resolvedStyle.height;
position.x = Mathf.Clamp(position.x, 0, width);
position.y = Mathf.Clamp(position.y, 0, height);
Window.transform.position = position;
}
}
}