MenuButton is broken

I have been writing code professionally for decades. I have been making games before the internet. However Godot has been making me tear my hair out more than anything I’ve ever experienced in my entire life.

I was really excited when I heard about an open source game engine
However, I was very disappointed when I found out that Godot is absolutely incapable of having functional menus. The MenuButton object does not work at all. It should even exist in it’s current state. The MenuButton object allows you to add items which then appear in a popup window. The problem is, there is exactly 0 ways to interact with these parameters in the script. This should be simple. There is no excuse to for it not to be. All I want to do is create a MenuButton object and call different functions based on what menu item is clicked. I have spent hours reading forum posts with outdated solutions that don’t work. The problem seems to be with the .connect() function. It’s saying that certain arguments aren’t “callable” which I find hilarious especially since there’s no documentation for MenuButton (or PopupMenu) that provides actual use examples. All I was able to find was a list of methods. What I want to know is basically this. The MenuButton object only has “about_to_popup()” as a signal that can be sent for some reason. This is horrible. I should be able to get signals from each of the items within the menu without having to use broken .connect() function. Is there some super critical piece I’m missing? All of the tutorials and forum posts I can find are pre Godot 4.0 and are likely outdated. What is the current best and easiest way to create a MenuButton and access the information in GDscript?

Use PopupMenu.get_focused_item() -> int when signal Popup.popup_hide.
When you click a control node, the focus will become that node.

1 Like

A MenuButton is just that. A Button that shows a menu. In this case a PopupMenu You can access that PopupMenu with MenuButton.get_popup() and you can do whatever you need to do with that.

1 Like

if you have time, consider volunteering and updating outdated information.

I’ve spent another 5-6 hours on this and basically got no where. The problem seems to be with this connect() function. I keep getting brick walled by these errors that say things like: “Invalid type in function ‘connect’ in base ‘PopupMenu’. Cannot convert argument 2 from Object to Callable.” I looked at the documentation for PopupMenu and the word “connect” doesn’t even appear on the page. I am opening an issue to fill that gap in documentation but in the meantime I have no idea what to do. I’ll provide the code so maybe someone can point out where the problem is.

I’m about at the point to just say screw it and manually draw a rectangle around it and detect mouse clicks within sections of that rectangle.

extends Node2D

func _ready():
var pmenu = $MenuPopup.get_popup()
pmenu.connect(“id_pressed”, self, “_on_menu_item_pressed” )

func _on_menu_item_pressed(id):
var selection = $MenuPopup.get_popup().get_item_index(id)
print(“test”)

func _process(delta):
pass

I’ve tried with and without the parentheses at the end of “_on_menu_item_pressed” and it doesn’t make a difference either.

I haven’t tested this, but have you tried:

‘pmenu.id_pressed.connect(_on_menu_item_pressed)’ ?

if it helps, here is how to do it in c#

using Godot;
using System;
public partial class c_menu_button:MenuButton {
	PopupMenu m_popup_menu = null;
	void PressedId(long a_id) {
		GD.Print($"{a_id}");
	}
	public override void _Ready() {
		m_popup_menu = GetPopup();
		m_popup_menu.IdPressed += PressedId;
	}
}

1 Like

Thanks for the info. I just figured it out.

turns out this works and I’m not sure why:
$MenuPopup.get_popup().id_pressed.connect(_on_menu_item_pressed)

I thought id pressed just returned a signal. I didn’t know you could use the connect method with it.

1 Like

here is gdscript. it prints the id i set for each item.

extends MenuButton
func PressedId(a_id):
	print(a_id)
func _ready():
	var v_popup_menu : PopupMenu = get_popup()
	v_popup_menu.connect("id_pressed", PressedId)

EDIT: oops, too slow! leaving here for whoever needs it

1 Like

Are you following a tutorial from Godot 3.x? That’s the way of connecting a signal in Godot 3.x

In Godot 4.x the Signal is now a built-in type which means that it can be used as another object. More information about how to use them here Using signals — Godot Engine (stable) documentation in English

For the record:
The reason why connect() isn’t described on the PopupMenu page is because it isn’t a method defined in that class.
It is a method inherited from the parent Object class.
If you look at the top of the page for any class you see this line:

Inherits: Popup < Window < Viewport < Node < Object

That is the chain of inheritance.