Newer
Older
DungeonShooting / DungeonShooting_Godot / addons / dungeonShooting_plugin / NodeMonitor.cs
@lijincheng lijincheng on 1 Aug 2023 4 KB Ui生成器支持监听脚本变化
  1. #if TOOLS
  2. using System;
  3. using System.Collections.Generic;
  4. using Godot;
  5.  
  6. namespace Plugin;
  7.  
  8. /// <summary>
  9. /// 场景监听器, 一旦当前节点内容发生改变, 则直接调用 SceneNodeChangeEvent 事件
  10. /// </summary>
  11. public class NodeMonitor
  12. {
  13. private class SceneNode : IEquatable<SceneNode>
  14. {
  15. public SceneNode(string type, string name, string scriptPath)
  16. {
  17. Type = type;
  18. Name = name;
  19. ScriptPath = scriptPath;
  20. }
  21.  
  22. /// <summary>
  23. /// 节点类型
  24. /// </summary>
  25. public string Type;
  26. /// <summary>
  27. /// 节点名称
  28. /// </summary>
  29. public string Name;
  30. /// <summary>
  31. /// 节点脚本路径
  32. /// </summary>
  33. public string ScriptPath;
  34. /// <summary>
  35. /// 子节点
  36. /// </summary>
  37. public List<SceneNode> Children = new List<SceneNode>();
  38.  
  39. public bool Equals(SceneNode other)
  40. {
  41. if (other == null)
  42. {
  43. return false;
  44. }
  45.  
  46. if (other.Name != Name || other.Type != Type || other.ScriptPath != ScriptPath)
  47. {
  48. return false;
  49. }
  50.  
  51. if (other.Children.Count != Children.Count)
  52. {
  53. return false;
  54. }
  55.  
  56. for (var i = 0; i < Children.Count; i++)
  57. {
  58. if (!Children[i].Equals(other.Children[i]))
  59. {
  60. return false;
  61. }
  62. }
  63.  
  64. return true;
  65. }
  66. }
  67.  
  68. /// <summary>
  69. /// 场景节点有变化时的回调事件
  70. /// </summary>
  71. public event Action<Node> SceneNodeChangeEvent;
  72.  
  73. private SceneNode _sceneNode;
  74. private Node _targetNode;
  75.  
  76.  
  77. private double _checkTreeTimer = 0;
  78.  
  79. /// <summary>
  80. /// 更新监听的节点
  81. /// </summary>
  82. public void ChangeCurrentNode(Node node)
  83. {
  84. //更新前检查旧的节点是否发生改变
  85. if (node != _targetNode && _targetNode != null)
  86. {
  87. try
  88. {
  89. var tempNode = ParseNodeTree(_targetNode);
  90. if (!_sceneNode.Equals(tempNode))
  91. {
  92. OnSceneNodeChange(_targetNode);
  93. }
  94. }
  95. catch (Exception e)
  96. {
  97. //检查节点存在报错, 直接跳过该节点的检查
  98. GD.Print(e.Message);
  99. }
  100. }
  101.  
  102. if (node != null)
  103. {
  104. _sceneNode = ParseNodeTree(node);
  105. _targetNode = node;
  106. }
  107. else
  108. {
  109. _targetNode = null;
  110. }
  111. _checkTreeTimer = 0;
  112. }
  113.  
  114. public void Process(float delta)
  115. {
  116. if (_targetNode == null)
  117. return;
  118. _checkTreeTimer += delta;
  119. if (_checkTreeTimer >= 5) //5秒检查一次
  120. {
  121. try
  122. {
  123. var tempNode = ParseNodeTree(_targetNode);
  124. if (!_sceneNode.Equals(tempNode))
  125. {
  126. OnSceneNodeChange(_targetNode);
  127. _sceneNode = tempNode;
  128. }
  129. }
  130. catch (Exception e)
  131. {
  132. //检查节点存在报错, 直接跳过该节点的检查
  133. GD.Print(e.Message);
  134. _targetNode = null;
  135. }
  136. _checkTreeTimer = 0;
  137. }
  138. }
  139. private SceneNode ParseNodeTree(Node node)
  140. {
  141. var script = node.GetScript().As<CSharpScript>();
  142. string scriptPath;
  143. if (script == null)
  144. {
  145. scriptPath = null;
  146. }
  147. else
  148. {
  149. scriptPath = script.ResourcePath;
  150. }
  151. var uiNode = new SceneNode(node.GetType().FullName, node.Name, scriptPath);
  152. var count = node.GetChildCount();
  153. for (var i = 0; i < count; i++)
  154. {
  155. uiNode.Children.Add(ParseNodeTree(node.GetChild(i)));
  156. }
  157.  
  158. return uiNode;
  159. }
  160.  
  161. private void OnSceneNodeChange(Node node)
  162. {
  163. if (SceneNodeChangeEvent != null)
  164. {
  165. SceneNodeChangeEvent(node);
  166. }
  167. }
  168. }
  169. #endif