Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / ui / tileSetEditorCombination / leftTop / TileEditCombination.cs
@小李xl 小李xl on 19 Dec 2023 10 KB 组合图块, 更新纹理, 开发中
using System;
using System.Collections.Generic;
using Godot;

namespace UI.TileSetEditorCombination;

public partial class TileEditCombination : GridBg<TileSetEditorCombination.LeftTopBg>
{
    // ------------------------------- 笔刷相关 -------------------------------
    //笔刷数据, kay: 代表原图中的坐标, 单位: 格
    private Dictionary<Vector2I, CombinationCell> _brushData = new Dictionary<Vector2I, CombinationCell>();

    //笔刷偏移, 单位: 像素
    private Vector2I _brushOffset = Vector2I.Zero;
    //上一帧笔刷位置
    private Vector2 _brushPrevPos = Vector2.Zero;
    private bool _initBrush = false;
    private bool _drawBrushFlag = false;
    private int _xStart = int.MaxValue;
    private int _yStart = int.MaxValue;
    private int _xEnd = int.MinValue;
    private int _yEnd = int.MinValue;
    // -----------------------------------------------------------------------
    
    // ------------------------------- 画布相关 -------------------------------
    //画布数据, kay: 绘制坐标, 单位: 像素
    private Dictionary<Vector2I, CombinationCell> _canvas = new Dictionary<Vector2I, CombinationCell>();
    //画布数据是否需要更新
    private bool _canvasDirty = false;
    // -----------------------------------------------------------------------

    public override void SetUiNode(IUiNode uiNode)
    {
        base.SetUiNode(uiNode);
        UiNode.L_CombinationRoot.L_RectBrush.Instance.Root = UiNode.L_CombinationRoot.Instance;
        Grid = UiNode.L_Grid.Instance;
        ContainerRoot = UiNode.L_CombinationRoot.Instance;

        UiNode.UiPanel.AddEventListener(EventEnum.OnSelectCombinationCell, OnSelectCombinationCell);
        UiNode.UiPanel.AddEventListener(EventEnum.OnRemoveCombinationCell, OnRemoveCombinationCell);
        UiNode.UiPanel.AddEventListener(EventEnum.OnClearCombinationCell, OnClearCombinationCell);

        //删除按钮点击事件
        UiNode.L_DeleteBtn.Instance.Pressed += OnDeleteClick;
        //聚焦按钮点击事件
        UiNode.L_FocusBtn.Instance.Pressed += OnFocusClick;
        //导入组合按钮点击事件
        UiNode.L_ImportBtn.Instance.Pressed += OnImportClick;
    }

    public override void _Process(double delta)
    {
        if (!UiNode.UiPanel.IsOpen)
        {
            return;
        }

        var brushRoot = UiNode.L_CombinationRoot.L_BrushRoot.Instance;
        var combinationRoot = UiNode.L_CombinationRoot.Instance;
        brushRoot.Position = combinationRoot.GetLocalMousePosition().FloorAdsorption(GameConfig.TileCellSizeVector2I) + _brushOffset;

        if (_canvasDirty) //更新画布范围
        {
            _canvasDirty = false;
            if (_canvas.Count > 0)
            {
                //单位: 像素
                var canvasXStart = int.MaxValue;
                var canvasYStart = int.MaxValue;
                var canvasXEnd = int.MinValue;
                var canvasYEnd = int.MinValue;

                foreach (var keyValuePair in _canvas)
                {
                    var pos = keyValuePair.Key;
                    canvasXStart = Mathf.Min(pos.X, canvasXStart);
                    canvasYStart = Mathf.Min(pos.Y, canvasYStart);
                    canvasXEnd = Mathf.Max(pos.X + GameConfig.TileCellSize, canvasXEnd);
                    canvasYEnd = Mathf.Max(pos.Y + GameConfig.TileCellSize, canvasYEnd);
                }
                
                UiNode.L_CombinationRoot.L_RectBrush.Instance.SetDrawRect(
                    canvasXStart,
                    canvasYStart,
                    canvasXEnd - canvasXStart,
                    canvasYEnd - canvasYStart
                );
            }
            else
            {
                UiNode.L_CombinationRoot.L_RectBrush.Instance.ClearDrawRect();
            }
        }
    }

    public override void _GuiInput(InputEvent @event)
    {
        base._GuiInput(@event);
        if (@event is InputEventMouse)
        {
            AcceptEvent();
            var brushRoot = UiNode.L_CombinationRoot.L_BrushRoot.Instance;
            var newPos = brushRoot.Position;
            
            sbyte flag = 0;
            //左键按下开始绘制
            if (_initBrush)
            {
                if (Input.IsMouseButtonPressed(MouseButton.Left)) //绘制
                {
                    flag = 1;
                    if (_brushPrevPos != newPos || !_drawBrushFlag)
                    {
                        _drawBrushFlag = true;
                        _brushPrevPos = newPos;
                        DrawBrush();
                    }
                }
                else if (Input.IsMouseButtonPressed(MouseButton.Right)) //擦除
                {
                    flag = -1;
                    brushRoot.Modulate = new Color(1, 1, 1, 0.3f);
                    if (_brushPrevPos != newPos || !_drawBrushFlag)
                    {
                        _drawBrushFlag = true;
                        _brushPrevPos = newPos;
                        EraseBrush();
                    }
                }
            }

            if (flag != 0)
            {
                _drawBrushFlag = false;
            }

            if (flag != -1)
            {
                brushRoot.Modulate = Colors.White;
            }
        }
    }

    //删除所有图块
    private void OnDeleteClick()
    {
        foreach (var keyValuePair in _canvas)
        {
            keyValuePair.Value.QueueFree();
        }

        _canvas.Clear();
        _canvasDirty = true;
    }
    
    //点击聚焦按钮
    private void OnFocusClick()
    {
        var pos = Size / 2;
        var center = UiNode.L_CombinationRoot.L_RectBrush.Instance.GetCenterPosition();
        ContainerRoot.Position = pos - center * ContainerRoot.Scale;
        RefreshGridTrans();
    }
    
    //导入按钮点击
    private void OnImportClick()
    {
        var size = UiNode.L_CombinationRoot.L_RectBrush.Instance.GetRectSize();
        if (size == Vector2.Zero)
        {
            EditorWindowManager.ShowTips("警告", "请先绘制组合图块!");
            return;
        }
        else if (size == GameConfig.TileCellSizeVector2I)
        {
            EditorWindowManager.ShowTips("警告", "导入一格大小的组合图块没有任何意义!");
            return;
        }

        var texture = GetCombinationPreviewTexture();
        EditorWindowManager.ShowImportCombination("组合名称", texture, (name) =>
        {
            //派发导入组合图块事件
            EventManager.EmitEvent(EventEnum.OnImportCombination, new ImportCombinationData()
            {
                Name = name,
                PreviewTexture = texture
            });
        }, () => //取消添加组件
        {
            texture.Dispose();
        });
    }
    
    //绘制笔刷
    private void DrawBrush()
    {
        var brushRoot = UiNode.L_CombinationRoot.L_BrushRoot.Instance;
        foreach (var keyValuePair in _brushData)
        {
            var combinationCell = keyValuePair.Value;
            var pos = (combinationCell.Position + brushRoot.Position).AsVector2I();
            if (_canvas.TryGetValue(pos, out var canvasCell))
            {
                canvasCell.CloneFrom(combinationCell);
            }
            else
            {
                canvasCell = (CombinationCell)combinationCell.Duplicate();
                canvasCell.Position = pos;
                UiNode.L_CombinationRoot.L_CanvasRoot.AddChild(canvasCell);
                _canvas.Add(pos, canvasCell);
                _canvasDirty = true;
            }
        }
    }

    //擦除笔刷
    private void EraseBrush()
    {
        var brushRoot = UiNode.L_CombinationRoot.L_BrushRoot.Instance;
        foreach (var keyValuePair in _brushData)
        {
            var combinationCell = keyValuePair.Value;
            var pos = (combinationCell.Position + brushRoot.Position).AsVector2I();
            if (_canvas.TryGetValue(pos, out var canvasCell))
            {
                canvasCell.QueueFree();
                _canvas.Remove(pos);
                _canvasDirty = true;
            }
        }
    }

    //选中组合的图块
    private void OnSelectCombinationCell(object obj)
    {
        if (obj is Vector2I cell && !_brushData.ContainsKey(cell))
        {
            _initBrush = true;
            var cellData = new CombinationCell();
            cellData.Position = cell * GameConfig.TileCellSize;
            cellData.InitData(UiNode.UiPanel.EditorPanel.Texture, cell);
            UiNode.L_CombinationRoot.L_BrushRoot.AddChild(cellData);
            _brushData.Add(cell, cellData);
            
            //计算起始点和终点
            _xStart = Mathf.Min(cell.X, _xStart);
            _yStart = Mathf.Min(cell.Y, _yStart);
            _xEnd = Mathf.Max(cell.X, _xEnd);
            _yEnd = Mathf.Max(cell.Y, _yEnd);
            _brushOffset = new Vector2I(-(_xStart + (_xEnd - _xStart) / 2), -(_yStart + (_yEnd - _yStart) / 2)) * GameConfig.TileCellSize;
        }
    }
    
    //移除组合图块
    private void OnRemoveCombinationCell(object obj)
    {
        if (obj is Vector2I cell)
        {
            if (_brushData.TryGetValue(cell, out var cellData))
            {
                cellData.QueueFree();
                _brushData.Remove(cell);
            }
        }
    }

    //移除所有组合图块
    private void OnClearCombinationCell(object obj)
    {
        foreach (var keyValuePair in _brushData)
        {
            keyValuePair.Value.QueueFree();
        }
        _brushData.Clear();
        _initBrush = false;
        _brushOffset = Vector2I.Zero;
        _xStart = int.MaxValue;
        _yStart = int.MaxValue;
        _xEnd = int.MinValue;
        _yEnd = int.MinValue;
    }
    
    /// <summary>
    /// 获取组合的预览图
    /// </summary>
    private Texture2D GetCombinationPreviewTexture()
    {
        var rectBrush = UiNode.L_CombinationRoot.L_RectBrush.Instance;
        var src = UiNode.UiPanel.EditorPanel.TextureImage;
        var rectSize = rectBrush.GetRectSize();
        var originPos = rectBrush.GetOriginPosition();
        var image = Image.Create(rectSize.X + 4, rectSize.Y + 4, false, Image.Format.Rgba8);
        image.Fill(Colors.Gray);
        foreach (var keyValuePair in _canvas)
        {
            var pos = keyValuePair.Key;
            var srcRect = keyValuePair.Value.RegionRect;
            image.BlendRect(src, new Rect2I(srcRect.Position.AsVector2I(), srcRect.Size.AsVector2I()),
                pos - originPos + new Vector2I(2, 2));
        }
        return ImageTexture.CreateFromImage(image);
    }
}