RapidGameFramework
Reusable Godot managers for data-driven small games
Loading...
Searching...
No Matches
info_panel.gd
Go to the documentation of this file.
1extends RefCounted
2
3
8
9
10func create_popup(owner:Node, title_text:String, pages:Array, options:Dictionary = {}) -> PopupPanel:
11 var popup := PopupPanel.new()
12 popup.name = str(options.get("name", "InfoPopup"))
13 popup.size = _option_vector2i(options, "size", Vector2i(520, 560))
14 if owner != null:
15 owner.add_child(popup)
16
17 var content := VBoxContainer.new()
18 content.name = "Content"
19 content.set_anchors_preset(Control.PRESET_FULL_RECT)
20 var margin:int = int(options.get("margin", 16))
21 content.offset_left = margin
22 content.offset_top = margin
23 content.offset_right = -margin
24 content.offset_bottom = -margin
25 content.add_theme_constant_override("separation", int(options.get("separation", 10)))
26 popup.add_child(content)
27
28 var title := Label.new()
29 title.name = "Title"
30 title.text = title_text
31 title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
32 title.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
33 title.add_theme_font_size_override("font_size", int(options.get("title_font_size", 22)))
34 content.add_child(title)
35
36 var tabs := TabContainer.new()
37 tabs.name = "Tabs"
38 tabs.size_flags_horizontal = Control.SIZE_EXPAND_FILL
39 tabs.size_flags_vertical = Control.SIZE_EXPAND_FILL
40 content.add_child(tabs)
41
42 for page_value in pages:
43 if page_value is Dictionary:
44 tabs.add_child(_create_page(page_value))
45
46 var back := Button.new()
47 back.name = str(options.get("back_name", "Back"))
48 back.text = str(options.get("back_label", "Back"))
49 back.custom_minimum_size = Vector2(0, float(options.get("back_height", 48.0)))
50 var callback:Callable = options.get("back_callback", Callable())
51 back.pressed.connect(func():
52 if callback.is_valid():
53 callback.call()
54 else:
55 popup.hide()
56 )
57 content.add_child(back)
58 return popup
59
60
61func get_tab_container(popup:PopupPanel) -> TabContainer:
62 if popup == null:
63 return null
64 var tabs = popup.get_node_or_null("Content/Tabs")
65 if tabs is TabContainer:
66 return tabs
67 return null
68
69
70func step_tab(popup:PopupPanel, direction:int) -> void:
71 var tabs := get_tab_container(popup)
72 if tabs == null or tabs.get_tab_count() <= 0:
73 return
74 tabs.current_tab = wrapi(tabs.current_tab + direction, 0, tabs.get_tab_count())
75
76
77func reset_tab(popup:PopupPanel, tab_index:int = 0) -> void:
78 var tabs := get_tab_container(popup)
79 if tabs == null or tabs.get_tab_count() <= 0:
80 return
81 tabs.current_tab = clampi(tab_index, 0, tabs.get_tab_count() - 1)
82
83
84
87func add_info_card(parent:Container, card:Dictionary, options:Dictionary = {}) -> PanelContainer:
88 var panel := PanelContainer.new()
89 panel.name = str(card.get("title", "Info")).replace(" ", "") + "InfoCard"
90 panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
91 panel.add_theme_stylebox_override("panel", _info_card_style(options))
92
93 var margin := MarginContainer.new()
94 var padding:int = int(options.get("padding", 14))
95 margin.add_theme_constant_override("margin_left", padding)
96 margin.add_theme_constant_override("margin_right", padding)
97 margin.add_theme_constant_override("margin_top", max(8, padding - 4))
98 margin.add_theme_constant_override("margin_bottom", max(8, padding - 4))
99 panel.add_child(margin)
100
101 var row := HBoxContainer.new()
102 row.name = "Body"
103 row.add_theme_constant_override("separation", int(options.get("gap", 12)))
104 margin.add_child(row)
105
106 var icon_label := Label.new()
107 icon_label.name = "Icon"
108 icon_label.custom_minimum_size = Vector2(float(options.get("icon_width", 38.0)), 0)
109 icon_label.text = str(card.get("icon", ""))
110 icon_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
111 icon_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
112 icon_label.add_theme_font_size_override("font_size", int(options.get("icon_font_size", 22)))
113 icon_label.add_theme_color_override("font_color", Color(str(options.get("accent", "#4bb3ff"))))
114 row.add_child(icon_label)
115
116 var stack := VBoxContainer.new()
117 stack.name = "Text"
118 stack.size_flags_horizontal = Control.SIZE_EXPAND_FILL
119 stack.add_theme_constant_override("separation", int(options.get("text_gap", 2)))
120 row.add_child(stack)
121
122 var kicker := Label.new()
123 kicker.name = "Kicker"
124 kicker.text = str(card.get("kicker", ""))
125 kicker.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
126 kicker.add_theme_font_size_override("font_size", int(options.get("kicker_font_size", 12)))
127 kicker.add_theme_color_override("font_color", Color(str(options.get("accent", "#4bb3ff"))))
128 stack.add_child(kicker)
129
130 var title := Label.new()
131 title.name = "Title"
132 title.text = str(card.get("title", "Info"))
133 title.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
134 title.max_lines_visible = int(options.get("title_lines", 1))
135 title.add_theme_font_size_override("font_size", int(options.get("title_font_size", 20)))
136 title.add_theme_color_override("font_color", Color(str(options.get("text", "#eef3f8"))))
137 stack.add_child(title)
138
139 var body := Label.new()
140 body.name = "Description"
141 body.text = str(card.get("text", ""))
142 body.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
143 body.max_lines_visible = int(options.get("body_lines", 3))
144 body.add_theme_font_size_override("font_size", int(options.get("body_font_size", 14)))
145 body.add_theme_color_override("font_color", Color(str(options.get("muted", "#aab6c4"))))
146 stack.add_child(body)
147
148 if parent != null:
149 parent.add_child(panel)
150 return panel
151
152
153func _create_page(page:Dictionary) -> ScrollContainer:
154 var scroll := ScrollContainer.new()
155 scroll.name = str(page.get("id", page.get("title", "InfoPage"))).replace(" ", "")
156 scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
157 scroll.size_flags_horizontal = Control.SIZE_EXPAND_FILL
158 scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL
159
160 var body := VBoxContainer.new()
161 body.name = "Content"
162 body.size_flags_horizontal = Control.SIZE_EXPAND_FILL
163 body.add_theme_constant_override("separation", int(page.get("separation", 8)))
164 scroll.add_child(body)
165
166 var title := Label.new()
167 title.name = "PageTitle"
168 title.text = str(page.get("title", "Info"))
169 title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
170 title.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
171 title.add_theme_font_size_override("font_size", int(page.get("title_font_size", 18)))
172 body.add_child(title)
173
174 var lines:Array = page.get("lines", [])
175 for line_value in lines:
176 var label := Label.new()
177 label.text = str(line_value)
178 label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
179 label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
180 body.add_child(label)
181 return scroll
182
183
184func _info_card_style(options:Dictionary) -> StyleBoxFlat:
185 var style := StyleBoxFlat.new()
186 var background := Color(str(options.get("background", "#1a222bcc")))
187 background.a = clampf(float(options.get("opacity", background.a)), 0.0, 1.0)
188 style.bg_color = background
189 style.border_color = Color(str(options.get("border", "#33404d")))
190 style.set_border_width_all(int(options.get("border_width", 1)))
191 style.set_corner_radius_all(int(options.get("radius", 8)))
192 return style
193
194
195func _option_vector2i(options:Dictionary, key:String, default_value:Vector2i) -> Vector2i:
196 if not options.has(key):
197 return default_value
198 var value = options[key]
199 if value is Vector2i:
200 return value
201 if value is Vector2:
202 return Vector2i(int(value.x), int(value.y))
203 return default_value