# Hurry Curry! - a game about cooking # Copyright 2024 metamuffin # Copyright 2024 tpart # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, version 3 of the License only. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # 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 var data signal submenu_close() const transition_scene = preload("res://menu/scene_transition.tscn") var transition: SceneTransition var parent_menu: Menu = null var open_since = 0 func _ready(): open_since = Time.get_ticks_msec() Global.focused_menu = self focus_first(self) connect_button_sounds(self) disable_context_menus(self) update_parent_menu(self.get_parent()) if support_anim: anim_setup() if auto_anim: _menu_open() func anim_setup(): transition = transition_scene.instantiate() add_child(transition) func _menu_open(): if transition != null: await transition.fade_in() func _menu_exit(): if transition != null: await transition.fade_out() func _menu_cover(_state: bool): pass var popup: Menu = null var covered := false func submenu(path: String, data_ = null): var prev_focus = Global.focused_node if popup != null: return _disable_recursive(self, true) covered = true await _menu_cover(true) popup = load(path).instantiate() popup.data = data_ add_child(popup) print("Submenu opened ", path) await submenu_close print("Submenu closed ", path) await _menu_cover(false) covered = false Global.focused_menu = self _disable_recursive(self, false) if prev_focus != null: prev_focus.grab_focus() func _disable_recursive(node: Node, state: bool): if node is BaseButton: if state and node.disabled: node.add_to_group("was_disabled") else: node.remove_from_group("was_disabled") node.disabled = state or node.is_in_group("was_disabled") for c in node.get_children(): _disable_recursive(c, state) func exit(): await self._menu_exit() get_parent().submenu_close.emit() queue_free() func quit(): await exit() get_parent().quit() func replace_menu(path: String, data_ = null): print("Replace menu: ", path) if popup != null: await popup.exit() _disable_recursive(self, true) await _menu_exit() var new_popup = load(path).instantiate() new_popup.data = data_ 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_in_group("no_auto_focus"): return false 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 or node is TextureButton: if not node.is_in_group("no_click_sound"): node.pressed.connect(Sound.play_click) if (node is Button and not node.disabled) or (node is LineEdit and node.editable) or node is Slider: node.mouse_entered.connect(Sound.play_hover) for c in node.get_children(): connect_button_sounds(c) func disable_context_menus(node: Node): if node is LineEdit: node.context_menu_enabled = false for c in node.get_children(): disable_context_menus(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 Time.get_ticks_msec() - open_since < 100: return if Input.is_action_just_pressed("menu"): Sound.play_click() exit()