using System; using Godot; using UI.MapEditor; namespace UI.MapEditorTools; public partial class DoorDragArea : Control { /// <summary> /// 当前区域所占大小, 单位: 像素 /// </summary> public Vector2 AreaSize => new Vector2(_areaSize, GameConfig.TileCellSize * 2); //错误时的颜色 private static Color _errorColor = new Color(1, 0, 0, 0.1882353F); /// <summary> /// 朝向 /// </summary> public DoorDirection Direction { get; private set; } /// <summary> /// 绑定的数据 /// </summary> public DoorAreaInfo DoorAreaInfo { get; set; } /// <summary> /// 所属悬停区域 /// </summary> public DoorHoverArea DoorHoverArea { get; private set; } /// <summary> /// 所属 Ui 对象 /// </summary> public MapEditorToolsPanel MapEditorToolsPanel { get; private set; } private DoorDragButton _startButton; private DoorDragButton _endButton; private bool _mouseHover = false; private MapEditorTools.DoorToolTemplate _node; private Vector2 _startTempPos; private Vector2 _endTempPos; //默认颜色 private Color _defaultColor; //区域大小, 单位: 像素 private int _areaSize = GameConfig.TileCellSize * 4; //拖拽松手后是否可以提交 private bool _canComment = true; //开始拖拽时的区域 private Vector2I _startDragRange; //是否是拖拽模式 private bool _isDragMode = false; //拖拽模式提交回调 private Action<DoorDirection, int, int> _onSubmit; //拖拽模式取消时回调 private Action _onCancel; public void SetDoorDragAreaNode(MapEditorTools.DoorToolTemplate node) { _node = node; MapEditorToolsPanel = (MapEditorToolsPanel)node.UiPanel; _defaultColor = _node.L_DoorArea.Instance.Color; _startButton = _node.L_StartBtn.Instance; _endButton = _node.L_EndBtn.Instance; _startButton.DragEvent += OnStartAreaDrag; _endButton.DragEvent += OnEndAreaDrag; node.L_DoorArea.Instance.MouseEntered += OnMouseEntered; node.L_DoorArea.Instance.MouseExited += OnMouseExited; SetDoorAreaSize(GameConfig.TileCellSize * 4); } public override void _Process(double delta) { if (_mouseHover && !DoorHoverArea.IsDrag && Input.IsMouseButtonPressed(MouseButton.Right)) //右键删除区域 { MapEditorToolsPanel.RemoveDoorTool(_node); } else if (_isDragMode) { if (!Input.IsMouseButtonPressed(MouseButton.Left)) //松开了右键 { _isDragMode = false; if (_canComment) //可以提交 { _isDragMode = false; _onCancel = null; _startButton.EmitSignal(BaseButton.SignalName.ButtonUp); _endButton.EmitSignal(BaseButton.SignalName.ButtonUp); if (_onSubmit != null) { var doorAreaRange = GetDoorAreaRange(); _onSubmit(Direction, doorAreaRange.X, doorAreaRange.Y); _onSubmit = null; } } else //不能提交 { if (_onCancel != null) { _onCancel(); } } } } } /// <summary> /// 设置门区域的位置, 单位: 像素 /// </summary> public void SetDoorAreaPosition(Vector2 position) { Position = position; } /// <summary> /// 设置所属悬停区域 /// </summary> public void SetDoorHoverArea(DoorHoverArea hoverArea) { DoorHoverArea = hoverArea; Direction = hoverArea.Direction; if (Direction == DoorDirection.N) { Scale = new Vector2(1, 1); RotationDegrees = 0; } else if (Direction == DoorDirection.E) { Scale = new Vector2(1, 1); RotationDegrees = 90; } else if (Direction == DoorDirection.S) { Scale = new Vector2(-1, 1); RotationDegrees = 180; } else { Scale = new Vector2(-1, 1); RotationDegrees = 270; } } /// <summary> /// 获取门区域所占范围, 单位: 像素, 返回的 Vector2I 的 x 代表起始坐标, y 代表结束坐标 /// </summary> /// <returns></returns> public Vector2I GetDoorAreaRange() { var start = (int)(_startButton.Position.X + _startButton.Size.X); return new Vector2I(start, start + _areaSize); } /// <summary> /// 设置门区域所占范围, 单位: 像素 /// </summary> public void SetDoorAreaRange(int start, int end) { var startPosition = _startButton.Position; startPosition.X = start - _startButton.Size.X; _startButton.Position = startPosition; SetDoorAreaSize(end - start); } /// <summary> /// 设置区域起始坐标 /// </summary> public void SetDoorAreaStart(int start) { var startPosition = _startButton.Position; startPosition.X = start - _startButton.Size.X; _startButton.Position = startPosition; RefreshArea(); } /// <summary> /// 设置区域大小, 单位: 像素 /// </summary> public void SetDoorAreaSize(int value) { _areaSize = value; RefreshArea(); //GD.Print("size: " + GetDoorAreaRange()); } //刷新区域位置 private void RefreshArea() { var colorRect = _node.L_DoorArea.Instance; var position = colorRect.Position; position.X = _startButton.Position.X + _startButton.Size.X; colorRect.Position = position; colorRect.Size = AreaSize; var position2 = _endButton.Position; position2.X = position.X + AreaSize.X; _endButton.Position = position2; } //拖拽起始点 private void OnStartAreaDrag(DragState dragState, Vector2 offset) { if (dragState == DragState.DragStart) { DoorHoverArea.IsDrag = true; _canComment = true; _startTempPos = _startButton.Position; _startDragRange = GetDoorAreaRange(); } else if (dragState == DragState.DragMove) { if (_isDragMode) { offset.X -= GameConfig.TileCellSize; } var position = _startTempPos; position.X += offset.X + _startButton.Size.X; var endPosition = _endButton.Position; //拖拽模式 if (_isDragMode) { if (position.X > endPosition.X) //该换方向了 { _startButton.EmitSignal(BaseButton.SignalName.ButtonUp); _endButton.EmitSignal(BaseButton.SignalName.ButtonDown); if (Mathf.Abs(position.X - endPosition.X) >= GameConfig.TileCellSize * 4 && !_canComment) { _canComment = true; _node.L_DoorArea.Instance.Color = _defaultColor; } return; } } //计算区域大小 var areaSize = (int)(endPosition.X - position.X); _startButton.Position = position - new Vector2(_startButton.Size.X, 0); //刷新区域位置 SetDoorAreaSize(areaSize); //起始点坐标必须要小于终点坐标, 且起点坐标大于0 if (position.X < endPosition.X && (DoorHoverArea == null || position.X >= 0)) { //区域必须大于等于 4 格宽度 if (areaSize >= GameConfig.TileCellSize * 4) { var doorAreaRange = GetDoorAreaRange(); //检测是否撞到其他区域 bool checkResult; if (DoorAreaInfo == null) { checkResult = MapEditorToolsPanel.EditorMap.Instance.CheckDoorArea(Direction, doorAreaRange.X, doorAreaRange.Y); } else { checkResult = MapEditorToolsPanel.EditorMap.Instance.CheckDoorArea(DoorAreaInfo, doorAreaRange.X, doorAreaRange.Y); } if (checkResult) { //可以提交 _canComment = true; _node.L_DoorArea.Instance.Color = _defaultColor; return; } } } //错误的位置 if (_canComment) { _canComment = false; _node.L_DoorArea.Instance.Color = _errorColor; } } else { DoorHoverArea.IsDrag = false; //松手后如果不能提交, 则还原初始位置 if (!_canComment) { _canComment = true; _node.L_DoorArea.Instance.Color = _defaultColor; SetDoorAreaRange(_startDragRange.X, _startDragRange.Y); } else { //提交数据 SubmitData(); } if (DoorHoverArea != null) { DoorHoverArea.EmitSignal(Control.SignalName.MouseExited); } } } private void OnEndAreaDrag(DragState dragState, Vector2 offset) { if (dragState == DragState.DragStart) { DoorHoverArea.IsDrag = true; _canComment = true; _endTempPos = _endButton.Position; _startDragRange = GetDoorAreaRange(); } else if (dragState == DragState.DragMove) { var position = _endTempPos; position.X = position.X += offset.X; var startPosition = _startButton.Position + new Vector2(_startButton.Size.X, 0); //拖拽模式 if (_isDragMode) { if (position.X < startPosition.X) //该换方向了 { _endButton.EmitSignal(BaseButton.SignalName.ButtonUp); _startButton.EmitSignal(BaseButton.SignalName.ButtonDown); if (Mathf.Abs(position.X - startPosition.X) >= GameConfig.TileCellSize * 4 && !_canComment) { _canComment = true; _node.L_DoorArea.Instance.Color = _defaultColor; } return; } } //区域大小 var areaSize = (int)(position.X - startPosition.X); //刷新区域位置 SetDoorAreaSize(areaSize); //终点坐标必须要大于起始点坐标, 且终点坐标必须小于宽度 if (position.X > startPosition.X && (DoorHoverArea == null || position.X <= DoorHoverArea.Size.X)) { //区域必须大于等于 4 格宽度 if (areaSize >= GameConfig.TileCellSize * 4) { var doorAreaRange = GetDoorAreaRange(); //检测是否撞到其他区域 bool checkResult; if (DoorAreaInfo == null) { checkResult = MapEditorToolsPanel.EditorMap.Instance.CheckDoorArea(Direction, doorAreaRange.X, doorAreaRange.Y); } else { checkResult = MapEditorToolsPanel.EditorMap.Instance.CheckDoorArea(DoorAreaInfo, doorAreaRange.X, doorAreaRange.Y); } if (checkResult) { //可以提交 _canComment = true; _node.L_DoorArea.Instance.Color = _defaultColor; return; } } } //错误的位置 if (_canComment) { _canComment = false; _node.L_DoorArea.Instance.Color = _errorColor; } } else { DoorHoverArea.IsDrag = false; //松手后如果不能提交, 则还原初始位置 if (!_canComment) { _canComment = true; _node.L_DoorArea.Instance.Color = _defaultColor; SetDoorAreaRange(_startDragRange.X, _startDragRange.Y); } else { //提交数据 SubmitData(); } if (DoorHoverArea != null) { DoorHoverArea.EmitSignal(Control.SignalName.MouseExited); } } } /// <summary> /// 将该区域变为拖拽模式, 用于创建门区域 /// </summary> /// <param name="onSubmit">成功提交时回调, 参数1为方向, 参数2为起始点, 参数3为大小</param> /// <param name="onCancel">取消时调用</param> public void MakeDragMode(Action<DoorDirection, int, int> onSubmit, Action onCancel) { _canComment = false; _isDragMode = true; _onSubmit = onSubmit; _onCancel = onCancel; _endButton.EmitSignal(BaseButton.SignalName.ButtonDown); } //提交数据 private void SubmitData() { //保存数据 if (DoorAreaInfo != null) { var doorAreaRange = GetDoorAreaRange(); DoorAreaInfo.Start = doorAreaRange.X; DoorAreaInfo.End = doorAreaRange.Y; GD.Print("提交修改: " + doorAreaRange); //派发修改数据修改事件 EventManager.EmitEvent(EventEnum.OnEditorDirty); } } private void OnMouseEntered() { if (MapEditorToolsPanel.EditorMap.Instance.MouseType != EditorTileMap.MouseButtonType.Edit) { return; } _mouseHover = true; } private void OnMouseExited() { if (MapEditorToolsPanel.EditorMap.Instance.MouseType != EditorTileMap.MouseButtonType.Edit) { return; } _mouseHover = false; } }