summaryrefslogtreecommitdiff
path: root/client/menu/menu.gd
blob: 5d6946cf260140c0d75581a51d559fa0b0cf4c63 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# 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 <https://www.gnu.org/licenses/>.
#
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
var open_since

func _ready():
	open_since = Time.get_ticks_msec()
	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():
	if transition != null: await transition.fade_in()
func menu_anim_exit():
	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
	_disable_recursive(self, true)
	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)
	_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_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()
	_disable_recursive(self, true)
	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_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 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 Time.get_ticks_msec() - open_since < 100: return
	if Input.is_action_just_pressed("ui_cancel"):
		Sound.play_click()
		exit()