Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / ui / tileSetEditorSegment / TileEditArea.cs
using System.Collections.Generic;
using Godot;

namespace UI.TileSetEditorSegment;

public partial class TileEditArea : ColorRect, IUiNodeScript
{
    private TileSetEditorSegment.LeftBg _leftBg;
    private DragBinder _dragBinder;
    private UiGrid<TileSetEditorSegment.MaskRect, bool> _maskGrid;
    private readonly HashSet<Vector2I> _useMask = new HashSet<Vector2I>();
    
    public void SetUiNode(IUiNode uiNode)
    {
        _leftBg = (TileSetEditorSegment.LeftBg)uiNode;
        var maskBrush = _leftBg.L_TileTexture.L_MaskBrush.Instance;
        maskBrush.TileTexture = _leftBg.L_TileTexture.Instance;
        maskBrush.TileEditArea = this;

        _dragBinder = DragUiManager.BindDrag(this, "mouse_middle", OnDrag);
        Resized += OnLeftBgResize;

        _maskGrid = new UiGrid<TileSetEditorSegment.MaskRect, bool>(_leftBg.L_TileTexture.L_MaskRoot.L_MaskRect, typeof(MaskRectCell));
        _maskGrid.SetCellOffset(Vector2I.Zero);
        
        _leftBg.UiPanel.AddEventListener(EventEnum.OnImportTileCell, OnImportCell);
        _leftBg.UiPanel.AddEventListener(EventEnum.OnRemoveTileCell, OnRemoveCell);
    }

    public void OnDestroy()
    {
        _dragBinder.UnBind();
        _maskGrid.Destroy();
    }

    private void OnDrag(DragState state, Vector2 pos)
    {
        if (state == DragState.DragMove)
        {
            _leftBg.L_TileTexture.Instance.Position += pos;
            OnLeftBgResize();
        }
    }

    public override void _Input(InputEvent @event)
    {
        //Ui未打开
        if (!_leftBg.UiPanel.IsOpen)
        {
            return;
        }
        if (@event is InputEventMouseButton mouseButton)
        {
            if (_leftBg.UiPanel.IsOpen)
            {
                if (mouseButton.ButtonIndex == MouseButton.WheelDown)
                {
                    if (GetGlobalRect().HasPoint(mouseButton.GlobalPosition))
                    {
                        //缩小
                        Shrink();
                    }
                }
                else if (mouseButton.ButtonIndex == MouseButton.WheelUp)
                {
                    if (GetGlobalRect().HasPoint(mouseButton.GlobalPosition))
                    {
                        //放大
                        Magnify();
                    }
                }
            }
        }
    }

    public override void _Process(double delta)
    {
        //Ui未打开
        if (!_leftBg.UiPanel.IsOpen)
        {
            return;
        }

        if (Input.IsMouseButtonPressed(MouseButton.Left)) //左键导入
        {
            if (_leftBg.L_TileTexture.Instance.IsMouseInRect() && this.IsMouseInRect())
            {
                var cellPosition = GetMouseCellPosition();
                if (!_useMask.Contains(cellPosition))
                {
                    EventManager.EmitEvent(EventEnum.OnImportTileCell, cellPosition);
                }
            }
        }
        else if (Input.IsMouseButtonPressed(MouseButton.Right)) //右键移除
        {
            if (_leftBg.L_TileTexture.Instance.IsMouseInRect() && this.IsMouseInRect())
            {
                var cellPosition = GetMouseCellPosition();
                if (_useMask.Contains(cellPosition))
                {
                    EventManager.EmitEvent(EventEnum.OnRemoveTileCell, cellPosition);
                }
            }
        }
    }

    /// <summary>
    /// 导入选中的Cell图块
    /// </summary>
    private void OnImportCell(object arg)
    {
        if (arg is Vector2I cell)
        {
            var cellIndex = _leftBg.UiPanel.EditorPanel.CellPositionToIndex(cell);
            var uiCell = _maskGrid.GetCell(cellIndex);
            if (uiCell != null && !uiCell.Data)
            {
                _useMask.Add(cell);
                uiCell.SetData(true);
            }
        }
    }

    /// <summary>
    /// 移除选中的Cell图块
    /// </summary>
    private void OnRemoveCell(object arg)
    {
        if (arg is Vector2I cell)
        {
            var cellIndex = _leftBg.UiPanel.EditorPanel.CellPositionToIndex(cell);
            var uiCell = _maskGrid.GetCell(cellIndex);
            if (uiCell != null && uiCell.Data)
            {
                _useMask.Remove(cell);
                uiCell.SetData(false);
            }
        }
    }

    //缩小
    private void Shrink()
    {
        var textureRect = _leftBg.L_TileTexture.Instance;
        var offset = textureRect.GetLocalMousePosition();
        var prevScale = textureRect.Scale;
        var newScale = prevScale / 1.1f;
        if (newScale.LengthSquared() >= 0.5f)
        {
            textureRect.Scale = newScale;
            var position = textureRect.Position + offset * 0.1f * newScale;
            textureRect.Position = position;
            SetGridTransform(position, newScale.X);
        }
    }
    //放大
    private void Magnify()
    {
        var textureRect = _leftBg.L_TileTexture.Instance;
        var offset = textureRect.GetLocalMousePosition();
        var prevScale = textureRect.Scale;
        var newScale = prevScale * 1.1f;
        if (newScale.LengthSquared() <= 2000)
        {
            textureRect.Scale = newScale;
            var position = textureRect.Position - offset * 0.1f * prevScale;
            textureRect.Position = position;
            SetGridTransform(position, newScale.X);
        }
    }

    /// <summary>
    /// 当前Ui被显示出来时调用
    /// </summary>
    public void OnShow()
    {
        OnLeftBgResize();
    }

    //背景宽度变化
    private void OnLeftBgResize()
    {
        var sprite = _leftBg.L_TileTexture.Instance;
        var colorRect = _leftBg.L_Grid.Instance;
        colorRect.Material.SetShaderMaterialParameter(ShaderParamNames.Size, Size);
        SetGridTransform(sprite.Position, sprite.Scale.X);
    }

    /// <summary>
    /// 改变TileSet纹理
    /// </summary>
    public void OnChangeTileSetTexture(Texture2D texture)
    {
        _leftBg.L_TileTexture.Instance.Texture = texture;
        var width = _leftBg.UiPanel.EditorPanel.CellHorizontal;
        var height = _leftBg.UiPanel.EditorPanel.CellVertical;
        _maskGrid.RemoveAll();
        _useMask.Clear();
        _maskGrid.SetColumns(width);
        for (var i = 0; i < width; i++)
        {
            for (var j = 0; j < height; j++)
            {
                _maskGrid.Add(false);
            }
        }
    }

    //设置网格位置和缩放
    private void SetGridTransform(Vector2 pos, float scale)
    {
        var colorRect = _leftBg.L_Grid.Instance;
        colorRect.Material.SetShaderMaterialParameter(ShaderParamNames.GridSize, GameConfig.TileCellSize * scale);
        colorRect.Material.SetShaderMaterialParameter(ShaderParamNames.Offset, -pos);
    }
    
    /// <summary>
    /// 返回鼠标所在的单元格位置, 相对于纹理左上角
    /// </summary>
    public Vector2I GetMouseCellPosition()
    {
        var textureRect = _leftBg.L_TileTexture.Instance;
        var pos = textureRect.GetLocalMousePosition() / GameConfig.TileCellSize;
        return pos.AsVector2I();
    }
}