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))
15 owner.add_child(popup)
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)
28 var title := Label.new()
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)
36 var tabs := TabContainer.new()
38 tabs.size_flags_horizontal = Control.SIZE_EXPAND_FILL
39 tabs.size_flags_vertical = Control.SIZE_EXPAND_FILL
40 content.add_child(tabs)
42 for page_value
in pages:
43 if page_value
is Dictionary:
44 tabs.add_child(_create_page(page_value))
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():
57 content.add_child(back)
61func get_tab_container(popup:PopupPanel) -> TabContainer:
64 var tabs = popup.get_node_or_null(
"Content/Tabs")
65 if tabs
is TabContainer:
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:
74 tabs.current_tab = wrapi(tabs.current_tab + direction, 0, tabs.get_tab_count())
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:
81 tabs.current_tab = clampi(tab_index, 0, tabs.get_tab_count() - 1)
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))
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)
101 var row := HBoxContainer.new()
103 row.add_theme_constant_override(
"separation",
int(options.get(
"gap", 12)))
104 margin.add_child(row)
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)
116 var stack := VBoxContainer.new()
118 stack.size_flags_horizontal = Control.SIZE_EXPAND_FILL
119 stack.add_theme_constant_override(
"separation",
int(options.get(
"text_gap", 2)))
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)
130 var title := Label.new()
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)
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)
149 parent.add_child(panel)
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
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)
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)
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)
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)))
195func _option_vector2i(options:Dictionary, key:String, default_value:Vector2i) -> Vector2i:
196 if not options.has(key):
198 var value = options[key]
199 if value
is Vector2i:
202 return Vector2i(
int(value.x),
int(value.y))