Hello Godot community.
I’m working on a small VR app (not as much as a few before unfortunately, but still chugging along slowly) and I have a problem with enabling and disabling UI panels.
I have a small viewport_2d_in_3d UI for a wrist menu, of about 4, 5 buttons. These are meant to work as toggle buttons, but I haven’t gotten that to work at all so I’ve been using the regular button_pressed signal.
On pressing a button on the wrist menu, another menu should become visible, and able to be pointed at and clicked at. I’ve been able to hide or show it, but then the collision for the pointer function is still there.
By my current understanding I should use remove_child and add_child to disconnect and connect the other UI panels from the node tree/scene.
But no matter what I try to get it to work, I only manage to remove a panel and then it never shows up again.
Each UI panel has a control node as root, with a button’s signal connected to it. When the button is pressed a global variable is changed from true to false. Theoretically, this new true/false value should be used to either add_child or remove_child.
My brain is so exhausted right now I’m sure I’m not explaining it right and it’s probably a very simple solution, but I’m not seeing it right now. Any suggestions would be appreciated.
Also, how can I post images/screenshots (node tree stuff) here?
extends Node3D
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
pass # Replace with function body.
#func UIbuttons():
# if GlobalStuff.ui_main_menu:
# add_child(get_node(Wrist-Main-Menu"))
# if not GlobalStuff.ui_main_menu:
# remove_child(get_node(Wrist-Main-Menu"))
func ToggleMenu():
if GlobalStuff.ui_main_menu:
$"Wrist-Main-Menu".set_process(Node.PROCESS_MODE_ALWAYS)
$"Wrist-Main-Menu".show()
if not GlobalStuff.ui_main_menu:
$"Wrist-Main-Menu".set_process(Node.PROCESS_MODE_DISABLED)
$"Wrist-Main-Menu".hide()
func disable_and_hide_node(node:Node) -> void:
node.set_process(Node.PROCESS_MODE_DISABLED)
node.hide()
func enable_and_show_node(node:Node) -> void:
node.set_process(Node.PROCESS_MODE_ALWAYS)
node.show()
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
# UIbuttons()
# ToggleMenu()
pass
This 1st image is the zone base with a player character setup.
The leftHand controller has a Node3D as a parent that holds the script for the add_child and remove_child toggle.
The second image is still the zone base and shows a similar setup for the camera parent for the righthand controller.
The hide and show toggle here works. But I don’t like that this toggle happens all the time (if I add a print for “tool_cam_visibility” I get non stop prints for true/false. Seems excessive).
The third image shows the GUI for the tools, which has a button to toggle a global variable true or false, and emit a signal. I don’t know how clean of a method this is to be honest.
The fourth image ahows the main wrist menu and the script. The main menu button is supposed to add/remove the “Wrist-Main-Menu” scene. If I do a similar trick as with the camera I can show or hide them instead, but all the collisions still work and the pointer shows up as soon as it collides with the menu.
This behavior is not what I want. As I understand I should use add_child and remove_child, Ideally also for the photo camera. Eventually I want to have a modal system where I can sort of "drag and drop new tool scenes is some folder and the menu would automatically show the new tools.
You can emit signals in a more type-safe fashion without using String, e.g. ToggleCam.emit()
I don’t see you actually using the signals anywhere. You are emitting, but not listening for them? E.g. in your TakeAPhoto() method you could listen for a signal instead of processing that method every frame in _process() method like you currently do.
I don’t think you need the add/remove child methods, because the show and hide methods should be enough. That’s how I handle my UI code and never had any issues with it.
It seems to be a bit too complex that you process your code through a GlobalStuff autoload. If you can, you should keep your code as local as possible - it’ll be easier to debug and refactor. Not sure if you can achieve it in your project, but you can try to make direct connections between your UI elements using signals. If not possible, then you can try to implement a Signal/Event Bus approach. I’m not a fan of it, but maybe you’ll like it, it’s an individual preference in the end.
I’m away from my PC during Christmas and New Years, but if you still struggle afterwards, I can try to help you debug your project later.