class_name Menu extends Control #enum Anim { NONE, FADE } #@export var animation: Anim = Anim.NONE @export var support_anim := true @export var auto_anim := true signal submenu_close() const transition_scene = preload("res://menu/scene_transition.tscn") var transition: SceneTransition var parent_menu: Menu = null func _ready(): focus_first(self) connect_button_sounds(self) update_parent_menu(self.get_parent()) if support_anim: anim_setup() if auto_anim: menu_anim_open() func anim_setup(): transition = transition_scene.instantiate() add_child(transition) func menu_anim_open(): print("open ", transition) if transition != null: await transition.fade_in() func menu_anim_exit(): print("exit ", transition) if transition != null: await transition.fade_out() func menu_anim_cover(state: bool): pass var popup: Menu = null func submenu(path: String, instant: bool = false): var prev_focus = Global.focused_node if popup != null: return await menu_anim_cover(true) popup = load(path).instantiate() if instant: popup.support_anim = false add_child(popup) print("Submenu opened ", path) await submenu_close print("Submenu closed ", path) await menu_anim_cover(false) if prev_focus != null: prev_focus.grab_focus() func exit(): await self.menu_anim_exit() get_parent().submenu_close.emit() queue_free() func quit(): await exit() get_parent().quit() func replace_menu(path: String): print("Replace menu: ", path) if popup != null: await popup.exit() await menu_anim_exit() var new_popup = load(path).instantiate() get_parent().add_child(new_popup) if parent_menu != null: parent_menu.popup = new_popup queue_free() var focus_auto_changed := false func focus_first(node: Node) -> bool: focus_auto_changed = true if node is Button or node is LineEdit: node.grab_focus() print("Node %s (%s) was selected for focus" % [node.name, node]) return true for c in node.get_children(): if focus_first(c): return true return false func connect_button_sounds(node: Node): if node is Button: if not node.is_in_group("no_click_sound"): node.pressed.connect(Sound.play_click) if node is Button or node is LineEdit or node is Slider: node.mouse_entered.connect(Sound.play_hover) for c in node.get_children(): connect_button_sounds(c) func update_parent_menu(node: Node): if node is Menu: parent_menu = node elif node.get_parent() != null: update_parent_menu(node.get_parent()) func _input(_event): if popup != null: return if Input.is_action_just_pressed("ui_cancel"): Sound.play_click() exit()