【Godot】菜单脚本,只用传入字典数据即可创建多级菜单

Godot 3.5 rc2

将脚本挂载到一个 HBoxContainerVBoxContainer 节点上

在这里插入图片描述

下面 test() 方法即是一个示例,可以扩展脚本重写 _menu_pressed() 方法操作点击的菜单项,或者连接 menu_pressed 信号进行对点击的菜单进行操作

#=====================================================
#   菜单列表
#=====================================================
#  类似 test() 脚本中的菜单结构,可以生成不断嵌套的菜单
#=====================================================

class_name MenuList
extends BoxContainer


func _ready():
	test()

func test():
	init_menu({
		"File": [
			"Open", "Save", "Save As",
			{
				"Export": [
					"Export",
					"Export as..."
				]
			}
		],
		"Edit": [
			"Undo",
			{
				"number": [
					"1",
					"2",
					"3",
				],
				"item_02": [
					"a",
					"b",
					"c",
					{"d": [1, 2, 3, 4]},
				]
			},
		],
	})



signal menu_pressed(id, path)


var idx := -1
var popup_menu_map := {}
var popup_item_path_map := {}


#=====================================================
#   Set/Get
#=====================================================
## 获取弹窗菜单
func get_popup_menu(path: String) -> PopupMenu:
	return popup_menu_map[path] as PopupMenu


#=====================================================
#   自定义方法
#=====================================================
## 初始化菜单
func init_menu(data: Dictionary):
	call_deferred("add_menu", data)


## 添加菜单项
func add_menu(menu_data, popup : PopupMenu = null, parent_label: String = ""):
	
	idx += 1
	if popup != null:
		# Dictionary
		if menu_data is Dictionary:
			for key in menu_data:
				add_menu(
					menu_data[key]
					, popup
					, parent_label.plus_file(key)
				)
		
		# Array
		elif menu_data is Array:
			for item in menu_data:
				add_menu(item, popup, parent_label)
		
		# String
		else:
			# 添加子菜单
			create_menu(parent_label, popup)
			
			# 添加菜单项
			var sub_popup := get_popup_menu(parent_label)
			var label : String = str(menu_data)
			if not label.begins_with("-"):
				popup_item_path_map[idx] = parent_label + "/" + label
				sub_popup.add_item(label, idx)
				
			else:
				sub_popup.add_separator()
			
	else:
		for key in menu_data:
			var menu = MenuButton.new()
			menu.switch_on_hover = true
			menu.text = str(key)
			add_child(menu)
			
			parent_label = "/" + key
			__popup_item_data__(parent_label, menu.get_popup())
			add_menu(menu_data[key], menu.get_popup(), parent_label)


## 创建菜单
func create_menu(menu_path: String, to_menu: PopupMenu = null):
	if menu_path == "":
		return
	
	if not popup_menu_map.has(menu_path):
		var arr : Array = menu_path.split("/")
		var last_menu : PopupMenu = to_menu
		for idx in range(1, arr.size()):
			var label : String = arr[idx]
			var sub_path = "/".join(arr.slice(0, idx))
			if not popup_menu_map.has(sub_path):
				var item_label = sub_path.right( sub_path.find_last("/") ).trim_prefix("/")
				var temp_popup = PopupMenu.new()
				temp_popup.name = item_label
				__popup_item_data__(sub_path, temp_popup)
				
				last_menu.add_child(temp_popup)
				last_menu.add_submenu_item( item_label, item_label )
			last_menu = get_popup_menu(sub_path)


## 点击菜单
func _menu_pressed(idx: int, path: String):
	printt(idx, path)
	pass


#=====================================================
#   连接信号
#=====================================================
# 弹窗菜单路径
func __popup_item_data__(path: String, popup: PopupMenu):
	popup_menu_map[path] = popup
	if not popup.is_connected("id_pressed", self, "__popup_id_pressed__"):
		popup.connect("id_pressed", self, "__popup_id_pressed__")


# 点击菜单连接信号
func __popup_id_pressed__(id: int):
	_menu_pressed(id, popup_item_path_map[id])
	emit_signal("menu_pressed", id, popup_item_path_map[id])

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值