前言
查看godot的源码推荐使用在线版vscode直接从github上看。(直接把网址的com改成dev即可)
重点查看以下源码
scene_tree_dock.h
scene_tree_dock.cpp
开始
@tool
extends EditorPluginvar window
var scene_menustatic func find_child_by_class(node:Node, cls:String):var child_list = []for child in node.get_children():if child.get_class() == cls:child_list.append(child)return child_listfunc _enter_tree():#创建窗口window = preload("res://addons/ps/WWindows.gd").new()self.add_child(window)var base = get_editor_interface().get_base_control()var scene_tree_dock = base.find_child("Scene", true, false)scene_menu = find_child_by_class(scene_tree_dock,"PopupMenu")scene_menu[0].menu_changed.connect(self.menu_changed)scene_menu[0].id_pressed.connect(self.id_pressed)func menu_changed():if scene_menu[0].item_count == 0:returnvar name = scene_menu[0].get_item_text(clamp(scene_menu[0].item_count - 1,0,9999))var m:PopupMenu = scene_menu[0]if name == "删除节点":m.add_item("UI Editor",99)#不能超过100func id_pressed(id):if id == 99:window.show()func _exit_tree():# Clean-up of the plugin goes here.pass
在源码中
SceneTreeDock类的名字就叫Scene,所以我通过 find_child来直接获取引用
var scene_tree_dock = base.find_child("Scene", true, false)
因为SceneTreeDock里面有两个PopupMenu,经过分析,第一个是编辑器右键菜单。
我们也可以通过如下方式遍历打印一个控件的所有子控件
for child in node.get_children():print(child.get_class())
在上图源码这里创建了menu,鼠标点击以后会自动清空menu重新添加所有子项
所以menu每次点击都会不同,我们无法直接在gds内给menu添加子项,因为会被清除
这里我跟着_tree_rmb看到一些信号
但是这些信号我使用gds绑定以后有些不会触发,经过我测试(重命名信号)会触发,右键点击信号不会触发,所以我们还得想其他办法,在每次初始化 menu的时候添加子项。
这里是 PopupMenu的文档,里面的menu_changed信号会在menu初始化的时候触发,所以在这个时候添加子项是有效的,不会被清除。
func menu_changed():if scene_menu[0].item_count == 0:returnvar name = scene_menu[0].get_item_text(clamp(scene_menu[0].item_count - 1,0,9999))var m:PopupMenu = scene_menu[0]if name == "删除节点":m.add_item("UI Editor",99)#不能超过100
这里我要把子项加到删除节点的下面,注意我这样写在其他语言中可能有问题,但是大概思路是这样的。
要点是id=99,因为0-30左右都被占用了,默认是-1好像也会报错,于是我找了源码看到了
所以需要填大于30小于100的ID才不会报错
总结
至此原理就讲完了,浪费了两天时间,提高了查看源码的能力