diff --git a/DungeonShooting_Godot/DungeonShooting.csproj b/DungeonShooting_Godot/DungeonShooting.csproj index f909828..4d20267 100644 --- a/DungeonShooting_Godot/DungeonShooting.csproj +++ b/DungeonShooting_Godot/DungeonShooting.csproj @@ -1,6 +1,9 @@ - + net6.0 true + + + \ No newline at end of file diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.cs b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.cs deleted file mode 100644 index 576b44f..0000000 --- a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.cs +++ /dev/null @@ -1,24 +0,0 @@ -#if TOOLS -using Generator; -using Godot; - -[Tool] -public partial class Automation : Control -{ - /// - /// 更新 ResourcePath - /// - private void _on_Button_pressed() - { - ResourcePathGenerator.Generate(); - } - - /// - /// 重新打包房间配置 - /// - private void _on_Button2_pressed() - { - RoomPackGenerator.Generate(); - } -} -#endif \ No newline at end of file diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.tscn b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.tscn deleted file mode 100644 index 66d1942..0000000 --- a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Automation.tscn +++ /dev/null @@ -1,46 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://bygnukrvvm1vi"] - -[ext_resource type="Script" path="res://addons/dungeonShooting_plugin/Automation.cs" id="1"] - -[node name="Automation" type="Control"] -layout_mode = 3 -anchors_preset = 15 -anchor_right = 1.0 -anchor_bottom = 1.0 -grow_horizontal = 2 -grow_vertical = 2 -script = ExtResource("1") - -[node name="ScrollContainer" type="ScrollContainer" parent="."] -layout_mode = 0 -anchor_right = 1.0 -anchor_bottom = 1.0 - -[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer"] -layout_mode = 2 -size_flags_horizontal = 3 - -[node name="HBoxContainer" type="HBoxContainer" parent="ScrollContainer/VBoxContainer"] -layout_mode = 2 - -[node name="Label" type="Label" parent="ScrollContainer/VBoxContainer/HBoxContainer"] -layout_mode = 2 -text = "ResourcePath.cs" - -[node name="Button" type="Button" parent="ScrollContainer/VBoxContainer/HBoxContainer"] -layout_mode = 2 -text = "重新生成" - -[node name="HBoxContainer2" type="HBoxContainer" parent="ScrollContainer/VBoxContainer"] -layout_mode = 2 - -[node name="Label" type="Label" parent="ScrollContainer/VBoxContainer/HBoxContainer2"] -layout_mode = 2 -text = "地牢房间配置" - -[node name="Button" type="Button" parent="ScrollContainer/VBoxContainer/HBoxContainer2"] -layout_mode = 2 -text = "重新打包" - -[connection signal="pressed" from="ScrollContainer/VBoxContainer/HBoxContainer/Button" to="." method="_on_Button_pressed"] -[connection signal="pressed" from="ScrollContainer/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..fc17fff --- /dev/null +++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/NodeMonitor.cs @@ -0,0 +1,148 @@ +#if TOOLS +using System; +using System.Collections.Generic; +using Godot; + +namespace Plugin; + +/// +/// 场景监听器, 一旦当前节点内容发生改变, 则直接调用 SceneNodeChangeEvent 事件 +/// +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) + { + try + { + var tempNode = ParseNodeTree(_targetNode); + if (!_sceneNode.Equals(tempNode)) + { + OnSceneNodeChange(_targetNode); + } + } + catch (Exception e) + { + //检查节点存在报错, 直接跳过该节点的检查 + GD.Print(e.Message); + } + } + + 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 >= 5) //5秒检查一次 + { + try + { + var tempNode = ParseNodeTree(_targetNode); + if (!_sceneNode.Equals(tempNode)) + { + OnSceneNodeChange(_targetNode); + _sceneNode = tempNode; + } + } + catch (Exception e) + { + //检查节点存在报错, 直接跳过该节点的检查 + GD.Print(e.Message); + _targetNode = null; + } + _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 10ccbeb..27c2b46 100644 --- a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs +++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs @@ -1,61 +1,273 @@ #if TOOLS +using System; +using Generator; using Godot; +using UI.EditorTools; namespace Plugin { [Tool] public partial class Plugin : EditorPlugin { - public static Plugin Instance => _instance; - private static Plugin _instance; + /// + /// 自定义节点类型数据 + /// + private class CustomTypeInfo + { + public CustomTypeInfo(string name, string parentName, string scriptPath, string iconPath) + { + Name = name; + ParentName = parentName; + ScriptPath = scriptPath; + IconPath = iconPath; + } - private Control dock; + public string Name; + public string ParentName; + public string ScriptPath; + public string IconPath; + } + + /// + /// 当前插件实例 + /// + public static Plugin Instance { get; private set; } + //工具面板 + private EditorToolsPanel _editorTools; + + //ui监听器 + private NodeMonitor _uiMonitor; + + //自定义节点 + private CustomTypeInfo[] _customTypeInfos = new CustomTypeInfo[] + { + new CustomTypeInfo( + "ActivityObjectTemplate", + "Node", + "res://src/framework/activity/ActivityObjectTemplate.cs", + "res://addons/dungeonShooting_plugin/ActivityObject.svg" + ), + new CustomTypeInfo( + "DungeonRoomTemplate", + "TileMap", + "res://src/framework/activity/ActivityObjectTemplate.cs", + "res://addons/dungeonShooting_plugin/Map.svg" + ), + new CustomTypeInfo( + "ActivityMark", + "Node2D", + "res://src/framework/map/mark/ActivityMark.cs", + "res://addons/dungeonShooting_plugin/Mark.svg" + ), + new CustomTypeInfo( + "EnemyMark", + "Node2D", + "res://src/framework/map/mark/EnemyMark.cs", + "res://addons/dungeonShooting_plugin/Mark.svg" + ), + new CustomTypeInfo( + "WeaponMark", + "Node2D", + "res://src/framework/map/mark/WeaponMark.cs", + "res://addons/dungeonShooting_plugin/Mark.svg" + ), + }; + public override void _Process(double delta) { - _instance = this; + Instance = this; + + if (_uiMonitor != null) + { + _uiMonitor.Process((float) delta); + } + else + { + _uiMonitor = new NodeMonitor(); + _uiMonitor.SceneNodeChangeEvent += GenerateUiCode; + OnSceneChanged(GetEditorInterface().GetEditedSceneRoot()); + } } public override void _EnterTree() { - _instance = this; - var script = GD.Load