Newer
Older
DungeonShooting / DungeonShooting_Godot / addons / dungeonShooting_plugin / NodeMonitor.cs
@lijincheng lijincheng on 18 Mar 2023 2 KB 整理注册自定义节点代码
#if TOOLS
using System;
using System.Collections.Generic;
using Godot;

namespace Plugin;

/// <summary>
/// 场景监听器, 一旦当前节点内容发生改变, 则直接调用 SceneNodeChangeEvent 事件
/// </summary>
public class NodeMonitor
{
    private class SceneNode : IEquatable<SceneNode>
    {
        public SceneNode(string type, string name)
        {
            Type = type;
            Name = name;
        }

        public string Type;
        public string Name;
        public List<SceneNode> Children = new List<SceneNode>();

        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;
        }
    }

    /// <summary>
    /// 场景节点有变化时的回调事件
    /// </summary>
    public event Action<Node> SceneNodeChangeEvent;

    private SceneNode _sceneNode;
    private Node _targetNode;


    private double _checkTreeTimer = 0;

    /// <summary>
    /// 更新监听的节点
    /// </summary>
    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