diff --git a/DungeonShooting_Godot/src/framework/ui/IUiNode.cs b/DungeonShooting_Godot/src/framework/ui/IUiNode.cs
index 12f5c8f..5e56ca1 100644
--- a/DungeonShooting_Godot/src/framework/ui/IUiNode.cs
+++ b/DungeonShooting_Godot/src/framework/ui/IUiNode.cs
@@ -9,25 +9,25 @@
///
/// 嵌套打开子ui
///
- public UiBase OpenNestedUi(string uiName, UiBase prevUi = null);
+ UiBase OpenNestedUi(string uiName, UiBase prevUi = null);
///
/// 嵌套打开子ui
///
- public T OpenNestedUi(string uiName, UiBase prevUi = null) where T : UiBase;
+ T OpenNestedUi(string uiName, UiBase prevUi = null) where T : UiBase;
///
/// 获取所属Ui面板
///
- public UiBase GetUiPanel();
+ UiBase GetUiPanel();
///
/// 获取Ui实例
///
- public Node GetUiInstance();
+ Node GetUiInstance();
///
/// 获取克隆的Ui实例
///
- public IUiCellNode CloneUiCell();
+ IUiCellNode CloneUiCell();
}
diff --git a/DungeonShooting_Godot/src/framework/ui/UiGridContainer.cs b/DungeonShooting_Godot/src/framework/ui/UiGridContainer.cs
new file mode 100644
index 0000000..891fe33
--- /dev/null
+++ b/DungeonShooting_Godot/src/framework/ui/UiGridContainer.cs
@@ -0,0 +1,27 @@
+using System;
+using Godot;
+
+///
+/// 用于 UiGrid 类
+///
+public partial class UiGridContainer : GridContainer
+{
+ private Action _onReady;
+ private Action _onProcess;
+
+ public UiGridContainer(Action onReady, Action onProcess)
+ {
+ _onReady = onReady;
+ _onProcess = onProcess;
+ }
+
+ public override void _Ready()
+ {
+ _onReady();
+ }
+
+ public override void _Process(double delta)
+ {
+ _onProcess((float)delta);
+ }
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/ui/grid/IUiCell.cs b/DungeonShooting_Godot/src/framework/ui/grid/IUiCell.cs
index 4b4e239..379abd9 100644
--- a/DungeonShooting_Godot/src/framework/ui/grid/IUiCell.cs
+++ b/DungeonShooting_Godot/src/framework/ui/grid/IUiCell.cs
@@ -5,23 +5,71 @@
public interface IUiCell : IDestroy
{
///
+ /// 是否启用了当前 Cell
+ ///
+ bool Enable { get; }
+
+ ///
/// 当前 Cell 在 UiGrid 组件中的索引位置
///
- public int Index { get; }
+ int Index { get; }
///
+ /// 当前 Cell 初始化时调用
+ ///
+ void OnInit();
+
+ ///
+ /// 如果启用了当前 Cell, 则调用
+ ///
+ void Process(float delta);
+
+ ///
+ /// 当前Ui被点击时调用
+ /// 如果 Cell 的模板为 BaseButton 类型, 则 UiCell 会自动绑定点击事件
+ /// 如果需要自己绑定点击事件, 请绑定 UiCell.Click() 函数
+ /// 如果当前 Cell 未被选中, 则 OnSelect() 会比 OnClick() 先调用
+ ///
+ void OnClick();
+
+ ///
+ /// 双击当前 Cell 调用
+ ///
+ void OnDoubleClick();
+
+ ///
+ /// 当启用当前 Cell 时调用
+ ///
+ void OnEnable();
+
+ ///
+ /// 当禁用当前 Cell 时调用, 也就是被回收时调用
+ ///
+ void OnDisable();
+
+ ///
/// 当检测当前 Cell 是否可以被选中时调用
///
- public bool CanSelect();
+ bool CanSelect();
///
/// 当前 Cell 选中时调用, 设置 UiGrid.SelectIndex 时触发
///
- public void OnSelect();
+ void OnSelect();
///
/// 当前 Cell 取消选中时调用, 设置 UiGrid.SelectIndex 时触发
///
- public void OnUnSelect();
+ void OnUnSelect();
+ ///
+ /// 当 Cell 索引发生改变时调用, 在 UiGrid 中调用 Insert(), Remove() 等函数时被动触发当前 Cell 索引值改变, Cell 业务逻辑需要用到索引值时, 那么就可以重写该函数
+ /// 注意: 该函数第一次调用会在 OnSetData() 之前调用
+ ///
+ void OnRefreshIndex();
+
+ ///
+ /// 销毁当前cell时调用
+ ///
+ void OnDestroy();
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/ui/grid/IUiGrid.cs b/DungeonShooting_Godot/src/framework/ui/grid/IUiGrid.cs
index 2965328..ddcfe39 100644
--- a/DungeonShooting_Godot/src/framework/ui/grid/IUiGrid.cs
+++ b/DungeonShooting_Godot/src/framework/ui/grid/IUiGrid.cs
@@ -8,10 +8,10 @@
///
/// 当前选中的 Cell 索引
///
- public int SelectIndex { get; set; }
+ int SelectIndex { get; set; }
///
/// 设置网格组件是否可见
///
- public bool Visible { get; set; }
+ bool Visible { get; set; }
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/ui/grid/UiCell.cs b/DungeonShooting_Godot/src/framework/ui/grid/UiCell.cs
index 01f61ac..9828ba5 100644
--- a/DungeonShooting_Godot/src/framework/ui/grid/UiCell.cs
+++ b/DungeonShooting_Godot/src/framework/ui/grid/UiCell.cs
@@ -1,4 +1,5 @@
+using System;
using Godot;
///
@@ -10,6 +11,8 @@
{
public bool IsDestroyed { get; private set; }
+ public bool Enable { get; private set; }
+
public int Index { get; private set; } = -1;
///
@@ -28,10 +31,9 @@
public T Data { get; private set; }
private bool _init = false;
-
- ///
- /// 当前cell初始化时调用
- ///
+ //上一次点击的时间
+ private long _prevClickTime = -1;
+
public virtual void OnInit()
{
}
@@ -43,23 +45,23 @@
{
}
- ///
- /// 当当前Ui被点击时调用, 如果 Cell 的模板为 BaseButton 类型, 则 UiCell 会自动绑定点击事件
- ///
+
+ public virtual void Process(float delta)
+ {
+ }
+
public virtual void OnClick()
{
}
- ///
- /// 当启用当前 Cell 时调用
- ///
+ public virtual void OnDoubleClick()
+ {
+ }
+
public virtual void OnEnable()
{
}
-
- ///
- /// 当禁用当前 Cell 时调用, 也就是被回收时调用
- ///
+
public virtual void OnDisable()
{
}
@@ -76,18 +78,11 @@
public virtual void OnUnSelect()
{
}
-
- ///
- /// 当 Cell 索引发生改变时调用, 在 UiGrid 中调用 Insert(), Remove() 等函数时被动触发当前 Cell 索引值改变, Cell 业务逻辑需要用到索引值时, 那么就可以重写该函数
- /// 注意: 该函数第一次调用会在 OnSetData() 之前调用
- ///
+
public virtual void OnRefreshIndex()
{
}
-
- ///
- /// 销毁当前cell时调用
- ///
+
public virtual void OnDestroy()
{
}
@@ -113,9 +108,9 @@
OnInit();
SetIndex(index);
}
-
+
///
- /// 设置当前cell的值, 这个函数由 UiGrid 调用
+ /// 设置当前 Cell 的值, 该函数由 UiGrid 调用
///
public void SetData(T data)
{
@@ -124,7 +119,7 @@
}
///
- /// 设置当前 Cell 的索引
+ /// 设置当前 Cell 的索引, 该函数由 UiGrid 对象调用
///
public void SetIndex(int index)
{
@@ -136,12 +131,44 @@
}
///
+ /// 设置是否启用该 Cell, 该函数由 UiGrid 对象调用
+ ///
+ public void SetEnable(bool value)
+ {
+ Enable = value;
+ if (value)
+ {
+ OnEnable();
+ }
+ else
+ {
+ OnDisable();
+ }
+ }
+
+ ///
/// 触发点击当前Ui, 如果 Cell 的模板为 BaseButton 类型, 则 UiCell 会自动绑定点击事件
///
public void Click()
{
Grid.SelectIndex = Index;
OnClick();
+
+ //双击判定
+ if (_prevClickTime >= 0)
+ {
+ var now = DateTime.Now.Ticks / 10000;
+ if (now <= _prevClickTime + 500)
+ {
+ OnDoubleClick();
+ }
+
+ _prevClickTime = -1;
+ }
+ else
+ {
+ _prevClickTime = DateTime.Now.Ticks / 10000;
+ }
}
public void Destroy()
diff --git a/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs b/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs
index 29ab909..b65349c 100644
--- a/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs
+++ b/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs
@@ -68,7 +68,7 @@
//当前已被回收的cell池
private List> _cellList = new List>();
//godot原生网格组件
- private GridContainer _gridContainer;
+ private UiGridContainer _gridContainer;
//单个cell偏移
private Vector2I _cellOffset;
//列数
@@ -80,7 +80,7 @@
public UiGrid(TUiCellNode template, Type cellType)
{
- _gridContainer = new GridContainer();
+ _gridContainer = new UiGridContainer(OnReady, OnProcess);
_gridContainer.Ready += OnReady;
_template = template;
_cellType = cellType;
@@ -344,15 +344,32 @@
_cellPool = null;
_gridContainer.QueueFree();
}
-
+
private void OnReady()
{
- _gridContainer.Ready -= OnReady;
if (_template.GetUiInstance() is Control control)
{
_gridContainer.Position = control.Position;
}
}
+
+ private void OnProcess(float delta)
+ {
+ if (IsDestroyed)
+ {
+ return;
+ }
+ //调用 cell 更新
+ var uiCells = _cellPool.ToArray();
+ for (var i = 0; i < uiCells.Length; i++)
+ {
+ var item = uiCells[i];
+ if (item.Enable)
+ {
+ item.Process(delta);
+ }
+ }
+ }
//获取 cell 实例
private UiCell GetCellInstance()
@@ -361,7 +378,7 @@
{
var cell = _cellPool.Pop();
cell.SetIndex(_cellList.Count);
- cell.OnEnable();
+ cell.SetEnable(true);
_cellList.Add(cell);
return cell;
}
@@ -374,14 +391,14 @@
_cellList.Add(uiCell);
uiCell.Init(this, (TUiCellNode)_template.CloneUiCell(), _cellList.Count - 1);
- uiCell.OnEnable();
+ uiCell.SetEnable(true);
return uiCell;
}
//回收 cell
private void ReclaimCellInstance(UiCell cell)
{
- cell.OnDisable();
+ cell.SetEnable(false);
_gridContainer.RemoveChild(cell.CellNode.GetUiInstance());
_cellPool.Push(cell);
}
diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorSelectObject/ObjectButtonCell.cs b/DungeonShooting_Godot/src/game/ui/mapEditorSelectObject/ObjectButtonCell.cs
index 989d9a9..60c1fbe 100644
--- a/DungeonShooting_Godot/src/game/ui/mapEditorSelectObject/ObjectButtonCell.cs
+++ b/DungeonShooting_Godot/src/game/ui/mapEditorSelectObject/ObjectButtonCell.cs
@@ -1,4 +1,5 @@
using Config;
+using Godot;
namespace UI.MapEditorSelectObject;