feat(component): 新增2D拖拽基础组件并重构拖拽区域组件

- 添加抽象基类 AbstractDragDrop2DComponentBase 用于实现通用2D拖拽功能
- 重命名 AbstractDragDropComponent 为 AbstractDragDropArea2DComponent
- 将公共拖拽逻辑提取至基类,减少代码重复
- 统一信号定义与属性配置,提升组件一致性
- 优化拖拽状态管理与位置计算逻辑
- 完善节点生命周期中的资源清理机制
This commit is contained in:
GwWuYou 2025-12-12 21:43:35 +08:00
parent e5c0964c93
commit 066ceeaec1
2 changed files with 101 additions and 70 deletions

View File

@ -0,0 +1,90 @@
using GFramework.Core.architecture;
using GFramework.Core.controller;
using GFramework.Core.events;
using GFramework.Core.extensions;
using Godot;
namespace GFramework.Core.Godot.component;
/// <summary>
/// 抽象基类用于实现2D拖拽功能的组件。
/// 继承自Godot的Node类并实现了IController接口。
/// 提供了拖拽相关的信号定义以及基础属性配置。
/// </summary>
public abstract partial class AbstractDragDrop2DComponentBase: Node, IController
{
/// <summary>
/// 取消注册列表,用于管理需要在节点销毁时取消注册的对象
/// </summary>
protected readonly IUnRegisterList UnRegisterList = new UnRegisterList();
/// <summary>
/// 当拖拽被取消时触发的信号。
/// </summary>
/// <param name="startingPosition">拖拽起始位置。</param>
[Signal]
public delegate void DragCanceledEventHandler(Vector2 startingPosition);
/// <summary>
/// 当拖拽开始时触发的信号。
/// </summary>
[Signal]
public delegate void DragStartedEventHandler();
/// <summary>
/// 当拖拽结束并放置时触发的信号。
/// </summary>
/// <param name="startingPosition">拖拽起始位置。</param>
[Signal]
public delegate void DroppedEventHandler(Vector2 startingPosition);
/// <summary>
/// 是否启用拖拽功能。若为 false则忽略所有输入事件。
/// </summary>
public bool Enable { get; set; }
/// <summary>
/// 拖拽组的名称,用于区分不同的拖拽组。
/// </summary>
public string GroupName { get; set; } = "dragging";
/// <summary>
/// 拖拽时元素的最大Z轴索引值。
/// </summary>
public int ZIndexMax { get; set; } = 99;
/// <summary>
/// 拖拽时元素的最小Z轴索引值。
/// </summary>
public int ZIndexMin { get; set; } = 0;
/// <summary>
/// 获取架构实例。
/// </summary>
/// <returns>返回实现IArchitecture接口的架构实例。</returns>
public abstract IArchitecture GetArchitecture();
/// <summary>
/// 表示是否正在拖拽操作的标志位。
/// </summary>
protected bool IsDragging;
/// <summary>
/// 表示拖拽操作中的偏移量,用于计算当前位置与起始位置的差值。
/// </summary>
protected Vector2 Offset = Vector2.Zero;
/// <summary>
/// 表示拖拽操作的起始位置坐标。
/// </summary>
protected Vector2 StartingPosition;
/// <summary>
/// 节点退出场景树时的回调方法。
/// 在节点从场景树移除前调用,用于清理资源。
/// </summary>
public override void _ExitTree()
{
UnRegisterList.UnRegisterAll();
}
}

View File

@ -1,8 +1,4 @@
using GFramework.Core.architecture;
using GFramework.Core.controller;
using GFramework.Core.events;
using GFramework.Core.extensions;
using GFramework.Core.Godot.extensions;
using GFramework.Core.Godot.extensions;
using Godot;
namespace GFramework.Core.Godot.component;
@ -11,59 +7,13 @@ namespace GFramework.Core.Godot.component;
/// 抽象拖拽组件类,用于处理节点的拖放逻辑。
/// 实现了 IController 接口以支持架构通信,并通过信号通知拖拽事件的发生。
/// </summary>
public abstract partial class AbstractDragDropComponent : Node, IController
public abstract partial class AbstractDragDropArea2DComponent : AbstractDragDrop2DComponentBase
{
/// <summary>
/// 当拖拽被取消时触发的信号。
/// </summary>
/// <param name="startingPosition">拖拽起始位置。</param>
[Signal]
public delegate void DragCanceledEventHandler(Vector2 startingPosition);
/// <summary>
/// 当拖拽开始时触发的信号。
/// </summary>
[Signal]
public delegate void DragStartedEventHandler();
/// <summary>
/// 当拖拽结束并放置时触发的信号。
/// </summary>
/// <param name="startingPosition">拖拽起始位置。</param>
[Signal]
public delegate void DroppedEventHandler(Vector2 startingPosition);
/// <summary>
/// 取消注册列表,用于管理需要在节点销毁时取消注册的对象
/// </summary>
private readonly IUnRegisterList _unRegisterList = new UnRegisterList();
private bool _isDragging;
private Vector2 _offset = Vector2.Zero;
private Vector2 _startingPosition;
/// <summary>
/// 目标区域,通常是可交互的游戏对象(如单位或物品)所在的碰撞区域。
/// </summary>
public required Area2D Target { get; set; }
/// <summary>
/// 是否启用拖拽功能。若为 false则忽略所有输入事件。
/// </summary>
public bool Enable { get; set; }
public string GroupName { get; set; } = "dragging";
public int ZIndexMax { get; set; } = 99;
public int ZIndexMin { get; set; } = 0;
/// <summary>
/// 获取游戏架构实例
/// </summary>
/// <returns>返回游戏架构接口实例</returns>
public abstract IArchitecture GetArchitecture();
/// <summary>
/// 节点准备就绪时的回调方法。
/// 在节点添加到场景树后调用,绑定目标区域的输入事件处理器。
@ -81,7 +31,7 @@ public abstract partial class AbstractDragDropComponent : Node, IController
/// <param name="event">输入事件对象</param>
public override void _Input(InputEvent @event)
{
switch (_isDragging)
switch (IsDragging)
{
// 处理取消拖拽操作:当正在拖拽且按下取消拖拽按键时,执行取消拖拽逻辑
case true when Target.IsValidNode() && @event.IsActionPressed("cancel_drag"):
@ -108,7 +58,7 @@ public abstract partial class AbstractDragDropComponent : Node, IController
// 获取当前正在拖拽的对象
var draggingObj = GetTree().GetFirstNodeInGroup(GroupName);
switch (_isDragging)
switch (IsDragging)
{
// 处理开始拖拽操作:当未在拖拽状态且按下选择按键时,开始拖拽
case false when
@ -127,7 +77,7 @@ public abstract partial class AbstractDragDropComponent : Node, IController
/// <param name="delta">与上一帧的时间间隔(秒)。</param>
public override void _Process(double delta)
{
if (_isDragging && Target.IsValidNode()) Target.GlobalPosition = Target.GetGlobalMousePosition() + _offset;
if (IsDragging && Target.IsValidNode()) Target.GlobalPosition = Target.GetGlobalMousePosition() + Offset;
}
/// <summary>
@ -136,7 +86,7 @@ public abstract partial class AbstractDragDropComponent : Node, IController
/// </summary>
private void EndDragging()
{
_isDragging = false;
IsDragging = false;
Target.RemoveFromGroup(GroupName);
Target.ZIndex = ZIndexMin;
}
@ -148,7 +98,7 @@ public abstract partial class AbstractDragDropComponent : Node, IController
private void CancelDragging()
{
EndDragging();
EmitSignalDragCanceled(_startingPosition);
EmitSignalDragCanceled(StartingPosition);
}
/// <summary>
@ -157,11 +107,11 @@ public abstract partial class AbstractDragDropComponent : Node, IController
/// </summary>
private void StartDragging()
{
_isDragging = true;
_startingPosition = Target.GlobalPosition;
IsDragging = true;
StartingPosition = Target.GlobalPosition;
Target.AddToGroup(GroupName);
Target.ZIndex = ZIndexMax;
_offset = Target.GlobalPosition - Target.GetGlobalMousePosition();
Offset = Target.GlobalPosition - Target.GetGlobalMousePosition();
EmitSignalDragStarted();
}
@ -172,15 +122,6 @@ public abstract partial class AbstractDragDropComponent : Node, IController
private void Drop()
{
EndDragging();
EmitSignalDropped(_startingPosition);
}
/// <summary>
/// 节点退出场景树时的回调方法。
/// 在节点从场景树移除前调用,用于清理资源。
/// </summary>
public override void _ExitTree()
{
_unRegisterList.UnRegisterAll();
EmitSignalDropped(StartingPosition);
}
}