发布 0.4 结果

发布: (2025年12月13日 GMT+8 07:00)
5 min read
原文: Dev.to

Source: Dev.to

我做了什么

目标是为默认的树形视图添加一个设置,使其可以切换为标签式视图:

树形视图

改为带有标签的视图。创建新分类和实体的逻辑已经存在,所以这主要是 UI 工作。

构建标签系统

核心逻辑位于 PandaEditor 场景中。在 Godot 编辑器里,你可以向每个场景添加节点,包括容器和 UI 元素。

Godot 编辑器视图

我首先向场景中添加了一个 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)

最终视图

加入标签、“+” 按钮以及上下文菜单后,编辑器现在呈现如下:

标签视图截图

以及在项目设置中出现的设置开关:

项目设置开关

唯一剩下的问题是设置在项目重新加载前不会生效。我通过在设置更改时添加一个简单的重载例程解决了这个问题。

Back to Blog

相关文章

阅读更多 »

为 streamplace 做贡献

我如何找到这个项目 如今,我经常阅读和编写 Go 代码,我的 Go 之旅始于《A Tour of Go》 https://go.dev/tour/welcome/1。Whi...

从开源维护者那里得到 NO

Forem 标志 https://media2.dev.to/dynamic/image/width=65,height=,fit=scale-down,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%...

Vibe Engineering 时代的代码乐趣

Programming 一直吸引着我,因为我可以让机器屈从于我的意志。把混乱的问题拆分成更小的部分的那种像拼图一样的乐趣,……