diff --git a/DungeonShooting_Godot/prefab/ui/MapEditorCreateMark.tscn b/DungeonShooting_Godot/prefab/ui/MapEditorCreateMark.tscn
new file mode 100644
index 0000000..da3e9b7
--- /dev/null
+++ b/DungeonShooting_Godot/prefab/ui/MapEditorCreateMark.tscn
@@ -0,0 +1,10 @@
+[gd_scene load_steps=2 format=3 uid="uid://bt4xo2lb4h4rx"]
+
+[ext_resource type="Script" path="res://src/game/ui/mapEditorCreateMark/MapEditorCreateMarkPanel.cs" id="1_cjivg"]
+
+[node name="MapEditorCreateMark" type="Control"]
+layout_mode = 3
+anchors_preset = 0
+anchor_right = 1.0
+anchor_bottom = 1.0
+script = ExtResource("1_cjivg")
diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room1/Room1_preinstall.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room1/Room1_preinstall.json
index 9324841..b37673f 100644
--- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room1/Room1_preinstall.json
+++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/battle/Room1/Room1_preinstall.json
@@ -1 +1 @@
-[{"Name":"test1","Weight":100,"Remark":""}]
\ No newline at end of file
+[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":null}],[{"Position":null},{"Position":null}]]}]
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/generator/UiGenerator.cs b/DungeonShooting_Godot/src/framework/generator/UiGenerator.cs
index ef55ab1..2866849 100644
--- a/DungeonShooting_Godot/src/framework/generator/UiGenerator.cs
+++ b/DungeonShooting_Godot/src/framework/generator/UiGenerator.cs
@@ -167,16 +167,19 @@
                $"}}\n";
     }
 
-    private static string GenerateInitNestedUi(string layer, UiNodeInfo uiNodeInfo, string retraction)
+    private static string GenerateInitNestedUi(string parent, UiNodeInfo uiNodeInfo, string retraction)
     {
         var str = "";
         if (uiNodeInfo.IsRefUi)
         {
-            var uiInst = "inst" + _nestedIndex++;
-            str += retraction + $"    var {uiInst} = {layer}Instance;\n";
-            str += retraction + $"    RecordNestedUi({uiInst}, UiManager.RecordType.Open);\n";
-            str += retraction + $"    {uiInst}.OnCreateUi();\n";
-            str += retraction + $"    {uiInst}.OnInitNestedUi();\n\n";
+            var parentUi = "inst" + _nestedIndex++;
+            var uiNode = $"{parentUi}.{uiNodeInfo.Name}.Instance";
+            var parentNode = string.IsNullOrEmpty(parent) ? "this" : parent;
+            var parentNode2 = string.IsNullOrEmpty(parent) ? "null" : parentUi;
+            str += retraction + $"    var {parentUi} = {parentNode};\n";
+            str += retraction + $"    RecordNestedUi({uiNode}, {parentNode2}, UiManager.RecordType.Open);\n";
+            str += retraction + $"    {uiNode}.OnCreateUi();\n";
+            str += retraction + $"    {uiNode}.OnInitNestedUi();\n\n";
         }
         else
         {
@@ -185,7 +188,14 @@
                 for (var i = 0; i < uiNodeInfo.Children.Count; i++)
                 {
                     var item = uiNodeInfo.Children[i];
-                    str += GenerateInitNestedUi(layer + item.Name + ".", item, retraction);
+                    if (uiNodeInfo.OriginName == uiNodeInfo.UiRootName)
+                    {
+                        str += GenerateInitNestedUi("", item, retraction);
+                    }
+                    else
+                    {
+                        str += GenerateInitNestedUi(parent + (string.IsNullOrEmpty(parent)? "" : ".") + uiNodeInfo.Name, item, retraction);
+                    }
                 }
             }
         }
@@ -218,7 +228,7 @@
             cloneCode = retraction + $"    public override {uiNodeInfo.ClassName} Clone()\n";
             cloneCode += retraction + $"    {{\n";
             cloneCode += retraction + $"        var uiNode = new {uiNodeInfo.ClassName}(UiPanel, ({uiNodeInfo.NodeTypeName})Instance.Duplicate());\n";
-            cloneCode += retraction + $"        UiPanel.RecordNestedUi(uiNode.Instance, UiManager.RecordType.Open);\n";
+            cloneCode += retraction + $"        UiPanel.RecordNestedUi(uiNode.Instance, this, UiManager.RecordType.Open);\n";
             cloneCode += retraction + $"        uiNode.Instance.OnCreateUi();\n";
             cloneCode += retraction + $"        uiNode.Instance.OnInitNestedUi();\n";
             cloneCode += retraction + $"        return uiNode;\n";
diff --git a/DungeonShooting_Godot/src/framework/map/data/MarkInfo.cs b/DungeonShooting_Godot/src/framework/map/data/MarkInfo.cs
new file mode 100644
index 0000000..e184a37
--- /dev/null
+++ b/DungeonShooting_Godot/src/framework/map/data/MarkInfo.cs
@@ -0,0 +1,11 @@
+
+using System.Text.Json.Serialization;
+
+/// <summary>
+/// 标记数据
+/// </summary>
+public class MarkInfo
+{
+    [JsonInclude]
+    public SerializeVector2 Position;
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/map/data/RoomPreinstall.cs b/DungeonShooting_Godot/src/framework/map/data/RoomPreinstall.cs
index b8fc223..a46fc8d 100644
--- a/DungeonShooting_Godot/src/framework/map/data/RoomPreinstall.cs
+++ b/DungeonShooting_Godot/src/framework/map/data/RoomPreinstall.cs
@@ -1,4 +1,5 @@
 
+using System.Collections.Generic;
 using System.Text.Json.Serialization;
 
 /// <summary>
@@ -23,4 +24,10 @@
     /// </summary>
     [JsonInclude]
     public string Remark;
+
+    /// <summary>
+    /// 波数数据
+    /// </summary>
+    [JsonInclude]
+    public List<List<MarkInfo>> WaveList;
 }
\ 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 3b7562a..0960821 100644
--- a/DungeonShooting_Godot/src/framework/ui/UiBase.cs
+++ b/DungeonShooting_Godot/src/framework/ui/UiBase.cs
@@ -35,6 +35,12 @@
     /// 注意: 如果是在预制体中放置的子 Ui, 那么子 Ui 的该属性会在 父 Ui 的 OnCreateUi() 之后赋值
     /// </summary>
     public UiBase ParentUi { get; private set; }
+    
+    /// <summary>
+    /// 所属父级节点, 仅当通过 UiNode.OpenNestedUi() 打开时才会赋值<br/>
+    /// 注意: 如果是在预制体中放置的子 Ui, 那么子 Ui 的该属性会在 父 Ui 的 OnCreateUi() 之后赋值
+    /// </summary>
+    public UiNode ParentNode { get; private set; }
 
     //开启的协程
     private List<CoroutineData> _coroutineList;
@@ -167,7 +173,7 @@
         //在父Ui中移除当前Ui
         if (ParentUi != null)
         {
-            ParentUi.RecordNestedUi(this, UiManager.RecordType.Close);
+            ParentUi.RecordNestedUi(this, null, UiManager.RecordType.Close);
         }
         
         QueueFree();
@@ -190,16 +196,45 @@
     }
 
     /// <summary>
+    /// 嵌套打开子ui
+    /// </summary>
+    public UiBase OpenNestedUi(string uiName, UiBase prevUi = null)
+    {
+        var packedScene = ResourceManager.Load<PackedScene>("res://" + GameConfig.UiPrefabDir + uiName + ".tscn");
+        var uiBase = packedScene.Instantiate<UiBase>();
+        uiBase.PrevUi = prevUi;
+        AddChild(uiBase);
+        RecordNestedUi(uiBase, null, UiManager.RecordType.Open);
+        
+        uiBase.OnCreateUi();
+        uiBase.OnInitNestedUi();
+        if (IsOpen)
+        {
+            uiBase.ShowUi();
+        }
+        
+        return uiBase;
+    }
+
+    /// <summary>
+    /// 嵌套打开子ui
+    /// </summary>
+    public T OpenNestedUi<T>(string uiName, UiBase prevUi = null) where T : UiBase
+    {
+        return (T)OpenNestedUi(uiName, prevUi);
+    }
+
+    /// <summary>
     /// 记录嵌套打开/关闭的UI
     /// </summary>
-    public void RecordNestedUi(UiBase uiBase, UiManager.RecordType type)
+    public void RecordNestedUi(UiBase uiBase, UiNode node, UiManager.RecordType type)
     {
         if (type == UiManager.RecordType.Open)
         {
             if (uiBase.ParentUi != null && uiBase.ParentUi != this)
             {
                 GD.PrintErr($"子Ui:'{uiBase.UiName}'已经被其他Ui:'{uiBase.ParentUi.UiName}'嵌套打开!");
-                uiBase.ParentUi.RecordNestedUi(uiBase, UiManager.RecordType.Close);
+                uiBase.ParentUi.RecordNestedUi(uiBase, node, UiManager.RecordType.Close);
             }
             if (_nestedUiSet == null)
             {
@@ -207,6 +242,7 @@
             }
 
             uiBase.ParentUi = this;
+            uiBase.ParentNode = node;
             _nestedUiSet.Add(uiBase);
         }
         else
@@ -214,6 +250,7 @@
             if (uiBase.ParentUi == this)
             {
                 uiBase.ParentUi = null;
+                uiBase.ParentNode = null;
             }
             else
             {
@@ -235,7 +272,22 @@
     /// <param name="uiName">下一级Ui的名称</param>
     public UiBase OpenNextUi(string uiName)
     {
-        var uiBase = UiManager.OpenUi(uiName, this);
+        UiBase uiBase;
+        if (ParentUi != null) //说明当前Ui是嵌套Ui
+        {
+            if (ParentNode != null) //子层级打开
+            {
+                uiBase = ParentNode.OpenNestedUi(uiName, this);
+            }
+            else
+            {
+                uiBase = ParentUi.OpenNestedUi(uiName, this);
+            }
+        }
+        else //正常打开
+        {
+            uiBase = UiManager.OpenUi(uiName, this);
+        }
         HideUi();
         return uiBase;
     }
diff --git a/DungeonShooting_Godot/src/framework/ui/UiMode.cs b/DungeonShooting_Godot/src/framework/ui/UiMode.cs
deleted file mode 100644
index d4d9ccb..0000000
--- a/DungeonShooting_Godot/src/framework/ui/UiMode.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-
-public enum UiMode
-{
-    /// <summary>
-    /// 正常模式,可以开多个相同的 Ui
-    /// </summary>
-    Normal,
-    /// <summary>
-    /// 单例模式, 只能同时打开一个相同的 Ui
-    /// </summary>
-    Singleton,
-}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/ui/UiNode.cs b/DungeonShooting_Godot/src/framework/ui/UiNode.cs
index f3ee7f4..82eb479 100644
--- a/DungeonShooting_Godot/src/framework/ui/UiNode.cs
+++ b/DungeonShooting_Godot/src/framework/ui/UiNode.cs
@@ -7,6 +7,21 @@
 public abstract class UiNode
 {
     /// <summary>
+    /// 嵌套打开子ui
+    /// </summary>
+    public abstract UiBase OpenNestedUi(string uiName, UiBase prevUi = null);
+
+    /// <summary>
+    /// 嵌套打开子ui
+    /// </summary>
+    public abstract T OpenNestedUi<T>(string uiName, UiBase prevUi = null) where T : UiBase;
+    
+    /// <summary>
+    /// 获取所属Ui面板
+    /// </summary>
+    public abstract UiBase GetUiPanel();
+    
+    /// <summary>
     /// 获取Ui实例
     /// </summary>
     public abstract Node GetUiInstance();
@@ -49,15 +64,13 @@
         Instance = node;
     }
     
-    /// <summary>
-    /// 嵌套打开子ui
-    /// </summary>
-    public UiBase OpenNestedUi(string uiName)
+    public override UiBase OpenNestedUi(string uiName, UiBase prevUi = null)
     {
         var packedScene = ResourceManager.Load<PackedScene>("res://" + GameConfig.UiPrefabDir + uiName + ".tscn");
         var uiBase = packedScene.Instantiate<UiBase>();
+        uiBase.PrevUi = prevUi;
         Instance.AddChild(uiBase);
-        UiPanel.RecordNestedUi(uiBase, UiManager.RecordType.Open);
+        UiPanel.RecordNestedUi(uiBase, this, UiManager.RecordType.Open);
         
         uiBase.OnCreateUi();
         uiBase.OnInitNestedUi();
@@ -69,12 +82,9 @@
         return uiBase;
     }
     
-    /// <summary>
-    /// 嵌套打开子ui
-    /// </summary>
-    public T OpenNestedUi<T>(string uiName) where T : UiBase
+    public override T OpenNestedUi<T>(string uiName, UiBase prevUi = null)
     {
-        return (T)OpenNestedUi(uiName);
+        return (T)OpenNestedUi(uiName, prevUi);
     }
 
     /// <summary>
@@ -86,7 +96,12 @@
         Instance.GetParent().AddChild(inst.GetUiInstance());
         return inst;
     }
-    
+
+    public override UiBase GetUiPanel()
+    {
+        return UiPanel;
+    }
+
     public override Node GetUiInstance()
     {
         return Instance;
diff --git a/DungeonShooting_Godot/src/game/manager/EditorWindowManager.cs b/DungeonShooting_Godot/src/game/manager/EditorWindowManager.cs
index 3726c40..a0777bc 100644
--- a/DungeonShooting_Godot/src/game/manager/EditorWindowManager.cs
+++ b/DungeonShooting_Godot/src/game/manager/EditorWindowManager.cs
@@ -5,6 +5,7 @@
 using UI.EditorTips;
 using UI.EditorWindow;
 using UI.MapEditorCreateGroup;
+using UI.MapEditorCreateMark;
 using UI.MapEditorCreatePreinstall;
 using UI.MapEditorCreateRoom;
 
@@ -155,6 +156,29 @@
             })
         );
     }
+
+    public static void ShowCreateMark()
+    {
+        var window = UiManager.Open_EditorWindow();
+        window.SetWindowTitle("创建标记");
+        window.SetWindowSize(new Vector2I(700, 600));
+        var body = window.OpenBody<MapEditorCreateMarkPanel>(UiManager.UiName.MapEditorCreateMark);
+        window.SetButtonList(
+            new EditorWindowPanel.ButtonData("确定", () =>
+            {
+                // var roomPreinstall = body.GetRoomPreinstall(list);
+                // if (roomPreinstall != null)
+                // {
+                //     window.CloseWindow();
+                //     onCreatePreinstall(roomPreinstall);
+                // }
+            }),
+            new EditorWindowPanel.ButtonData("取消", () =>
+            {
+                window.CloseWindow();
+            })
+        );
+    }
     
     public static void ShowSelectObject(string title)
     {
diff --git a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs
index 5bf0865..460803b 100644
--- a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs
+++ b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs
@@ -54,6 +54,7 @@
     public const string prefab_ui_Main_tscn = "res://prefab/ui/Main.tscn";
     public const string prefab_ui_MapEditor_tscn = "res://prefab/ui/MapEditor.tscn";
     public const string prefab_ui_MapEditorCreateGroup_tscn = "res://prefab/ui/MapEditorCreateGroup.tscn";
+    public const string prefab_ui_MapEditorCreateMark_tscn = "res://prefab/ui/MapEditorCreateMark.tscn";
     public const string prefab_ui_MapEditorCreatePreinstall_tscn = "res://prefab/ui/MapEditorCreatePreinstall.tscn";
     public const string prefab_ui_MapEditorCreateRoom_tscn = "res://prefab/ui/MapEditorCreateRoom.tscn";
     public const string prefab_ui_MapEditorMapLayer_tscn = "res://prefab/ui/MapEditorMapLayer.tscn";
diff --git a/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs b/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs
index e076168..738391c 100644
--- a/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs
+++ b/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs
@@ -14,6 +14,7 @@
         public const string Main = "Main";
         public const string MapEditor = "MapEditor";
         public const string MapEditorCreateGroup = "MapEditorCreateGroup";
+        public const string MapEditorCreateMark = "MapEditorCreateMark";
         public const string MapEditorCreatePreinstall = "MapEditorCreatePreinstall";
         public const string MapEditorCreateRoom = "MapEditorCreateRoom";
         public const string MapEditorMapLayer = "MapEditorMapLayer";
@@ -410,6 +411,54 @@
     }
 
     /// <summary>
+    /// 创建 MapEditorCreateMark, 并返回UI实例, 该函数不会打开 Ui
+    /// </summary>
+    public static UI.MapEditorCreateMark.MapEditorCreateMarkPanel Create_MapEditorCreateMark()
+    {
+        return CreateUi<UI.MapEditorCreateMark.MapEditorCreateMarkPanel>(UiName.MapEditorCreateMark);
+    }
+
+    /// <summary>
+    /// 打开 MapEditorCreateMark, 并返回UI实例
+    /// </summary>
+    public static UI.MapEditorCreateMark.MapEditorCreateMarkPanel Open_MapEditorCreateMark()
+    {
+        return OpenUi<UI.MapEditorCreateMark.MapEditorCreateMarkPanel>(UiName.MapEditorCreateMark);
+    }
+
+    /// <summary>
+    /// 隐藏 MapEditorCreateMark 的所有实例
+    /// </summary>
+    public static void Hide_MapEditorCreateMark()
+    {
+        var uiInstance = Get_MapEditorCreateMark_Instance();
+        foreach (var uiPanel in uiInstance)
+        {
+            uiPanel.HideUi();
+        }
+    }
+
+    /// <summary>
+    /// 销毁 MapEditorCreateMark 的所有实例
+    /// </summary>
+    public static void Destroy_MapEditorCreateMark()
+    {
+        var uiInstance = Get_MapEditorCreateMark_Instance();
+        foreach (var uiPanel in uiInstance)
+        {
+            uiPanel.Destroy();
+        }
+    }
+
+    /// <summary>
+    /// 获取所有 MapEditorCreateMark 的实例, 如果没有实例, 则返回一个空数组
+    /// </summary>
+    public static UI.MapEditorCreateMark.MapEditorCreateMarkPanel[] Get_MapEditorCreateMark_Instance()
+    {
+        return GetUiInstance<UI.MapEditorCreateMark.MapEditorCreateMarkPanel>(nameof(UI.MapEditorCreateMark.MapEditorCreateMark));
+    }
+
+    /// <summary>
     /// 创建 MapEditorCreatePreinstall, 并返回UI实例, 该函数不会打开 Ui
     /// </summary>
     public static UI.MapEditorCreatePreinstall.MapEditorCreatePreinstallPanel Create_MapEditorCreatePreinstall()
diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditor.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditor.cs
index 7503e68..69d293c 100644
--- a/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditor.cs
+++ b/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditor.cs
@@ -12,7 +12,7 @@
     {
         get
         {
-            if (_L_Bg == null) _L_Bg = new Bg(this, GetNodeOrNull<Godot.Panel>("Bg"));
+            if (_L_Bg == null) _L_Bg = new Bg((MapEditorPanel)this, GetNodeOrNull<Godot.Panel>("Bg"));
             return _L_Bg;
         }
     }
@@ -25,36 +25,36 @@
 
     public sealed override void OnInitNestedUi()
     {
-        var inst1 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_Left.L_MarginContainer.L_MapView.L_SubViewport.L_CanvasLayer.L_MapEditorTools.Instance;
-        RecordNestedUi(inst1, UiManager.RecordType.Open);
-        inst1.OnCreateUi();
-        inst1.OnInitNestedUi();
+        var inst1 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_Left.L_MarginContainer.L_MapView.L_SubViewport.L_CanvasLayer;
+        RecordNestedUi(inst1.L_MapEditorTools.Instance, inst1, UiManager.RecordType.Open);
+        inst1.L_MapEditorTools.Instance.OnCreateUi();
+        inst1.L_MapEditorTools.Instance.OnInitNestedUi();
 
-        var inst2 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_Right.L_MarginContainer.L_TabContainer.L_MapLayer.L_MapEditorMapLayer.Instance;
-        RecordNestedUi(inst2, UiManager.RecordType.Open);
-        inst2.OnCreateUi();
-        inst2.OnInitNestedUi();
+        var inst2 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_Right.L_MarginContainer.L_TabContainer.L_MapLayer;
+        RecordNestedUi(inst2.L_MapEditorMapLayer.Instance, inst2, UiManager.RecordType.Open);
+        inst2.L_MapEditorMapLayer.Instance.OnCreateUi();
+        inst2.L_MapEditorMapLayer.Instance.OnInitNestedUi();
 
-        var inst3 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_Right.L_MarginContainer.L_TabContainer.L_MapMark.L_MapEditorMapMark.Instance;
-        RecordNestedUi(inst3, UiManager.RecordType.Open);
-        inst3.OnCreateUi();
-        inst3.OnInitNestedUi();
+        var inst3 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_Right.L_MarginContainer.L_TabContainer.L_MapMark;
+        RecordNestedUi(inst3.L_MapEditorMapMark.Instance, inst3, UiManager.RecordType.Open);
+        inst3.L_MapEditorMapMark.Instance.OnCreateUi();
+        inst3.L_MapEditorMapMark.Instance.OnInitNestedUi();
 
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.Button"/>, 路径: MapEditor.Bg.VBoxContainer.Head.Back
     /// </summary>
-    public class Back : UiNode<MapEditor, Godot.Button, Back>
+    public class Back : UiNode<MapEditorPanel, Godot.Button, Back>
     {
-        public Back(MapEditor uiPanel, Godot.Button node) : base(uiPanel, node) {  }
+        public Back(MapEditorPanel uiPanel, Godot.Button node) : base(uiPanel, node) {  }
         public override Back Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.Panel"/>, 路径: MapEditor.Bg.VBoxContainer.Head
     /// </summary>
-    public class Head : UiNode<MapEditor, Godot.Panel, Head>
+    public class Head : UiNode<MapEditorPanel, Godot.Panel, Head>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.Button"/>, 节点路径: MapEditor.Bg.VBoxContainer.Back
@@ -69,23 +69,23 @@
         }
         private Back _L_Back;
 
-        public Head(MapEditor uiPanel, Godot.Panel node) : base(uiPanel, node) {  }
+        public Head(MapEditorPanel uiPanel, Godot.Panel node) : base(uiPanel, node) {  }
         public override Head Clone() => new (UiPanel, (Godot.Panel)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.AnimationPlayer"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.TileMap.ErrorCell.ErrorCellAnimationPlayer
     /// </summary>
-    public class ErrorCellAnimationPlayer : UiNode<MapEditor, Godot.AnimationPlayer, ErrorCellAnimationPlayer>
+    public class ErrorCellAnimationPlayer : UiNode<MapEditorPanel, Godot.AnimationPlayer, ErrorCellAnimationPlayer>
     {
-        public ErrorCellAnimationPlayer(MapEditor uiPanel, Godot.AnimationPlayer node) : base(uiPanel, node) {  }
+        public ErrorCellAnimationPlayer(MapEditorPanel uiPanel, Godot.AnimationPlayer node) : base(uiPanel, node) {  }
         public override ErrorCellAnimationPlayer Clone() => new (UiPanel, (Godot.AnimationPlayer)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.Sprite2D"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.TileMap.ErrorCell
     /// </summary>
-    public class ErrorCell : UiNode<MapEditor, Godot.Sprite2D, ErrorCell>
+    public class ErrorCell : UiNode<MapEditorPanel, Godot.Sprite2D, ErrorCell>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.AnimationPlayer"/>, 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.TileMap.ErrorCellAnimationPlayer
@@ -100,23 +100,23 @@
         }
         private ErrorCellAnimationPlayer _L_ErrorCellAnimationPlayer;
 
-        public ErrorCell(MapEditor uiPanel, Godot.Sprite2D node) : base(uiPanel, node) {  }
+        public ErrorCell(MapEditorPanel uiPanel, Godot.Sprite2D node) : base(uiPanel, node) {  }
         public override ErrorCell Clone() => new (UiPanel, (Godot.Sprite2D)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.Node2D"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.TileMap.Brush
     /// </summary>
-    public class Brush : UiNode<MapEditor, Godot.Node2D, Brush>
+    public class Brush : UiNode<MapEditorPanel, Godot.Node2D, Brush>
     {
-        public Brush(MapEditor uiPanel, Godot.Node2D node) : base(uiPanel, node) {  }
+        public Brush(MapEditorPanel uiPanel, Godot.Node2D node) : base(uiPanel, node) {  }
         public override Brush Clone() => new (UiPanel, (Godot.Node2D)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="UI.MapEditor.EditorTileMap"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.TileMap
     /// </summary>
-    public class TileMap : UiNode<MapEditor, UI.MapEditor.EditorTileMap, TileMap>
+    public class TileMap : UiNode<MapEditorPanel, UI.MapEditor.EditorTileMap, TileMap>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.Sprite2D"/>, 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.ErrorCell
@@ -144,20 +144,20 @@
         }
         private Brush _L_Brush;
 
-        public TileMap(MapEditor uiPanel, UI.MapEditor.EditorTileMap node) : base(uiPanel, node) {  }
+        public TileMap(MapEditorPanel uiPanel, UI.MapEditor.EditorTileMap node) : base(uiPanel, node) {  }
         public override TileMap Clone() => new (UiPanel, (UI.MapEditor.EditorTileMap)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="UI.MapEditorTools.MapEditorToolsPanel"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.CanvasLayer.MapEditorTools
     /// </summary>
-    public class MapEditorTools : UiNode<MapEditor, UI.MapEditorTools.MapEditorToolsPanel, MapEditorTools>
+    public class MapEditorTools : UiNode<MapEditorPanel, UI.MapEditorTools.MapEditorToolsPanel, MapEditorTools>
     {
-        public MapEditorTools(MapEditor uiPanel, UI.MapEditorTools.MapEditorToolsPanel node) : base(uiPanel, node) {  }
+        public MapEditorTools(MapEditorPanel uiPanel, UI.MapEditorTools.MapEditorToolsPanel node) : base(uiPanel, node) {  }
         public override MapEditorTools Clone()
         {
             var uiNode = new MapEditorTools(UiPanel, (UI.MapEditorTools.MapEditorToolsPanel)Instance.Duplicate());
-            UiPanel.RecordNestedUi(uiNode.Instance, UiManager.RecordType.Open);
+            UiPanel.RecordNestedUi(uiNode.Instance, this, UiManager.RecordType.Open);
             uiNode.Instance.OnCreateUi();
             uiNode.Instance.OnInitNestedUi();
             return uiNode;
@@ -167,7 +167,7 @@
     /// <summary>
     /// 类型: <see cref="Godot.CanvasLayer"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.CanvasLayer
     /// </summary>
-    public class CanvasLayer : UiNode<MapEditor, Godot.CanvasLayer, CanvasLayer>
+    public class CanvasLayer : UiNode<MapEditorPanel, Godot.CanvasLayer, CanvasLayer>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="UI.MapEditorTools.MapEditorToolsPanel"/>, 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.MapEditorTools
@@ -182,14 +182,14 @@
         }
         private MapEditorTools _L_MapEditorTools;
 
-        public CanvasLayer(MapEditor uiPanel, Godot.CanvasLayer node) : base(uiPanel, node) {  }
+        public CanvasLayer(MapEditorPanel uiPanel, Godot.CanvasLayer node) : base(uiPanel, node) {  }
         public override CanvasLayer Clone() => new (UiPanel, (Godot.CanvasLayer)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.SubViewport"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport
     /// </summary>
-    public class SubViewport : UiNode<MapEditor, Godot.SubViewport, SubViewport>
+    public class SubViewport : UiNode<MapEditorPanel, Godot.SubViewport, SubViewport>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="UI.MapEditor.EditorTileMap"/>, 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.TileMap
@@ -217,14 +217,14 @@
         }
         private CanvasLayer _L_CanvasLayer;
 
-        public SubViewport(MapEditor uiPanel, Godot.SubViewport node) : base(uiPanel, node) {  }
+        public SubViewport(MapEditorPanel uiPanel, Godot.SubViewport node) : base(uiPanel, node) {  }
         public override SubViewport Clone() => new (UiPanel, (Godot.SubViewport)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.SubViewportContainer"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView
     /// </summary>
-    public class MapView : UiNode<MapEditor, Godot.SubViewportContainer, MapView>
+    public class MapView : UiNode<MapEditorPanel, Godot.SubViewportContainer, MapView>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.SubViewport"/>, 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.SubViewport
@@ -239,14 +239,14 @@
         }
         private SubViewport _L_SubViewport;
 
-        public MapView(MapEditor uiPanel, Godot.SubViewportContainer node) : base(uiPanel, node) {  }
+        public MapView(MapEditorPanel uiPanel, Godot.SubViewportContainer node) : base(uiPanel, node) {  }
         public override MapView Clone() => new (UiPanel, (Godot.SubViewportContainer)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.MarginContainer"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer
     /// </summary>
-    public class MarginContainer : UiNode<MapEditor, Godot.MarginContainer, MarginContainer>
+    public class MarginContainer : UiNode<MapEditorPanel, Godot.MarginContainer, MarginContainer>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.SubViewportContainer"/>, 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MapView
@@ -261,14 +261,14 @@
         }
         private MapView _L_MapView;
 
-        public MarginContainer(MapEditor uiPanel, Godot.MarginContainer node) : base(uiPanel, node) {  }
+        public MarginContainer(MapEditorPanel uiPanel, Godot.MarginContainer node) : base(uiPanel, node) {  }
         public override MarginContainer Clone() => new (UiPanel, (Godot.MarginContainer)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.Panel"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left
     /// </summary>
-    public class Left : UiNode<MapEditor, Godot.Panel, Left>
+    public class Left : UiNode<MapEditorPanel, Godot.Panel, Left>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.MarginContainer"/>, 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.MarginContainer
@@ -283,20 +283,20 @@
         }
         private MarginContainer _L_MarginContainer;
 
-        public Left(MapEditor uiPanel, Godot.Panel node) : base(uiPanel, node) {  }
+        public Left(MapEditorPanel uiPanel, Godot.Panel node) : base(uiPanel, node) {  }
         public override Left Clone() => new (UiPanel, (Godot.Panel)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="UI.MapEditorMapLayer.MapEditorMapLayerPanel"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Right.MarginContainer.TabContainer.MapLayer.MapEditorMapLayer
     /// </summary>
-    public class MapEditorMapLayer : UiNode<MapEditor, UI.MapEditorMapLayer.MapEditorMapLayerPanel, MapEditorMapLayer>
+    public class MapEditorMapLayer : UiNode<MapEditorPanel, UI.MapEditorMapLayer.MapEditorMapLayerPanel, MapEditorMapLayer>
     {
-        public MapEditorMapLayer(MapEditor uiPanel, UI.MapEditorMapLayer.MapEditorMapLayerPanel node) : base(uiPanel, node) {  }
+        public MapEditorMapLayer(MapEditorPanel uiPanel, UI.MapEditorMapLayer.MapEditorMapLayerPanel node) : base(uiPanel, node) {  }
         public override MapEditorMapLayer Clone()
         {
             var uiNode = new MapEditorMapLayer(UiPanel, (UI.MapEditorMapLayer.MapEditorMapLayerPanel)Instance.Duplicate());
-            UiPanel.RecordNestedUi(uiNode.Instance, UiManager.RecordType.Open);
+            UiPanel.RecordNestedUi(uiNode.Instance, this, UiManager.RecordType.Open);
             uiNode.Instance.OnCreateUi();
             uiNode.Instance.OnInitNestedUi();
             return uiNode;
@@ -306,7 +306,7 @@
     /// <summary>
     /// 类型: <see cref="Godot.MarginContainer"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Right.MarginContainer.TabContainer.MapLayer
     /// </summary>
-    public class MapLayer : UiNode<MapEditor, Godot.MarginContainer, MapLayer>
+    public class MapLayer : UiNode<MapEditorPanel, Godot.MarginContainer, MapLayer>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="UI.MapEditorMapLayer.MapEditorMapLayerPanel"/>, 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Right.MarginContainer.TabContainer.MapEditorMapLayer
@@ -321,20 +321,20 @@
         }
         private MapEditorMapLayer _L_MapEditorMapLayer;
 
-        public MapLayer(MapEditor uiPanel, Godot.MarginContainer node) : base(uiPanel, node) {  }
+        public MapLayer(MapEditorPanel uiPanel, Godot.MarginContainer node) : base(uiPanel, node) {  }
         public override MapLayer Clone() => new (UiPanel, (Godot.MarginContainer)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="UI.MapEditorMapMark.MapEditorMapMarkPanel"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Right.MarginContainer.TabContainer.MapMark.MapEditorMapMark
     /// </summary>
-    public class MapEditorMapMark : UiNode<MapEditor, UI.MapEditorMapMark.MapEditorMapMarkPanel, MapEditorMapMark>
+    public class MapEditorMapMark : UiNode<MapEditorPanel, UI.MapEditorMapMark.MapEditorMapMarkPanel, MapEditorMapMark>
     {
-        public MapEditorMapMark(MapEditor uiPanel, UI.MapEditorMapMark.MapEditorMapMarkPanel node) : base(uiPanel, node) {  }
+        public MapEditorMapMark(MapEditorPanel uiPanel, UI.MapEditorMapMark.MapEditorMapMarkPanel node) : base(uiPanel, node) {  }
         public override MapEditorMapMark Clone()
         {
             var uiNode = new MapEditorMapMark(UiPanel, (UI.MapEditorMapMark.MapEditorMapMarkPanel)Instance.Duplicate());
-            UiPanel.RecordNestedUi(uiNode.Instance, UiManager.RecordType.Open);
+            UiPanel.RecordNestedUi(uiNode.Instance, this, UiManager.RecordType.Open);
             uiNode.Instance.OnCreateUi();
             uiNode.Instance.OnInitNestedUi();
             return uiNode;
@@ -344,7 +344,7 @@
     /// <summary>
     /// 类型: <see cref="Godot.MarginContainer"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Right.MarginContainer.TabContainer.MapMark
     /// </summary>
-    public class MapMark : UiNode<MapEditor, Godot.MarginContainer, MapMark>
+    public class MapMark : UiNode<MapEditorPanel, Godot.MarginContainer, MapMark>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="UI.MapEditorMapMark.MapEditorMapMarkPanel"/>, 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Right.MarginContainer.TabContainer.MapEditorMapMark
@@ -359,14 +359,14 @@
         }
         private MapEditorMapMark _L_MapEditorMapMark;
 
-        public MapMark(MapEditor uiPanel, Godot.MarginContainer node) : base(uiPanel, node) {  }
+        public MapMark(MapEditorPanel uiPanel, Godot.MarginContainer node) : base(uiPanel, node) {  }
         public override MapMark Clone() => new (UiPanel, (Godot.MarginContainer)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.TabContainer"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Right.MarginContainer.TabContainer
     /// </summary>
-    public class TabContainer : UiNode<MapEditor, Godot.TabContainer, TabContainer>
+    public class TabContainer : UiNode<MapEditorPanel, Godot.TabContainer, TabContainer>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.MarginContainer"/>, 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Right.MarginContainer.MapLayer
@@ -394,14 +394,14 @@
         }
         private MapMark _L_MapMark;
 
-        public TabContainer(MapEditor uiPanel, Godot.TabContainer node) : base(uiPanel, node) {  }
+        public TabContainer(MapEditorPanel uiPanel, Godot.TabContainer node) : base(uiPanel, node) {  }
         public override TabContainer Clone() => new (UiPanel, (Godot.TabContainer)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.MarginContainer"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Right.MarginContainer
     /// </summary>
-    public class MarginContainer_1 : UiNode<MapEditor, Godot.MarginContainer, MarginContainer_1>
+    public class MarginContainer_1 : UiNode<MapEditorPanel, Godot.MarginContainer, MarginContainer_1>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.TabContainer"/>, 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Right.TabContainer
@@ -416,14 +416,14 @@
         }
         private TabContainer _L_TabContainer;
 
-        public MarginContainer_1(MapEditor uiPanel, Godot.MarginContainer node) : base(uiPanel, node) {  }
+        public MarginContainer_1(MapEditorPanel uiPanel, Godot.MarginContainer node) : base(uiPanel, node) {  }
         public override MarginContainer_1 Clone() => new (UiPanel, (Godot.MarginContainer)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.Panel"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Right
     /// </summary>
-    public class Right : UiNode<MapEditor, Godot.Panel, Right>
+    public class Right : UiNode<MapEditorPanel, Godot.Panel, Right>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.MarginContainer"/>, 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.MarginContainer
@@ -438,14 +438,14 @@
         }
         private MarginContainer_1 _L_MarginContainer;
 
-        public Right(MapEditor uiPanel, Godot.Panel node) : base(uiPanel, node) {  }
+        public Right(MapEditorPanel uiPanel, Godot.Panel node) : base(uiPanel, node) {  }
         public override Right Clone() => new (UiPanel, (Godot.Panel)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.HSplitContainer"/>, 路径: MapEditor.Bg.VBoxContainer.HSplitContainer
     /// </summary>
-    public class HSplitContainer : UiNode<MapEditor, Godot.HSplitContainer, HSplitContainer>
+    public class HSplitContainer : UiNode<MapEditorPanel, Godot.HSplitContainer, HSplitContainer>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.Panel"/>, 节点路径: MapEditor.Bg.VBoxContainer.Left
@@ -473,14 +473,14 @@
         }
         private Right _L_Right;
 
-        public HSplitContainer(MapEditor uiPanel, Godot.HSplitContainer node) : base(uiPanel, node) {  }
+        public HSplitContainer(MapEditorPanel uiPanel, Godot.HSplitContainer node) : base(uiPanel, node) {  }
         public override HSplitContainer Clone() => new (UiPanel, (Godot.HSplitContainer)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.VBoxContainer"/>, 路径: MapEditor.Bg.VBoxContainer
     /// </summary>
-    public class VBoxContainer : UiNode<MapEditor, Godot.VBoxContainer, VBoxContainer>
+    public class VBoxContainer : UiNode<MapEditorPanel, Godot.VBoxContainer, VBoxContainer>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.Panel"/>, 节点路径: MapEditor.Bg.Head
@@ -508,14 +508,14 @@
         }
         private HSplitContainer _L_HSplitContainer;
 
-        public VBoxContainer(MapEditor uiPanel, Godot.VBoxContainer node) : base(uiPanel, node) {  }
+        public VBoxContainer(MapEditorPanel uiPanel, Godot.VBoxContainer node) : base(uiPanel, node) {  }
         public override VBoxContainer Clone() => new (UiPanel, (Godot.VBoxContainer)Instance.Duplicate());
     }
 
     /// <summary>
     /// 类型: <see cref="Godot.Panel"/>, 路径: MapEditor.Bg
     /// </summary>
-    public class Bg : UiNode<MapEditor, Godot.Panel, Bg>
+    public class Bg : UiNode<MapEditorPanel, Godot.Panel, Bg>
     {
         /// <summary>
         /// 使用 Instance 属性获取当前节点实例对象, 节点类型: <see cref="Godot.VBoxContainer"/>, 节点路径: MapEditor.VBoxContainer
@@ -530,7 +530,7 @@
         }
         private VBoxContainer _L_VBoxContainer;
 
-        public Bg(MapEditor uiPanel, Godot.Panel node) : base(uiPanel, node) {  }
+        public Bg(MapEditorPanel uiPanel, Godot.Panel node) : base(uiPanel, node) {  }
         public override Bg Clone() => new (UiPanel, (Godot.Panel)Instance.Duplicate());
     }
 
diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs
index eea44cd..de3e2cb 100644
--- a/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs
+++ b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs
@@ -115,8 +115,10 @@
     private int _terrain = 0;
     private AutoTileConfig _autoTileConfig = new AutoTileConfig();
     
-    //原数据
-    private DungeonRoomSplit _roomSplit;
+    /// <summary>
+    /// 正在编辑的房间数据
+    /// </summary>
+    public DungeonRoomSplit RoomSplit { get; private set; }
 
     //变动过的数据
     
@@ -382,6 +384,7 @@
     {
         SaveRoomInfoConfig();
         SaveTileInfoConfig();
+        SavePreinstallConfig();
     }
 
     /// <summary>
@@ -389,7 +392,12 @@
     /// </summary>
     public bool Load(DungeonRoomSplit roomSplit)
     {
-        _roomSplit = roomSplit;
+        //重新加载数据
+        roomSplit.ReloadRoomInfo();
+        roomSplit.ReloadTileInfo();
+        roomSplit.ReloadPreinstall();
+        
+        RoomSplit = roomSplit;
         var roomInfo = roomSplit.RoomInfo;
         var tileInfo = roomSplit.TileInfo;
 
@@ -421,6 +429,9 @@
         {
             MapEditorToolsPanel.CreateDoorTool(doorAreaInfo);
         }
+        
+        //聚焦
+        OnClickCenterTool(null);
         return true;
     }
 
@@ -858,7 +869,7 @@
     private void SaveRoomInfoConfig()
     {
         //存入本地
-        var roomInfo = _roomSplit.RoomInfo;
+        var roomInfo = RoomSplit.RoomInfo;
         var path = MapProjectManager.GetConfigPath(roomInfo.GroupName,roomInfo.RoomType, roomInfo.RoomName);
         if (!Directory.Exists(path))
         {
@@ -879,14 +890,14 @@
     public void SaveTileInfoConfig()
     {
         //存入本地
-        var roomInfo = _roomSplit.RoomInfo;
+        var roomInfo = RoomSplit.RoomInfo;
         var path = MapProjectManager.GetConfigPath(roomInfo.GroupName,roomInfo.RoomType, roomInfo.RoomName);
         if (!Directory.Exists(path))
         {
             Directory.CreateDirectory(path);
         }
 
-        var tileInfo = _roomSplit.TileInfo;
+        var tileInfo = RoomSplit.TileInfo;
         tileInfo.NavigationList.Clear();
         tileInfo.NavigationList.AddRange(_dungeonTileMap.GetPolygonData());
         tileInfo.Floor.Clear();
@@ -902,6 +913,22 @@
         File.WriteAllText(path, jsonStr);
     }
 
+    //保存预设数据
+    public void SavePreinstallConfig()
+    {
+        //存入本地
+        var roomInfo = RoomSplit.RoomInfo;
+        var path = MapProjectManager.GetConfigPath(roomInfo.GroupName,roomInfo.RoomType, roomInfo.RoomName);
+        if (!Directory.Exists(path))
+        {
+            Directory.CreateDirectory(path);
+        }
+
+        path += "/" + MapProjectManager.GetRoomPreinstallConfigName(roomInfo.RoomName);
+        var jsonStr = JsonSerializer.Serialize(RoomSplit.Preinstall);
+        File.WriteAllText(path, jsonStr);
+    }
+
     //设置地图坐标
     private void SetMapPosition(Vector2 pos)
     {
diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMapBar.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMapBar.cs
index eb9b839..aa73a0b 100644
--- a/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMapBar.cs
+++ b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMapBar.cs
@@ -14,12 +14,8 @@
         _editorTileMap.Instance.MapEditorToolsPanel = editorPanel.S_MapEditorTools.Instance;
         _editorTileMap.Instance.MapEditorToolsPanel.EditorMap = _editorTileMap;
 
-        _eventFactory = EventManager.CreateEventFactory();
-    }
-
-    public void OnShow()
-    {
         _editorTileMap.L_Brush.Instance.Draw += OnDrawGuides;
+        _eventFactory = EventManager.CreateEventFactory();
         _eventFactory.AddEventListener(EventEnum.OnSelectDragTool, _editorTileMap.Instance.OnSelectHandTool);
         _eventFactory.AddEventListener(EventEnum.OnSelectPenTool, _editorTileMap.Instance.OnSelectPenTool);
         _eventFactory.AddEventListener(EventEnum.OnSelectRectTool, _editorTileMap.Instance.OnSelectRectTool);
@@ -27,10 +23,14 @@
         _eventFactory.AddEventListener(EventEnum.OnClickCenterTool, _editorTileMap.Instance.OnClickCenterTool);
     }
 
+    public void OnShow()
+    {
+
+    }
+
     public void OnHide()
     {
-        _editorTileMap.L_Brush.Instance.Draw -= OnDrawGuides;
-        _eventFactory.RemoveAllEventListener();
+        
     }
 
     public void Process(float delta)
@@ -45,6 +45,7 @@
 
     public void OnDestroy()
     {
-        
+        _editorTileMap.L_Brush.Instance.Draw -= OnDrawGuides;
+        _eventFactory.RemoveAllEventListener();
     }
 }
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MapEditorCreateMark.cs b/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MapEditorCreateMark.cs
new file mode 100644
index 0000000..eadfbed
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MapEditorCreateMark.cs
@@ -0,0 +1,18 @@
+namespace UI.MapEditorCreateMark;
+
+/// <summary>
+/// Ui代码, 该类是根据ui场景自动生成的, 请不要手动编辑该类, 以免造成代码丢失
+/// </summary>
+public abstract partial class MapEditorCreateMark : UiBase
+{
+
+    public MapEditorCreateMark() : base(nameof(MapEditorCreateMark))
+    {
+    }
+
+    public sealed override void OnInitNestedUi()
+    {
+    }
+
+
+}
diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MapEditorCreateMarkPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MapEditorCreateMarkPanel.cs
new file mode 100644
index 0000000..868a2d8
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/ui/mapEditorCreateMark/MapEditorCreateMarkPanel.cs
@@ -0,0 +1,18 @@
+using Godot;
+
+namespace UI.MapEditorCreateMark;
+
+public partial class MapEditorCreateMarkPanel : MapEditorCreateMark
+{
+
+    public override void OnCreateUi()
+    {
+        
+    }
+
+    public override void OnDestroyUi()
+    {
+        
+    }
+
+}
diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorCreatePreinstall/MapEditorCreatePreinstallPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorCreatePreinstall/MapEditorCreatePreinstallPanel.cs
index 5cad8a5..a567119 100644
--- a/DungeonShooting_Godot/src/game/ui/mapEditorCreatePreinstall/MapEditorCreatePreinstallPanel.cs
+++ b/DungeonShooting_Godot/src/game/ui/mapEditorCreatePreinstall/MapEditorCreatePreinstallPanel.cs
@@ -30,6 +30,7 @@
         }
 
         data.Remark = S_RemarkInput.Instance.Text;
+        data.WaveList = new List<List<MarkInfo>>();
         data.Weight = (int)S_WeightInput.Instance.Value;
         return data;
     }
diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/EditorMarkCell.cs b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/EditorMarkCell.cs
index 17082cc..688af7c 100644
--- a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/EditorMarkCell.cs
+++ b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/EditorMarkCell.cs
@@ -1,6 +1,8 @@
-namespace UI.MapEditorMapMark;
+using System.Collections.Generic;
 
-public class EditorMarkCell : UiCell<MapEditorMapMark.MarkItem, object>
+namespace UI.MapEditorMapMark;
+
+public class EditorMarkCell : UiCell<MapEditorMapMark.MarkItem, MarkInfo>
 {
     public override void OnInit()
     {
diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/EditorWaveCell.cs b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/EditorWaveCell.cs
index 66b42e5..5224a77 100644
--- a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/EditorWaveCell.cs
+++ b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/EditorWaveCell.cs
@@ -1,26 +1,28 @@
-using Godot;
+using System.Collections.Generic;
+using Godot;
 
 namespace UI.MapEditorMapMark;
 
-public class EditorWaveCell : UiCell<MapEditorMapMark.WaveItem, object>
+public class EditorWaveCell : UiCell<MapEditorMapMark.WaveItem, List<MarkInfo>>
 {
-    private UiGrid<MapEditorMapMark.MarkItem, object> _grid;
+    private UiGrid<MapEditorMapMark.MarkItem, MarkInfo> _grid;
     
     public override void OnInit()
     {
         CellNode.L_WaveContainer.L_WaveButton.Instance.Pressed += OnClick;
         CellNode.L_WaveContainer.L_TextureButton.Instance.Pressed += OnExpandOrClose;
+        CellNode.L_MarginContainer.L_AddMarkButton.Instance.Pressed += OnAddMark;
 
         CellNode.L_MarkContainer.L_MarkItem.Instance.SetHorizontalExpand(true);
-        _grid = new UiGrid<MapEditorMapMark.MarkItem, object>(CellNode.L_MarkContainer.L_MarkItem, typeof(EditorMarkCell));
+        _grid = new UiGrid<MapEditorMapMark.MarkItem, MarkInfo>(CellNode.L_MarkContainer.L_MarkItem, typeof(EditorMarkCell));
         _grid.SetColumns(1);
         _grid.SetHorizontalExpand(true);
         _grid.SetCellOffset(new Vector2I(0, 5));
     }
 
-    public override void OnSetData(object data)
+    public override void OnSetData(List<MarkInfo> data)
     {
-        //_grid.SetDataList(new object[] { 1, 2, 3, 4, 5, 6, 7 });
+        _grid.SetDataList(data.ToArray());
     }
 
     public override void OnRefreshIndex()
@@ -33,6 +35,14 @@
         _grid.Destroy();
     }
 
+    private void OnAddMark()
+    {
+        EditorWindowManager.ShowCreateMark();
+        // var info = new MarkInfo();
+        // Data.Add(info);
+        // _grid.Add(info);
+    }
+    
     //展开/收起按钮点击
     private void OnExpandOrClose()
     {
diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs
index a00efa2..2449ccc 100644
--- a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs
+++ b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
 using Godot;
 using UI.MapEditor;
 
@@ -27,7 +28,7 @@
     /// </summary>
     public EditorTileMap EditorTileMap { get; private set; }
     
-    private UiGrid<WaveItem, object> _grid;
+    private UiGrid<WaveItem, List<MarkInfo>> _grid;
 
     public override void OnCreateUi()
     {
@@ -37,11 +38,11 @@
         S_DynamicTool.Instance.GetParent().RemoveChild(S_DynamicTool.Instance);
         S_DynamicTool.Instance.Visible = true;
         
-        _grid = new UiGrid<WaveItem, object>(S_WaveItem, typeof(EditorWaveCell));
+        _grid = new UiGrid<WaveItem, List<MarkInfo>>(S_WaveItem, typeof(EditorWaveCell));
         _grid.SetCellOffset(new Vector2I(0, 10));
         _grid.SetColumns(1);
-        
-        //_grid.SetDataList(new object[] { 1, 2, 3, 4});
+
+        S_PreinstallOption.Instance.ItemSelected += OnItemSelected;
         S_AddPreinstall.Instance.Pressed += OnAddPreinstall;
         S_AddWaveButton.Instance.Pressed += OnAddWave;
         
@@ -69,11 +70,32 @@
         optionButton.Clear();
         foreach (var item in preinstall)
         {
+            if (item.WaveList == null)
+            {
+                item.WaveList = new List<List<MarkInfo>>();
+            }
+
             optionButton.AddItem($"{item.Name} ({item.Weight})");
         }
 
         optionButton.Selected = selectIndex;
     }
+
+    /// <summary>
+    /// 下拉框选中项
+    /// </summary>
+    public void OnItemSelected(long index)
+    {
+        var preinstall = EditorTileMap.RoomSplit.Preinstall;
+        if (index >= 0 && index <= preinstall.Count)
+        {
+            _grid.SetDataList(preinstall[(int)index].WaveList.ToArray());
+        }
+        else
+        {
+            _grid.RemoveAll();
+        }
+    }
     
     /// <summary>
     /// 选中 cell, 并设置显示的工具
@@ -146,11 +168,23 @@
     /// </summary>
     public void OnAddWave()
     {
-        if (S_PreinstallOption.Instance.Selected == -1)
+        var index = S_PreinstallOption.Instance.Selected;
+        if (index == -1)
         {
             EditorWindowManager.ShowTips("警告", "请先选择预设!");
             return;
         }
+
+        var preinstall = EditorTileMap.RoomSplit.Preinstall;
+        if (index >= preinstall.Count)
+        {
+            EditorWindowManager.ShowTips("警告", "未知预设选项!");
+            return;
+        }
+        var item = preinstall[index];
+        var wave = new List<MarkInfo>();
+        item.WaveList.Add(wave);
+        _grid.Add(wave);
     }
     
     /// <summary>