diff --git a/DungeonShooting_Godot/prefab/ui/TileSetEditorCombination.tscn b/DungeonShooting_Godot/prefab/ui/TileSetEditorCombination.tscn
index 393a3c2..67899fc 100644
--- a/DungeonShooting_Godot/prefab/ui/TileSetEditorCombination.tscn
+++ b/DungeonShooting_Godot/prefab/ui/TileSetEditorCombination.tscn
@@ -3,12 +3,12 @@
 [ext_resource type="Script" path="res://src/game/ui/tileSetEditorCombination/TileSetEditorCombinationPanel.cs" id="1_to1lc"]
 [ext_resource type="Script" path="res://src/game/ui/tileSetEditorCombination/leftBottom/TileEditArea.cs" id="2_h43yx"]
 [ext_resource type="Script" path="res://src/game/ui/tileSetEditorCombination/leftTop/RectBrush.cs" id="3_avikb"]
-[ext_resource type="Script" path="res://src/game/ui/tileSetEditorCombination/leftBottom/MaskBrush.cs" id="4_ytys0"]
 [ext_resource type="Texture2D" uid="uid://fkg21rtph51d" path="res://resource/sprite/ui/commonIcon/Delete2.png" id="5_6jqro"]
 [ext_resource type="Texture2D" uid="uid://7l7aqhsaexoh" path="res://resource/sprite/ui/commonIcon/Play.png" id="6_75xjp"]
 [ext_resource type="Script" path="res://src/game/ui/tileSetEditorCombination/leftTop/TileEditCombination.cs" id="6_bb3jf"]
 [ext_resource type="Texture2D" uid="uid://bn47bmilcw4x0" path="res://resource/sprite/ui/commonIcon/Select2.png" id="6_g5ey6"]
 [ext_resource type="Script" path="res://src/game/ui/tileSetEditorCombination/right/TileSelected.cs" id="6_gql80"]
+[ext_resource type="Script" path="res://src/game/common/ui/EditorMaskBrush.cs" id="7_k0dkc"]
 [ext_resource type="Texture2D" uid="uid://d2wslibovwv7w" path="res://resource/sprite/ui/commonIcon/CenterTool.png" id="7_mbnpy"]
 
 [node name="TileSetEditorCombination" type="Control"]
@@ -197,7 +197,7 @@
 grow_horizontal = 2
 grow_vertical = 2
 mouse_filter = 2
-script = ExtResource("4_ytys0")
+script = ExtResource("7_k0dkc")
 
 [node name="Grid" type="ColorRect" parent="HSplitContainer/VSplitContainer/LeftBottom/MarginContainer/LeftBottomBg"]
 layout_mode = 1
diff --git a/DungeonShooting_Godot/prefab/ui/TileSetEditorTerrain.tscn b/DungeonShooting_Godot/prefab/ui/TileSetEditorTerrain.tscn
index 684b926..6e940f0 100644
--- a/DungeonShooting_Godot/prefab/ui/TileSetEditorTerrain.tscn
+++ b/DungeonShooting_Godot/prefab/ui/TileSetEditorTerrain.tscn
@@ -1,7 +1,8 @@
-[gd_scene load_steps=4 format=3 uid="uid://dfqb73y4br8yd"]
+[gd_scene load_steps=5 format=3 uid="uid://dfqb73y4br8yd"]
 
 [ext_resource type="Script" path="res://src/game/ui/tileSetEditorTerrain/TileSetEditorTerrainPanel.cs" id="1_6jjk7"]
 [ext_resource type="Script" path="res://src/game/ui/tileSetEditorTerrain/left/TileEditArea.cs" id="2_ynf0r"]
+[ext_resource type="Script" path="res://src/game/common/ui/EditorMaskBrush.cs" id="3_gydh0"]
 [ext_resource type="Texture2D" uid="uid://d2wslibovwv7w" path="res://resource/sprite/ui/commonIcon/CenterTool.png" id="5_08bc4"]
 
 [node name="TileSetEditorTerrain" type="Control"]
@@ -67,6 +68,7 @@
 grow_horizontal = 2
 grow_vertical = 2
 mouse_filter = 2
+script = ExtResource("3_gydh0")
 
 [node name="Grid" type="ColorRect" parent="HSplitContainer/LeftBottom/MarginContainer/LeftBg"]
 layout_mode = 1
diff --git a/DungeonShooting_Godot/src/framework/common/GridBg.cs b/DungeonShooting_Godot/src/framework/common/GridBg.cs
deleted file mode 100644
index c89664e..0000000
--- a/DungeonShooting_Godot/src/framework/common/GridBg.cs
+++ /dev/null
@@ -1,108 +0,0 @@
-using Godot;
-
-/// <summary>
-/// 通用Ui网格背景组件, 包含可拖拽的容器根节点
-/// </summary>
-public abstract partial class GridBg<T> : ColorRect, IUiNodeScript where T : IUiNode
-{
-    /// <summary>
-    /// 可拖拽容器根节点
-    /// </summary>
-    public Control ContainerRoot { get; private set; }
-    /// <summary>
-    /// 显示网格的节点
-    /// </summary>
-    public ColorRect Grid { get; private set; }
-    /// <summary>
-    /// 当前对象绑定的Ui节点
-    /// </summary>
-    public T UiNode { get; private set; }
-    
-    private ShaderMaterial _gridMaterial;
-    
-    /// <summary>
-    /// 初始化节点数据
-    /// </summary>
-    /// <param name="containerRoot">可拖拽容器根节点</param>
-    /// <param name="grid">当前对象绑定的Ui节点</param>
-    public void InitNode(Control containerRoot, ColorRect grid)
-    {
-        ContainerRoot = containerRoot;
-        Grid = grid;
-        grid.MouseFilter = MouseFilterEnum.Ignore;
-        _gridMaterial = ResourceManager.Load<ShaderMaterial>(ResourcePath.resource_material_Grid_tres, false);
-        grid.Material = _gridMaterial;
-    }
-    
-    public virtual void SetUiNode(IUiNode uiNode)
-    {
-        UiNode = (T)uiNode;
-        this.AddDragListener(DragButtonEnum.Middle, OnDrag);
-        Resized += RefreshGridTrans;
-    }
-
-    public virtual void OnDestroy()
-    {
-        
-    }
-    
-    /// <summary>
-    /// 当前Ui被显示出来时调用
-    /// </summary>
-    public void OnShow()
-    {
-        RefreshGridTrans();
-    }
-
-    public override void _GuiInput(InputEvent @event)
-    {
-        if (@event is InputEventMouseButton mouseButton)
-        {
-            AcceptEvent();
-            if (mouseButton.ButtonIndex == MouseButton.WheelDown)
-            {
-                //缩小
-                if (Utils.DoShrinkByMousePosition(ContainerRoot, 0.4f))
-                {
-                    SetGridTransform(ContainerRoot.Position, ContainerRoot.Scale.X);
-                }
-            }
-            else if (mouseButton.ButtonIndex == MouseButton.WheelUp)
-            {
-                //放大
-                if (Utils.DoMagnifyByMousePosition(ContainerRoot, 20))
-                {
-                    SetGridTransform(ContainerRoot.Position, ContainerRoot.Scale.X);
-                }
-            }
-        }
-    }
-    
-    //拖拽回调
-    private void OnDrag(DragState state, Vector2 pos)
-    {
-        if (state == DragState.DragMove)
-        {
-            ContainerRoot.Position += pos;
-            RefreshGridTrans();
-        }
-    }
-    
-    
-    /// <summary>
-    /// 刷新背景网格位置和缩放
-    /// </summary>
-    public void RefreshGridTrans()
-    {
-        _gridMaterial.SetShaderMaterialParameter(ShaderParamNames.Size, Size);
-        SetGridTransform(ContainerRoot.Position, ContainerRoot.Scale.X);
-    }
-    
-    //设置网格位置和缩放
-    private void SetGridTransform(Vector2 pos, float scale)
-    {
-        _gridMaterial.SetShaderMaterialParameter(ShaderParamNames.GridSize, GameConfig.TileCellSize * scale);
-        _gridMaterial.SetShaderMaterialParameter(ShaderParamNames.Offset, -pos);
-    }
-    
-}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/common/Utils.cs b/DungeonShooting_Godot/src/framework/common/Utils.cs
index 28f327e..0bdcbd4 100644
--- a/DungeonShooting_Godot/src/framework/common/Utils.cs
+++ b/DungeonShooting_Godot/src/framework/common/Utils.cs
@@ -496,4 +496,13 @@
         control.Position = parentSize / 2 - selfSize * 0.5f * control.Scale;
     }
 
+    /// <summary>
+    /// 返回鼠标所在的单元格位置, 相对于Ui节点左上角
+    /// </summary>
+    public static Vector2I GetMouseCellPosition(Control control)
+    {
+        var pos = control.GetLocalMousePosition() / GameConfig.TileCellSize;
+        return pos.AsVector2I();
+    }
+
 }
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/ui/UiBase.cs b/DungeonShooting_Godot/src/framework/ui/UiBase.cs
index 230991e..f30270f 100644
--- a/DungeonShooting_Godot/src/framework/ui/UiBase.cs
+++ b/DungeonShooting_Godot/src/framework/ui/UiBase.cs
@@ -9,6 +9,19 @@
 public abstract partial class UiBase : Control, IDestroy, ICoroutine
 {
     /// <summary>
+    /// Ui显示事件
+    /// </summary>
+    public event Action OnShowUiEvent;
+    /// <summary>
+    /// Ui隐藏事件
+    /// </summary>
+    public event Action OnHideUiEvent;
+    /// <summary>
+    /// Ui销毁事件
+    /// </summary>
+    public event Action OnDestroyUiEvent;
+    
+    /// <summary>
     /// 当前 UI 所属层级
     /// </summary>
     [Export]
@@ -127,6 +140,10 @@
         IsOpen = true;
         Visible = true;
         OnShowUi();
+        if (OnShowUiEvent != null)
+        {
+            OnShowUiEvent();
+        }
         
         //子Ui调用显示
         if (_nestedUiSet != null)
@@ -160,6 +177,10 @@
         IsOpen = false;
         Visible = false;
         OnHideUi();
+        if (OnHideUiEvent != null)
+        {
+            OnHideUiEvent();
+        }
         
         //子Ui调用隐藏
         if (_nestedUiSet != null)
@@ -189,6 +210,10 @@
         HideUi();
         IsDestroyed = true;
         OnDestroyUi();
+        if (OnDestroyUiEvent != null)
+        {
+            OnDestroyUiEvent();
+        }
         
         //子Ui调用销毁
         if (_nestedUiSet != null)
diff --git a/DungeonShooting_Godot/src/game/common/ui/EditorGridBg.cs b/DungeonShooting_Godot/src/game/common/ui/EditorGridBg.cs
new file mode 100644
index 0000000..45d75c1
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/common/ui/EditorGridBg.cs
@@ -0,0 +1,102 @@
+using Godot;
+
+/// <summary>
+/// 通用Ui网格背景组件, 包含可拖拽的容器根节点
+/// </summary>
+public abstract partial class EditorGridBg<T> : ColorRect, IUiNodeScript where T : IUiNode
+{
+    /// <summary>
+    /// 可拖拽容器根节点
+    /// </summary>
+    public Control ContainerRoot { get; private set; }
+    /// <summary>
+    /// 显示网格的节点
+    /// </summary>
+    public ColorRect Grid { get; private set; }
+    /// <summary>
+    /// 当前对象绑定的Ui节点
+    /// </summary>
+    public T UiNode { get; private set; }
+    
+    private ShaderMaterial _gridMaterial;
+    
+    /// <summary>
+    /// 初始化节点数据
+    /// </summary>
+    /// <param name="containerRoot">可拖拽容器根节点</param>
+    /// <param name="grid">当前对象绑定的Ui节点</param>
+    public void InitNode(Control containerRoot, ColorRect grid)
+    {
+        ContainerRoot = containerRoot;
+        Grid = grid;
+        grid.MouseFilter = MouseFilterEnum.Ignore;
+        _gridMaterial = ResourceManager.Load<ShaderMaterial>(ResourcePath.resource_material_Grid_tres, false);
+        grid.Material = _gridMaterial;
+    }
+    
+    public virtual void SetUiNode(IUiNode uiNode)
+    {
+        UiNode = (T)uiNode;
+        this.AddDragListener(DragButtonEnum.Middle, OnDrag);
+        Resized += RefreshGridTrans;
+        //打开Ui时刷新网格
+        UiNode.GetUiPanel().OnShowUiEvent += RefreshGridTrans;
+    }
+
+    public virtual void OnDestroy()
+    {
+        
+    }
+
+    public override void _GuiInput(InputEvent @event)
+    {
+        if (@event is InputEventMouseButton mouseButton)
+        {
+            AcceptEvent();
+            if (mouseButton.ButtonIndex == MouseButton.WheelDown)
+            {
+                //缩小
+                if (Utils.DoShrinkByMousePosition(ContainerRoot, 0.4f))
+                {
+                    SetGridTransform(ContainerRoot.Position, ContainerRoot.Scale.X);
+                }
+            }
+            else if (mouseButton.ButtonIndex == MouseButton.WheelUp)
+            {
+                //放大
+                if (Utils.DoMagnifyByMousePosition(ContainerRoot, 20))
+                {
+                    SetGridTransform(ContainerRoot.Position, ContainerRoot.Scale.X);
+                }
+            }
+        }
+    }
+    
+    //拖拽回调
+    private void OnDrag(DragState state, Vector2 pos)
+    {
+        if (state == DragState.DragMove)
+        {
+            ContainerRoot.Position += pos;
+            RefreshGridTrans();
+        }
+    }
+    
+    
+    /// <summary>
+    /// 刷新背景网格位置和缩放
+    /// </summary>
+    public void RefreshGridTrans()
+    {
+        _gridMaterial.SetShaderMaterialParameter(ShaderParamNames.Size, Size);
+        SetGridTransform(ContainerRoot.Position, ContainerRoot.Scale.X);
+    }
+    
+    //设置网格位置和缩放
+    private void SetGridTransform(Vector2 pos, float scale)
+    {
+        _gridMaterial.SetShaderMaterialParameter(ShaderParamNames.GridSize, GameConfig.TileCellSize * scale);
+        _gridMaterial.SetShaderMaterialParameter(ShaderParamNames.Offset, -pos);
+    }
+    
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/common/ui/EditorMaskBrush.cs b/DungeonShooting_Godot/src/game/common/ui/EditorMaskBrush.cs
new file mode 100644
index 0000000..313e6cb
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/common/ui/EditorMaskBrush.cs
@@ -0,0 +1,55 @@
+using Godot;
+using UI.TileSetEditor;
+
+/// <summary>
+/// 地图编辑器通用遮罩笔刷
+/// </summary>
+public partial class EditorMaskBrush : Control
+{
+    /// <summary>
+    /// 绑定的地图纹理节点
+    /// </summary>
+    public TextureRect TileTexture { get; private set; }
+    
+    /// <summary>
+    /// 绑定的 TileSetEditorPanel Ui
+    /// </summary>
+    public TileSetEditorPanel TileSetEditorPanel { get; private set; }
+
+    /// <summary>
+    /// 初始化笔刷数绑定的节点
+    /// </summary>
+    public void Init(TextureRect tileTexture, TileSetEditorPanel tileSetEditorPanel)
+    {
+        TileTexture = tileTexture;
+        TileSetEditorPanel = tileSetEditorPanel;
+    }
+    
+    public override void _Process(double delta)
+    {
+        QueueRedraw();
+    }
+
+    public override void _Draw()
+    {
+        //绘制texture区域
+        if (TileTexture.Texture != null)
+        {
+            DrawRect(
+                new Rect2(Vector2.Zero, TileSetEditorPanel.CellHorizontal * GameConfig.TileCellSize, TileSetEditorPanel.CellVertical * GameConfig.TileCellSize),
+                new Color(1, 1, 0, 0.5f), false,
+                2f / TileTexture.Scale.X
+            );
+        }
+
+        //绘制鼠标悬停区域
+        if (TileTexture.IsMouseInRect())
+        {
+            var pos = Utils.GetMouseCellPosition(TileTexture) * GameConfig.TileCellSize;
+            DrawRect(
+                new Rect2(pos,GameConfig.TileCellSizeVector2I),
+                Colors.Green, false, 3f / TileTexture.Scale.X
+            );
+        }
+    }
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/TileSetEditorCombination.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/TileSetEditorCombination.cs
index 520e585..765eea6 100644
--- a/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/TileSetEditorCombination.cs
+++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/TileSetEditorCombination.cs
@@ -27,7 +27,6 @@
     {
         _ = L_HSplitContainer.L_VSplitContainer.L_LeftTop.L_MarginContainer.L_LeftTopBg;
         _ = L_HSplitContainer.L_VSplitContainer.L_LeftBottom.L_MarginContainer.L_LeftBottomBg;
-        _ = L_HSplitContainer.L_VSplitContainer.L_LeftBottom.L_MarginContainer.L_LeftBottomBg.L_TileTexture.L_MaskBrush;
         _ = L_HSplitContainer.L_Right.L_MarginContainer.L_RightBg;
 
     }
@@ -293,12 +292,12 @@
     }
 
     /// <summary>
-    /// 类型: <see cref="UI.TileSetEditorCombination.MaskBrush"/>, 路径: TileSetEditorCombination.HSplitContainer.VSplitContainer.LeftBottom.MarginContainer.LeftBottomBg.TileTexture.MaskBrush
+    /// 类型: <see cref="EditorMaskBrush"/>, 路径: TileSetEditorCombination.HSplitContainer.VSplitContainer.LeftBottom.MarginContainer.LeftBottomBg.TileTexture.MaskBrush
     /// </summary>
-    public class MaskBrush : UiNode<TileSetEditorCombinationPanel, UI.TileSetEditorCombination.MaskBrush, MaskBrush>
+    public class MaskBrush : UiNode<TileSetEditorCombinationPanel, EditorMaskBrush, MaskBrush>
     {
-        public MaskBrush(TileSetEditorCombinationPanel uiPanel, UI.TileSetEditorCombination.MaskBrush node) : base(uiPanel, node) {  }
-        public override MaskBrush Clone() => new (UiPanel, (UI.TileSetEditorCombination.MaskBrush)Instance.Duplicate());
+        public MaskBrush(TileSetEditorCombinationPanel uiPanel, EditorMaskBrush node) : base(uiPanel, node) {  }
+        public override MaskBrush Clone() => new (UiPanel, (EditorMaskBrush)Instance.Duplicate());
     }
 
     /// <summary>
@@ -320,13 +319,13 @@
         private MaskRoot _L_MaskRoot;
 
         /// <summary>
-        /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="UI.TileSetEditorCombination.MaskBrush"/>, 节点路径: TileSetEditorCombination.HSplitContainer.VSplitContainer.LeftBottom.MarginContainer.LeftBottomBg.MaskBrush
+        /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="EditorMaskBrush"/>, 节点路径: TileSetEditorCombination.HSplitContainer.VSplitContainer.LeftBottom.MarginContainer.LeftBottomBg.MaskBrush
         /// </summary>
         public MaskBrush L_MaskBrush
         {
             get
             {
-                if (_L_MaskBrush == null) _L_MaskBrush = new MaskBrush(UiPanel, Instance.GetNode<UI.TileSetEditorCombination.MaskBrush>("MaskBrush"));
+                if (_L_MaskBrush == null) _L_MaskBrush = new MaskBrush(UiPanel, Instance.GetNode<EditorMaskBrush>("MaskBrush"));
                 return _L_MaskBrush;
             }
         }
@@ -753,7 +752,7 @@
     public MaskRoot S_MaskRoot => L_HSplitContainer.L_VSplitContainer.L_LeftBottom.L_MarginContainer.L_LeftBottomBg.L_TileTexture.L_MaskRoot;
 
     /// <summary>
-    /// 场景中唯一名称的节点, 节点类型: <see cref="UI.TileSetEditorCombination.MaskBrush"/>, 节点路径: TileSetEditorCombination.HSplitContainer.VSplitContainer.LeftBottom.MarginContainer.LeftBottomBg.TileTexture.MaskBrush
+    /// 场景中唯一名称的节点, 节点类型: <see cref="EditorMaskBrush"/>, 节点路径: TileSetEditorCombination.HSplitContainer.VSplitContainer.LeftBottom.MarginContainer.LeftBottomBg.TileTexture.MaskBrush
     /// </summary>
     public MaskBrush S_MaskBrush => L_HSplitContainer.L_VSplitContainer.L_LeftBottom.L_MarginContainer.L_LeftBottomBg.L_TileTexture.L_MaskBrush;
 
diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/TileSetEditorCombinationPanel.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/TileSetEditorCombinationPanel.cs
index fd9368e..4cdefd3 100644
--- a/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/TileSetEditorCombinationPanel.cs
+++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/TileSetEditorCombinationPanel.cs
@@ -29,9 +29,6 @@
                 EditorPanel.TabGrid.SelectIndex = 0;
             });
         }
-
-        S_LeftTopBg.Instance.OnShow();
-        S_LeftBottomBg.Instance.OnShow();
     }
 
     public override void OnDestroyUi()
diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/leftBottom/MaskBrush.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/leftBottom/MaskBrush.cs
deleted file mode 100644
index d7c7f11..0000000
--- a/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/leftBottom/MaskBrush.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using Godot;
-
-namespace UI.TileSetEditorCombination;
-
-public partial class MaskBrush : Control, IUiNodeScript
-{
-    /// <summary>
-    /// 绑定的地图纹理节点
-    /// </summary>
-    public TextureRect TileTexture { get; private set; }
-    
-    /// <summary>
-    /// 绑定的TileSet编辑区域节点
-    /// </summary>
-    public TileEditArea TileEditArea { get; private set; }
-    
-    private TileSetEditorCombination.MaskBrush _maskBrush;
-    public override void _Process(double delta)
-    {
-        QueueRedraw();
-    }
-
-    public override void _Draw()
-    {
-        //绘制texture区域
-        if (TileTexture.Texture != null)
-        {
-            var editorPanel = TileEditArea.UiNode.UiPanel.EditorPanel;
-            DrawRect(
-                new Rect2(Vector2.Zero, editorPanel.CellHorizontal * GameConfig.TileCellSize, editorPanel.CellVertical * GameConfig.TileCellSize),
-                new Color(1, 1, 0, 0.5f), false,
-                2f / TileTexture.Scale.X
-            );
-        }
-
-        //绘制鼠标悬停区域
-        if (TileTexture.IsMouseInRect())
-        {
-            var pos = TileEditArea.GetMouseCellPosition() * GameConfig.TileCellSize;
-            DrawRect(
-                new Rect2(pos,GameConfig.TileCellSizeVector2I),
-                Colors.Green, false, 3f / TileTexture.Scale.X
-            );
-        }
-    }
-
-    public void SetUiNode(IUiNode uiNode)
-    {
-        _maskBrush = (TileSetEditorCombination.MaskBrush)uiNode;
-        TileTexture = _maskBrush.UiPanel.S_TileTexture.Instance;
-        TileEditArea = _maskBrush.UiPanel.S_LeftBottomBg.Instance;
-    }
-
-    public void OnDestroy()
-    {
-        
-    }
-}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/leftBottom/TileEditArea.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/leftBottom/TileEditArea.cs
index 1ed6f44..097d005 100644
--- a/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/leftBottom/TileEditArea.cs
+++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/leftBottom/TileEditArea.cs
@@ -3,7 +3,7 @@
 
 namespace UI.TileSetEditorCombination;
 
-public partial class TileEditArea : GridBg<TileSetEditorCombination.LeftBottomBg>
+public partial class TileEditArea : EditorGridBg<TileSetEditorCombination.LeftBottomBg>
 {
     private UiGrid<TileSetEditorCombination.MaskRect, bool> _maskGrid;
     private readonly HashSet<Vector2I> _useMask = new HashSet<Vector2I>();
@@ -13,6 +13,8 @@
         base.SetUiNode(uiNode);
         InitNode(UiNode.L_TileTexture.Instance, UiNode.L_Grid.Instance);
         UiNode.L_TileTexture.Instance.Texture = UiNode.UiPanel.EditorPanel.Texture;
+        var maskBrush = UiNode.L_TileTexture.L_MaskBrush.Instance;
+        maskBrush.Init(UiNode.L_TileTexture.Instance, UiNode.UiPanel.EditorPanel);
 
         _maskGrid = new UiGrid<TileSetEditorCombination.MaskRect, bool>(UiNode.L_TileTexture.L_MaskRoot.L_MaskRect, typeof(MaskRectCell));
         _maskGrid.SetCellOffset(Vector2I.Zero);
@@ -149,8 +151,6 @@
     /// </summary>
     public Vector2I GetMouseCellPosition()
     {
-        var textureRect = UiNode.L_TileTexture.Instance;
-        var pos = textureRect.GetLocalMousePosition() / GameConfig.TileCellSize;
-        return pos.AsVector2I();
+        return Utils.GetMouseCellPosition(UiNode.L_TileTexture.Instance);
     }
 }
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/leftTop/TileEditCombination.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/leftTop/TileEditCombination.cs
index 80ca5c6..40351a0 100644
--- a/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/leftTop/TileEditCombination.cs
+++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorCombination/leftTop/TileEditCombination.cs
@@ -5,7 +5,7 @@
 
 namespace UI.TileSetEditorCombination;
 
-public partial class TileEditCombination : GridBg<TileSetEditorCombination.LeftTopBg>
+public partial class TileEditCombination : EditorGridBg<TileSetEditorCombination.LeftTopBg>
 {
     // ------------------------------- 笔刷相关 -------------------------------
     //笔刷数据, kay: 代表原图中的坐标, 单位: 格
diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TileSetEditorTerrain.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TileSetEditorTerrain.cs
index 1d34d9e..42f6ca9 100644
--- a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TileSetEditorTerrain.cs
+++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TileSetEditorTerrain.cs
@@ -30,12 +30,12 @@
     }
 
     /// <summary>
-    /// 类型: <see cref="Godot.Control"/>, 路径: TileSetEditorTerrain.HSplitContainer.LeftBottom.MarginContainer.LeftBg.TileTexture.MaskBrush
+    /// 类型: <see cref="EditorMaskBrush"/>, 路径: TileSetEditorTerrain.HSplitContainer.LeftBottom.MarginContainer.LeftBg.TileTexture.MaskBrush
     /// </summary>
-    public class MaskBrush : UiNode<TileSetEditorTerrainPanel, Godot.Control, MaskBrush>
+    public class MaskBrush : UiNode<TileSetEditorTerrainPanel, EditorMaskBrush, MaskBrush>
     {
-        public MaskBrush(TileSetEditorTerrainPanel uiPanel, Godot.Control node) : base(uiPanel, node) {  }
-        public override MaskBrush Clone() => new (UiPanel, (Godot.Control)Instance.Duplicate());
+        public MaskBrush(TileSetEditorTerrainPanel uiPanel, EditorMaskBrush node) : base(uiPanel, node) {  }
+        public override MaskBrush Clone() => new (UiPanel, (EditorMaskBrush)Instance.Duplicate());
     }
 
     /// <summary>
@@ -44,13 +44,13 @@
     public class TileTexture : UiNode<TileSetEditorTerrainPanel, Godot.TextureRect, TileTexture>
     {
         /// <summary>
-        /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.Control"/>, 节点路径: TileSetEditorTerrain.HSplitContainer.LeftBottom.MarginContainer.LeftBg.MaskBrush
+        /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="EditorMaskBrush"/>, 节点路径: TileSetEditorTerrain.HSplitContainer.LeftBottom.MarginContainer.LeftBg.MaskBrush
         /// </summary>
         public MaskBrush L_MaskBrush
         {
             get
             {
-                if (_L_MaskBrush == null) _L_MaskBrush = new MaskBrush(UiPanel, Instance.GetNode<Godot.Control>("MaskBrush"));
+                if (_L_MaskBrush == null) _L_MaskBrush = new MaskBrush(UiPanel, Instance.GetNode<EditorMaskBrush>("MaskBrush"));
                 return _L_MaskBrush;
             }
         }
@@ -304,7 +304,7 @@
 
 
     /// <summary>
-    /// 场景中唯一名称的节点, 节点类型: <see cref="Godot.Control"/>, 节点路径: TileSetEditorTerrain.HSplitContainer.LeftBottom.MarginContainer.LeftBg.TileTexture.MaskBrush
+    /// 场景中唯一名称的节点, 节点类型: <see cref="EditorMaskBrush"/>, 节点路径: TileSetEditorTerrain.HSplitContainer.LeftBottom.MarginContainer.LeftBg.TileTexture.MaskBrush
     /// </summary>
     public MaskBrush S_MaskBrush => L_HSplitContainer.L_LeftBottom.L_MarginContainer.L_LeftBg.L_TileTexture.L_MaskBrush;
 
diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TileSetEditorTerrainPanel.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TileSetEditorTerrainPanel.cs
index f90a0bf..c99123c 100644
--- a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TileSetEditorTerrainPanel.cs
+++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TileSetEditorTerrainPanel.cs
@@ -22,11 +22,6 @@
     {
         
     }
-
-    public override void OnShowUi()
-    {
-        S_LeftBg.Instance.OnShow();
-    }
     
     //改变TileSet纹理
     private void OnSetTileTexture(object arg)
diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/left/TileEditArea.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/left/TileEditArea.cs
index 40ead48..95f738b 100644
--- a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/left/TileEditArea.cs
+++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/left/TileEditArea.cs
@@ -2,12 +2,14 @@
 
 namespace UI.TileSetEditorTerrain;
 
-public partial class TileEditArea : GridBg<TileSetEditorTerrain.LeftBg>
+public partial class TileEditArea : EditorGridBg<TileSetEditorTerrain.LeftBg>
 {
     public override void SetUiNode(IUiNode uiNode)
     {
         base.SetUiNode(uiNode);
         InitNode(UiNode.L_TileTexture.Instance, UiNode.L_Grid.Instance);
+        UiNode.L_TileTexture.L_MaskBrush.Instance.Init(UiNode.L_TileTexture.Instance, UiNode.UiPanel.EditorPanel);
+        
         UiNode.L_TileTexture.Instance.Texture = UiNode.UiPanel.EditorPanel.Texture;
         
         //聚焦按钮点击