发布 0.4 结果
Source: Dev.to
我做了什么
目标是为默认的树形视图添加一个设置,使其可以切换为标签式视图:
改为带有标签的视图。创建新分类和实体的逻辑已经存在,所以这主要是 UI 工作。
构建标签系统
核心逻辑位于 PandaEditor 场景中。在 Godot 编辑器里,你可以向每个场景添加节点,包括容器和 UI 元素。
我首先向场景中添加了一个 TabContainer 并将其设为隐藏。选中该设置后,它最终会被填充标签并显示出来。
添加设置
pandora-settings 保存了添加设置的代码,所以我在其中加入了一个布尔开关,用于切换到标签视图:
const USE_CATEGORY_TABS = "pandora/use_category_tabs"
static func get_use_category_tabs() -> bool:
return ProjectSettings.get_setting(USE_CATEGORY_TABS, false)
修改数据填充
接着,我在 pandora-editor.gd 中加入了标签填充的逻辑。已有一个名为 _populate_data() 的函数默认处理数据,但我需要修改它以检查标签设置是否启用:
var use_tabs = PandoraSettings.get_use_category_tabs()
if use_tabs:
await _populate_tabs(data)
else:
tree.set_data(data)
为根分类创建标签
我实现了 _populate_tabs() 函数,使其接受数据并在不是映射到树的情况下,为每个根分类创建一个标签:
# 为根分类创建标签
for i in range(root_categories.size()):
var tab_content = Control.new()
category_tab_container.add_child(tab_content)
category_tab_container.set_tab_title(i, root_categories[i].get_entity_name())
处理标签切换
为了在选择标签时仅显示所选分类的子项,我添加了 _on_tab_changed():
func _populate_tabs(root_categories: Array[PandoraEntity]) -> void:
# ... 创建标签 ...
# 保存根分类
category_tab_container.set_meta("root_categories", root_categories)
# 连接标签切换信号
category_tab_container.tab_changed.connect(_on_tab_changed)
func _on_tab_changed(tab_index: int) -> void:
var root_categories = category_tab_container.get_meta("root_categories", []) as Array
var selected_category = root_categories[tab_index]
# 过滤树,仅显示选中分类中的实体
var filtered_data: Array[PandoraEntity] = []
filtered_data.assign(selected_category._children)
tree.set_data(filtered_data)
为新分类添加 “+” 标签
原始视图没有通过标签栏创建分类的方式,于是我在根分类后面加入了一个 “+” 标签:
func _populate_tabs(root_categories: Array[PandoraEntity]) -> void:
# ... 创建分类标签 ...
# 为创建新根分类添加 '+' 标签
var add_tab_content = Control.new()
add_tab_content.name = "+"
category_tab_container.add_child(add_tab_content)
随后我更新了 _on_tab_changed(),使其在点击 “+” 标签时创建新根分类:
func _on_tab_changed(tab_index: int) -> void:
var root_categories = category_tab_container.get_meta("root_categories", []) as Array
# 如果选择的是 '+' 标签,则创建新根分类
if tab_index >= root_categories.size():
_create_root_category()
return
# 其余常规标签的处理...
重命名 / 删除的右键菜单
为了支持对分类进行重命名和删除,我在标签栏上添加了右键上下文菜单:
func _on_tab_bar_input(event: InputEvent) -> void:
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:
var tab_bar = category_tab_container.get_tab_bar()
var clicked_tab = tab_bar.get_tab_idx_at_point(event.position)
if clicked_tab >= 0:
var root_categories = category_tab_container.get_meta("root_categories", []) as Array
# '+' 标签不显示菜单
if clicked_tab >= root_categories.size():
return
# 记录点击的标签
category_tab_container.set_meta("context_menu_tab", clicked_tab)
# 显示上下文菜单
tab_context_menu.position = tab_bar.get_screen_position() + event.position
tab_context_menu.popup()
func _on_tab_context_menu_pressed(id: int) -> void:
var clicked_tab = category_tab_container.get_meta("context_menu_tab", -1)
if clicked_tab = root_categories.size():
return
var category = root_categories[clicked_tab]
match id:
0: # 重命名
_show_rename_dialog(category, clicked_tab)
1: # 删除
_show_delete_confirmation(category, clicked_tab)
最终视图
加入标签、“+” 按钮以及上下文菜单后,编辑器现在呈现如下:
以及在项目设置中出现的设置开关:
唯一剩下的问题是设置在项目重新加载前不会生效。我通过在设置更改时添加一个简单的重载例程解决了这个问题。



