【Godot4.2】菜单栏生成函数库menuDB

概述

关于Godot的手动菜单栏制作,我已经在之前的文章中有所描述。

但是对于一些场景,手动制作菜单仍然是一个比较低效的做法。所以我将MenuBar以及基于HBoxContainer+MenuButton创建菜单栏写成了一个静态函数库。

利用此函数库我们可以用函数形式构造PopupMenuMenuButtonMenuBar以及基于HBoxContainer+MenuButton创建的菜单栏。

另外我自定义3种资源,来定义和存储单个菜单栏、单个菜单和单个菜单项所需的数据:

  • MenuBarData:存储定义单个MenuBar所需的数据
  • MenuData:存储定义单个菜单所需的数据
  • PopupMenuItem:存储单个菜单项所需的数据

当然我的本意是基于这个函数库构建更简单的菜单栏自定义控件。

函数库代码

# ========================================
# 名称:menuDB
# 类型:静态函数库
# 描述:专用于【生成菜单栏】的静态函数库
# 作者:巽星石
# Godot版本:v4.2.1.stable.official [b09f793f5]
# 创建时间:202422718:45:28
# 最后修改时间:202422721:51:11
# ========================================
class_name menuDB

# -------------- 构造MenuBar或基于HBoxContainer+MenuButton的水平菜单栏 --------------
# 构造并返回有完整结构的MenuBar
static func menu_bar(menu_bar_data:MenuBarData) -> MenuBar:
	var bar = MenuBar.new()
	# 遍历MenuBar数据,创建PopUp
	for menu_data in menu_bar_data.menus:
		var menu = popup_menu(menu_data.text,menu_data.items,menu_bar_data.icon_max_width)
		bar.add_child(menu)
	return bar

# 构造并返回多个MenuButton水平排列的HBoxContainer
static func hbox_menu_bar(menu_bar_data:MenuBarData) -> HBoxContainer:
	var bar = HBoxContainer.new()
	# 遍历MenuBar数据,创建PopUp
	for menu_data in menu_bar_data.menus:
		var menu = menu_button(menu_data.text,menu_data.icon,menu_data.items,menu_bar_data.icon_max_width)
		bar.add_child(menu)
	return bar


# -------------- 构造 PopupMenuMenuButton --------------
# 构造并返回一个带有菜单项的PopupMenu
static func popup_menu(
					text:String = "MenuButton",  # 按钮文本
					items:Array[PopupMenuItem] = [], # 菜单项数据集
					items_icon_max_width = 16        # 菜单项图标的最大宽度
				) -> PopupMenu:
	# --------------- 创建MenuButton ---------------
	var menu = PopupMenu.new()
	menu.name = text
	# --------------- 遍历items,为PopupMenu添加菜单项 ---------------
	for item in items:
		popup_menu_add_item(menu,item,items_icon_max_width)
	return menu


# 构造并返回带有菜单项的MenuButton
static func menu_button(
					text:String = "MenuButton",  # 按钮文本
					icon:Texture2D = null,           # 按钮图标
					items:Array[PopupMenuItem] = [], # 菜单项数据集
					items_icon_max_width = 16        # 菜单项图标的最大宽度
				) -> MenuButton:
	# --------------- 创建MenuButton ---------------
	var btn = MenuButton.new()
	btn.text = text
	btn.icon = icon
	# --------------- 获取其PopupMenu ---------------
	var menu:PopupMenu = btn.get_popup()
	# --------------- 遍历items,为PopupMenu添加菜单项 ---------------
	for item in items:
		popup_menu_add_item(menu,item,items_icon_max_width)
	return btn


# -------------- PopupMenu菜单项添加 --------------
# 通过PopupMenuItem资源数据为PopupMenu添加一个菜单项
static func popup_menu_add_item(menu:PopupMenu,item:PopupMenuItem,icon_max_width = 16) -> void:
	var index = menu.item_count # 当前项索引 = 已有菜单项总数
	# 创建纯文本菜单项
	menu.add_item(item.text)
	# 设置附加选项
	if item.icon:              # 图标
		menu.set_item_icon(index,item.icon)
	menu.set_item_icon_max_width(index,icon_max_width)        # 图标最大宽度
	if item.checkable:         # 复选框 形式
		menu.set_item_as_checkable(index,item.checkable)
	if item.radio_checkable:   # 单选框 形式
		menu.set_item_as_radio_checkable(index,item.radio_checkable)
	if item.separator:         # 带分割线 形式
		menu.set_item_as_separator(index,item.separator)
	if item.shortcut:          # 快捷键 + 是否全局
		menu.set_item_shortcut(index,item.shortcut,item.shortcut_global)
	menu.set_item_shortcut_disabled(index,item.shortcut_disabled)   # 快捷键是否禁用
	
	menu.set_item_checked(index,item.checked)    # 是否选中(仅在单选框或复选框形式下)
	menu.set_item_disabled(index,item.disabled)  # 是否禁用
	menu.set_item_tooltip(index,item.tooltip)    # 鼠标提示文本
	
	if item.sub_menu.size() > 0:        # 如果菜单项存在子菜单项
		var sub_popup = PopupMenu.new() # 创建子菜单
		sub_popup.name = "%d_%s_sub_popup" % [index,item.text]  # 创建唯一名称
		# 添加子菜单项
		for sub_item in item.sub_menu:
			popup_menu_add_item(sub_popup,sub_item,icon_max_width)
		# 添加为当前PopupMenu的子节点
		menu.add_child(sub_popup)
		menu.set_item_submenu(index,sub_popup.name)  # 为当前项指定子菜单的名称

3种自定义数据结构

MenuBar

@tool
# 单个MenuBar数据
class_name MenuBarData extends Resource
	
@export var menus:Array[MenuData]           # 菜单列表
@export var icon_max_width = 16       # 菜单项图标的最大宽度

MenuData

@tool
# 单个菜单数据
class_name MenuData extends Resource

@export var text:String                     # 按钮文本
@export var icon:Texture2D                  # 按钮图标
@export var items:Array[PopupMenuItem]      # 菜单项

PopupMenuItem

@tool
# PopupMenu单个菜单项数据
class_name PopupMenuItem extends Resource

# 基础设置
@export var text:String             # 文本
@export var icon:Texture2D          # 图标
# 特殊形式
@export var checkable:bool          # 复选框 形式
@export var radio_checkable:bool    # 单选框 形式
@export var separator:bool          # 带分割线 形式
# 快捷键
@export var shortcut:Shortcut       # 快捷键
@export var shortcut_global:bool    # 快捷键是否全局
@export var shortcut_disabled:bool  # 快捷键是否禁用
# 选中与禁用
@export var checked:bool            # 选中
@export var disabled:bool           # 禁用
# 鼠标提示文本
@export var tooltip:String          # 鼠标提示文本
# 子菜单
@export var sub_menu:Array[PopupMenuItem]     # 子菜单

基于函数库创建自定义MenuBar节点

# ========================================
# 基于menuDB函数库的自定义MenuBar节点
# ========================================
@tool
class_name myMenuBar extends MenuBar

@export var data:MenuBarData:
	set(val):
		data = val
		create()
		
# 根据MenuBarData创建菜单和菜单项
func create() -> void:
	# 遍历MenuBar数据,创建PopUp
	for menu_data in data.menus:
		var menu = menuDB.popup_menu(menu_data.text,menu_data.items,data.icon_max_width)
		add_child(menu)

我们可以看到myMenuBar类型有一个Data参数,我们需要为其设定MenuBarData类型的资源。
在这里插入图片描述
运行后的效果如下:
在这里插入图片描述
可以看到这种自定义资源多层嵌套形式在Godot检视器面板上就是一种灾难。

所以更好的做法是基于字典的解析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/413388.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Oracle】玩转Oracle数据库(六):模式对象管理与安全管理

前言 嘿,数据库大冒险家们!准备好迎接数据库管理的新挑战了吗?今天我们要探索的是Oracle数据库中的模式对象管理与安全管理!🛡️💻 在这篇博文【Oracle】玩转Oracle数据库(六)&#…

CTFHub技能树web之XSS

在XSS系列的题目中,由于需要使用能够接受XSS数据的平台,并且由于使用的是CTFHub的模拟机器人点击我们的虚假URL,因此使用的XSS平台不能是自己本地搭建的,如果是本地的模拟点击的机器人将无法访问我们给的这个URL地址,也…

Maven【1】(命令行操作)

文章目录 一丶创建maven工程二、理解pom.xml三、maven的构建命令1.编译操作2.清理操作3.测试操作4.打包操作5.安装操作 一丶创建maven工程 首先创建这样一个目录,然后从命令行里进入这个目录: 然后接下来就在这个命令行里进行操作了。 这个命令是&…

听劝!年后跳槽需谨慎……

​新年新气象,许多不满需求的开发者都想开展一番新的事业。跳槽找工作是要吃老本行?还是换岗?请三思啊!! 2024年的移动开发行业岗位还友好吗? 随着互联网的时间发展推移,大部分开发岗已经走向末…

Spring Cloud Gateway官方文档学习

文章目录 推荐写在前面一、熟悉Gateway基本概念与原理1、三大概念2、工作流程 二、基本使用路由断言的两种写法 三、路由断言工厂1、After路由断言工厂2、Before路由断言工厂3、Between路由断言工厂4、Cookie路由断言工厂5、Header路由断言工厂6、Host路由断言工厂7、Method路由…

中间件-Nginx漏洞整改(限制IP访问隐藏nginx版本信息)

中间件-Nginx漏洞整改(限制IP访问&隐藏nginx版本信息) 一、限制IP访问1.1 配置Nginx的ACL1.2 重载Nginx配置1.3 验证结果 二、隐藏nginx版本信息2.1 打开Nginx配置文件2.2 隐藏Nginx版本信息2.3 保存并重新加载Nginx配置2.4 验证结果2.5 验证隐藏版本…

LabVIEW光伏逆变器低电压穿越能力测试

LabVIEW光伏逆变器低电压穿越能力测试 随着光伏发电技术的迅速发展,光伏逆变器的低电压穿越(LVRT)能力日益成为影响电网稳定性的关键因素。为了提升光伏逆变器的并网性能,开发了一套基于LabVIEW的光伏逆变器LVRT测试系统。该系统…

【VSCode】SSH Remote 通过跳板机连开发机提示“bash行1 powershell未找到命令”

需求背景 因为需要,在家我需要挂上公司VPN然后SSH连到跳板机,然后再从跳板机SSH进开发机。 问题背景 跳板机进开发机输入完密码显示 bash行1 powershell未找到命令VSCode SSH Remote跳板机配置请自行搜素其他文章config配置 注意其中ssh.exe地址请根据…

用39块钱的全志V851se视觉开发板做了个小相机,还可以物品识别、自动追焦!

用39块钱的V851se视觉开发板做了个小相机。 可以进行物品识别、自动追焦! 这个超低成本的小相机是在V851se上移植使用全志在线开源版本的Tina Linux与OpenCV框架开启摄像头拍照捕获视频,并结合NPU实现Mobilenet v2目标分类识别以及运动追踪等功能…并最终…

k8s节点负载使用情况分析命令kubectl describe node [node-name]

1.到任意安装了kubectl节点命令的节点上执行kubectl describe node [node-name] 上面的Requests最小分配 Limits最大分配是所有pod之和,最小分配之和不能超过服务器实际参数,否则新的pod会因为资源不够起不来,最大分配是预设之和&#xff0…

图片数据爬取工具Image-Downloader

图片数据爬取工具Image-Downloader_image downloader-CSDN博客文章浏览阅读1.2k次。既然我们使用 Image-Downloader 这个工具进行图片搜索,相比python我们都非常熟悉,在此不在叙述,可参考其他文章。_image downloaderhttps://blog.csdn.net/w…

有方机器人 STM32智能小车 项目学习笔记1

今天开始学习有方机器人--智能小车项目,正点原子部分的学习先放一放,还是小车更有吸引力哈哈。 新建工程及工程模板搭建 新建工程须知 目前常用的 STM32 的开发方式主要有基于寄存器编程、基于标准库函数编程、基于 HAL 库编程这三种。 寄存器版本--…

七、防御保护---VPN篇

七、防御保护---VPN篇 一、VPN介绍二、VPN的分类2.1 根据建设的单位不同分类2.2 根据组网方式不同分类2.3 根据应用场景不同分类2.4 按照VPN技术实现的网络层次进行分类: 三、VPN的核心技术3.1 隧道技术3.2 身份认证技术3.3 加密技术3.4 数据验证技术 一、VPN介绍 …

【Python-语法】

Python-语法 ■ Python基础■ 数据类型■ 注释 单行注释,多行注释■ 编码方式 ■■■■■ ■ Python基础 ■ 数据类型 ■ 注释 单行注释,多行注释 ■ 编码方式 ■ ■ ■ ■ ■

vue3新特性-defineOptions和defineModel

defineOptions 背景说明&#xff1a; 有 <script setup> 之前&#xff0c;如果要定义 props, emits 可以轻而易举地添加一个与 setup 平级的属性。 但是用了 <script setup> 后&#xff0c;就没法这么干了 setup 属性已经没有了&#xff0c;自然无法添加与其平…

apachectl: line 79: 20233 Segmentation fault (core dumped) $HTTPD “$@“

[TOC](apachectl: line 79: 20233 Segmentation fault (core dumped) $HTTPD “$”) 1、问题描述 apache 启动报错 apachectl: line 79: 20233 Segmentation fault (core dumped) $HTTPD “$” 2、问题分析 参考链接: https://stackoverflow.com/questions/43726930/apache…

【leetcode热题】杨辉三角 II

难度&#xff1a; 简单通过率&#xff1a; 41.1%题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定一个非负索引 k&#xff0c;其中 k ≤ 33&#xff0c;返回杨辉三角的第 k 行。 在杨辉三角中&#xff0c;每个数是它左上方和右上方的数的和。 示…

YOLOv9中的“RepNCSPELAN4”结构!

RepNCSPELAN4结构出炉啦&#xff0c;收藏起来写论文用&#xff01; 论文链接&#xff1a; YOLOv9: Learning What You Want to Learn Using Programmable Gradient 代码链接&#xff1a;https://github.com/WongKinYiu/yolov9/tree/main 1.代码&#xff1a; 代码路径&#x…

【Android移动开发】Windows10平台安装Android Studio与人工智能算法模型部署案例

目录 一、Android Studio下载地址二、开发环境JDK三、开始安装Android Studio四、案例展示与搭建五、人工智能算法模型移动端部署案例参考 一、Android Studio下载地址 https://developer.android.google.cn/studio/install.html 电脑配置要求&#xff1a; 下载保存在指定文…

自动化工具 接口自动化测试引擎

一、前言&#xff1a; 1、解决痛点&#xff1a;接口自动化测试用例需要人去开发、去维护。 2、实现第一性原理&#xff1a;根据定义的测试策略自动生成接口测试用例。 二、引擎优势&#xff1a; 1、提升人效&#xff1a;降低传统方式中接口测试开发与维护的工作量。 2、覆盖更…