diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/EditorTools.tscn b/DungeonShooting_Godot/addons/dungeonShooting_plugin/EditorTools.tscn
new file mode 100644
index 0000000..02e3496
--- /dev/null
+++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/EditorTools.tscn
@@ -0,0 +1,57 @@
+[gd_scene load_steps=2 format=3 uid="uid://doyyiro45hwb6"]
+
+[ext_resource type="Script" path="res://addons/dungeonShooting_plugin/Tools.cs" id="1_y0p44"]
+
+[node name="EditorTools" type="Control"]
+layout_mode = 3
+anchors_preset = 15
+anchor_right = 1.0
+anchor_bottom = 1.0
+grow_horizontal = 2
+grow_vertical = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+script = ExtResource("1_y0p44")
+
+[node name="ScrollContainer" type="ScrollContainer" parent="."]
+layout_mode = 0
+anchor_right = 1.0
+anchor_bottom = 1.0
+
+[node name="MarginContainer" type="MarginContainer" parent="ScrollContainer"]
+layout_mode = 2
+size_flags_horizontal = 3
+size_flags_vertical = 3
+theme_override_constants/margin_left = 10
+theme_override_constants/margin_top = 10
+theme_override_constants/margin_right = 10
+theme_override_constants/margin_bottom = 10
+
+[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer/MarginContainer"]
+layout_mode = 2
+size_flags_horizontal = 3
+
+[node name="HBoxContainer" type="HBoxContainer" parent="ScrollContainer/MarginContainer/VBoxContainer"]
+layout_mode = 2
+
+[node name="Label" type="Label" parent="ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer"]
+layout_mode = 2
+text = "ResourcePath.cs"
+
+[node name="Button" type="Button" parent="ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer"]
+layout_mode = 2
+text = "重新生成"
+
+[node name="HBoxContainer2" type="HBoxContainer" parent="ScrollContainer/MarginContainer/VBoxContainer"]
+layout_mode = 2
+
+[node name="Label" type="Label" parent="ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer2"]
+layout_mode = 2
+text = "地牢房间配置"
+
+[node name="Button" type="Button" parent="ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer2"]
+layout_mode = 2
+text = "重新打包"
+
+[connection signal="pressed" from="ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer/Button" to="." method="_on_Button_pressed"]
+[connection signal="pressed" from="ScrollContainer/MarginContainer/VBoxContainer/HBoxContainer2/Button" to="." method="_on_Button2_pressed"]
diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/NodeMonitor.cs b/DungeonShooting_Godot/addons/dungeonShooting_plugin/NodeMonitor.cs
new file mode 100644
index 0000000..db423ba
--- /dev/null
+++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/NodeMonitor.cs
@@ -0,0 +1,132 @@
+#if TOOLS
+using System;
+using System.Collections.Generic;
+using Godot;
+
+namespace Plugin;
+
+///
+/// 场景监听器, 一旦当前节点内容发生改变, 则直接调用回调代码
+///
+public class NodeMonitor
+{
+ private class SceneNode : IEquatable
+ {
+ public SceneNode(string type, string name)
+ {
+ Type = type;
+ Name = name;
+ }
+
+ public string Type;
+ public string Name;
+ public List Children = new List();
+
+ public bool Equals(SceneNode other)
+ {
+ if (other == null)
+ {
+ return false;
+ }
+
+ if (other.Name != Name || other.Type != Type)
+ {
+ return false;
+ }
+
+ if (other.Children.Count != Children.Count)
+ {
+ return false;
+ }
+
+ for (var i = 0; i < Children.Count; i++)
+ {
+ if (!Children[i].Equals(other.Children[i]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ ///
+ /// 场景节点有变化时的回调事件
+ ///
+ public event Action SceneNodeChangeEvent;
+
+ private SceneNode _sceneNode;
+ private Node _targetNode;
+
+
+ private double _checkTreeTimer = 0;
+
+ ///
+ /// 更新监听的节点
+ ///
+ public void ChangeCurrentNode(Node node)
+ {
+ //更新前检查旧的节点是否发生改变
+ if (node != _targetNode && _targetNode != null)
+ {
+ var tempNode = ParseNodeTree(_targetNode);
+ if (!_sceneNode.Equals(tempNode))
+ {
+ OnSceneNodeChange(_targetNode);
+ }
+ }
+
+ if (node != null)
+ {
+ _sceneNode = ParseNodeTree(node);
+ _targetNode = node;
+ }
+ else
+ {
+ _targetNode = null;
+ }
+ _checkTreeTimer = 0;
+ }
+
+ public void Process(float delta)
+ {
+ if (_targetNode == null)
+ return;
+
+ _checkTreeTimer += delta;
+ if (_checkTreeTimer >= 1)
+ {
+ var tempNode = ParseNodeTree(_targetNode);
+ if (!_sceneNode.Equals(tempNode))
+ {
+ OnSceneNodeChange(_targetNode);
+ _sceneNode = tempNode;
+ }
+
+ _checkTreeTimer = 0;
+ }
+ }
+
+
+ private SceneNode ParseNodeTree(Node node)
+ {
+ var uiNode = new SceneNode(node.GetType().FullName, node.Name);
+ var count = node.GetChildCount();
+ for (var i = 0; i < count; i++)
+ {
+ uiNode.Children.Add(ParseNodeTree(node.GetChild(i)));
+ }
+
+ return uiNode;
+ }
+
+ private void OnSceneNodeChange(Node node)
+ {
+ if (SceneNodeChangeEvent != null)
+ {
+ SceneNodeChangeEvent(node);
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs
index 0132338..9f96b7e 100644
--- a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs
+++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs
@@ -1,4 +1,6 @@
#if TOOLS
+using System;
+using Generator;
using Godot;
namespace Plugin
@@ -6,14 +8,23 @@
[Tool]
public partial class Plugin : EditorPlugin
{
+ public const string UiResourcePath = "";
+
public static Plugin Instance => _instance;
private static Plugin _instance;
private Control dock;
+ //ui监听器
+ private NodeMonitor _uiMonitor;
+
public override void _Process(double delta)
{
_instance = this;
+ if (_uiMonitor != null)
+ {
+ _uiMonitor.Process((float) delta);
+ }
}
public override void _EnterTree()
@@ -37,13 +48,18 @@
var script5 = GD.Load