概述
在设计Godot插件或应用程序时,可能需要显某个文件夹下的文件夹或文件的树形列表。FileSystemTree
就是为此而实现的,它是一个扩展自Tree
的自定义控件。
在Godot3.5中,我实现过类似的自定义控件,但是依赖场景文件而存在(我称为“场景元件”),在Godot4.2,完全基于自定义控件类,所以只有一个.gd
文件。
Godot4.2自定义控件系列目录
- 文件系统自定义控件 - FileSystemTree
- 文件系统自定义控件 - GroupButtons
- 文件系统自定义控件 - DirListView
- 基于EasyTreeData解析的扩展Tree控件 - ETDTree
类图关系
使用
- 将完整代码拷贝到你的项目中,创建.gd脚本文件,可以起名叫"FileSystemTree.gd"。
- 然后通过“添加节点”对话框,搜索
Tree
或FileSystemTree
就可以找到并添加它了。
- 然后在检视器面板设定参数,就可以看到相应的效果:
- 具体使用可以参照我的B站演示视频:B站【Godot4.2】文件系统自定义节点 - FileSystemTree
完整代码
# =============================================
# 名称:FileSystemTree
# 类型:自定义节点(扩展控件)
# 描述:专用于显示某文件夹结构的Tree控件
# 作者:巽星石
# Godot版本:v4.2.1.stable.official [b09f793f5]
# 创建时间:2024年2月7日20:20:45
# 最后修改时间:2024年2月7日23:48:19
# =============================================
@tool
extends Tree
class_name FileSystemTree
## 要显示的文件夹根目录
@export_global_dir var dir_path:String:
set(val):
dir_path = val
reload()
@export_group("icon")
## 文件夹图标
@export var dir_icon:Texture2D:
set(val):
dir_icon = val
reload()
## 文件图标
@export var file_icon:Texture2D:
set(val):
file_icon = val
reload()
@export_group("set")
## 支持的文件后缀名列表,可以写点也可以不写
@export var file_filters:Array[String]:
set(val):
file_filters = val
reload()
## 强制显示所有类型的文件,忽略file_filters的设置
@export var show_all_file:bool = false:
set(val):
show_all_file = val
reload()
# ========================= 方法 =========================
# 重新加载
func reload():
clear()
# 将根目录设定为根节点
var root = create_item()
root.set_text(0,dir_path.replace("/","//"))
root.set_icon(0,dir_icon)
# 加载子文件夹和子文件
load_dir(dir_path,root)
# 加载指定根目录下的文件夹和文件
func load_dir(path:String,p_node:TreeItem = null):
# 1.加载子文件夹列表
var dirs = DirAccess.get_directories_at(path)
for dir in dirs:
var itm = create_item(p_node)
itm.set_text(0,dir)
itm.set_icon(0,dir_icon)
# 1.1 递归子文件夹
load_dir("%s/%s" % [path,dir],itm)
# 2.加载子文件列表
var files = DirAccess.get_files_at(path)
for file in files:
if show_all_file: # 强制显示所有类型的文件
var itm = create_item(p_node)
itm.set_text(0,file)
itm.set_icon(0,file_icon)
else: # 只显示相应后缀名的文件
for filter in file_filters:
filter = filter if filter.begins_with(".") else "." + filter
if file.ends_with(filter):
var itm = create_item(p_node)
itm.set_text(0,file)
itm.set_icon(0,file_icon)
# 返回当前选中项在Tree中的完整路径
func get_rel_path(item:TreeItem)-> String:
var _path =""
if item.get_parent(): # 有父节点
# 递归父节点
_path = get_rel_path(item.get_parent()) + "/" + item.get_text(0)
else:# 根节点
_path = item.get_text(0)
return _path