13const DataCacheManager = preload(
"res://scripts/systems/dataCacheManager/data_cache_manager.gd")
16var current_screen_id :=
""
19var data_cache_manager = DataCacheManager.new()
23func load_menu(file_path:String) -> void:
24 var data = data_cache_manager.load_json(file_path)
25 config = data
if data
is Dictionary
else {}
26 current_screen_id = str(config.get(
"start_screen",
""))
31func get_cache_stats() -> Dictionary:
32 return data_cache_manager.get_cache_stats()
36func set_context(values:Dictionary) -> void:
37 context = values.duplicate(true)
41func update_context(values:Dictionary) -> void:
42 for key
in values.keys():
43 context[key] = values[key]
47func show_screen(screen_id:String, add_to_stack:bool = true) -> bool:
48 if not get_screens().has(screen_id):
50 if add_to_stack
and current_screen_id !=
"":
51 screen_stack.append(current_screen_id)
52 current_screen_id = screen_id
57func go_back() -> bool:
58 if screen_stack.is_empty():
60 current_screen_id = str(screen_stack.pop_back())
65func get_current_screen() -> Dictionary:
66 return get_screen(current_screen_id)
70func get_screen(screen_id:String) -> Dictionary:
71 return get_screens().get(screen_id, {})
75func get_screens() -> Dictionary:
76 return config.get(
"screens", {})
80func get_current_screen_id() -> String:
81 return current_screen_id
85func get_render_items(screen_id:String =
"") -> Array:
86 var screen = get_current_screen()
if screen_id ==
"" else get_screen(screen_id)
88 for raw_item
in screen.get(
"items", []):
89 if not raw_item
is Dictionary:
91 for expanded_item
in expand_item(raw_item):
92 if not is_item_visible(expanded_item):
94 expanded_item[
"disabled"] = is_item_disabled(expanded_item)
95 expanded_item[
"display_label"] = format_item_label(expanded_item)
96 items.append(expanded_item)
101func expand_item(item:Dictionary) -> Array:
102 var template_id = str(item.get(
"template",
""))
103 if template_id ==
"":
104 return [item.duplicate(true)]
105 if template_id ==
"save_slots":
106 return _expand_save_slots(item)
107 if template_id ==
"game_profiles":
108 return _expand_game_profiles(item)
109 if template_id ==
"platformer_levels":
110 return _expand_platformer_levels(item)
111 var templates = config.get(
"templates", {})
112 if templates.has(template_id)
and templates[template_id]
is Array:
114 for template_item
in templates[template_id]:
115 if template_item
is Dictionary:
116 expanded.append(_merge_template_item(template_item, item))
122func is_item_visible(item:Dictionary) -> bool:
123 if not item.has(
"visible_when"):
125 return _evaluate_condition(item.get(
"visible_when", {}))
129func is_item_disabled(item:Dictionary) -> bool:
130 if not item.has(
"disabled_when"):
132 return _evaluate_condition(item.get(
"disabled_when", {}))
136func format_item_label(item:Dictionary) -> String:
137 var label = str(item.get(
"label",
"Menu Item"))
138 var formatter = str(item.get(
"metadata_formatter",
""))
141 var data = item.get(
"metadata", context.get(formatter, {}))
142 if data
is Dictionary
and not data.is_empty():
143 return label +
"\n" + _format_metadata(data)
148func get_confirmation(item:Dictionary) -> Dictionary:
149 var confirm = item.get(
"confirm", {})
150 return confirm
if confirm
is Dictionary
else {}
154func get_item_sprite_id(item:Dictionary) -> String:
155 var explicit = str(item.get(
"sprite_id",
"")).strip_edges()
158 var icons = config.get(
"icons", {})
159 if not icons
is Dictionary:
161 var label_icons = icons.get(
"labels", {})
162 if label_icons
is Dictionary:
163 var label_key = str(item.get(
"label", item.get(
"display_label",
""))).strip_edges().to_lower()
164 if label_icons.has(label_key):
165 return str(label_icons[label_key])
166 var action = str(item.get(
"action",
""))
167 var action_icons = icons.get(
"actions", {})
168 if action_icons
is Dictionary
and action_icons.has(action):
169 return str(action_icons[action])
170 if action ==
"screen":
171 var target = str(item.get(
"target",
""))
172 var target_icons = icons.get(
"targets", {})
173 if target_icons
is Dictionary
and target_icons.has(target):
174 return str(target_icons[target])
175 return str(icons.get(
"fallback",
""))
178func _format_metadata(data:Dictionary) -> String:
179 if data.has(
"status"):
180 return str(data[
"status"])
181 if data.has(
"money")
or data.has(
"cards")
or data.has(
"wins")
or data.has(
"losses"):
182 var updated = str(data.get(
"updated_label",
""))
184 "$%d | %d cards" % [int(data.get(
"money", 0)), int(data.get(
"cards", 0))],
185 "%dW / %dL" % [int(data.get(
"wins", 0)), int(data.get(
"losses", 0))]
188 lines.append(
"Updated %s" % updated)
189 return "\n".join(lines)
191 for key
in data.keys():
192 if str(key)
in [
"empty",
"updated_at",
"slot"]:
194 parts.append(
"%s: %s" % [str(key).capitalize(), str(data[key])])
195 return " | ".join(parts)
198func _evaluate_condition(rule) -> bool:
200 for child_rule
in rule:
201 if _evaluate_condition(child_rule):
204 if not rule
is Dictionary:
207 for child_rule
in rule[
"all"]:
208 if not _evaluate_condition(child_rule):
212 for child_rule
in rule[
"any"]:
213 if _evaluate_condition(child_rule):
217 return not _evaluate_condition(rule[
"not"])
218 var key = str(rule.get(
"key",
""))
219 var value = _get_context_value(key)
220 if rule.has(
"equals"):
221 return value == rule[
"equals"]
222 if rule.has(
"not_equals"):
223 return value != rule[
"not_equals"]
224 if rule.has(
"greater_than"):
225 return float(value) > float(rule[
"greater_than"])
226 if rule.has(
"less_than"):
227 return float(value) < float(rule[
"less_than"])
228 if rule.has(
"at_least"):
229 return float(value) >= float(rule[
"at_least"])
230 if rule.has(
"at_most"):
231 return float(value) <= float(rule[
"at_most"])
232 if rule.has(
"missing"):
233 return bool(rule[
"missing"])
and (value == null
or value == false)
234 if rule.has(
"present"):
235 return bool(rule[
"present"])
and value != null
and value != false
239func _get_context_value(path:String):
242 var parts = path.split(
".")
245 if value
is Dictionary
and value.has(part):
252func _expand_save_slots(item:Dictionary) -> Array:
253 var slots = context.get(str(item.get(
"source",
"save_slots")), [])
256 if not slot
is Dictionary:
258 var slot_item = item.duplicate(true)
259 slot_item.erase(
"template")
260 slot_item[
"label"] = _format_template(str(item.get(
"label_template",
"Slot {slot}")), slot)
261 slot_item[
"metadata"] = slot
262 slot_item[
"action"] = str(item.get(
"slot_action", item.get(
"action",
"save_slot")))
263 slot_item[
"slot"] = int(slot.get(
"slot", 0))
264 slot_item[
"empty"] =
bool(slot.get(
"empty", false))
265 if bool(slot.get(
"empty", false)):
266 slot_item[
"display_state"] =
"empty"
267 expanded.append(slot_item)
271func _expand_game_profiles(item:Dictionary) -> Array:
272 var profiles = context.get(str(item.get(
"source",
"game_profiles")), [])
274 for profile
in profiles:
275 if not profile
is Dictionary:
277 var profile_item = item.duplicate(true)
278 profile_item.erase(
"template")
279 profile_item[
"label"] = str(profile.get(
"menu_label", profile.get(
"label", profile.get(
"id",
"Game"))))
280 profile_item[
"action"] = str(profile.get(
"action", item.get(
"profile_action",
"screen")))
281 profile_item[
"target"] = str(profile.get(
"target", profile.get(
"menu_route", profile.get(
"id",
""))))
282 profile_item[
"game_id"] = str(profile.get(
"id", profile.get(
"game_id",
"")))
283 profile_item[
"metadata"] = profile.duplicate(true)
284 if profile.has(
"sprite_id"):
285 profile_item[
"sprite_id"] = str(profile[
"sprite_id"])
286 if profile.has(
"description"):
287 profile_item[
"description"] = str(profile[
"description"])
288 expanded.append(profile_item)
292func _expand_platformer_levels(item:Dictionary) -> Array:
293 var levels = context.get(str(item.get(
"source",
"platformer_levels")), [])
296 if not level
is Dictionary:
298 var level_item = item.duplicate(true)
299 level_item.erase(
"template")
300 level_item[
"label"] = str(level.get(
"display_label", level.get(
"name", level.get(
"id",
"Level"))))
301 level_item[
"action"] = str(item.get(
"level_action",
"platformer_select_level"))
302 level_item[
"level_id"] = str(level.get(
"id",
""))
303 level_item[
"metadata"] = level.duplicate(true)
304 if bool(level.get(
"locked", false)):
305 level_item[
"disabled_when"] = {
"key":
"platformer_level_locks.%s" % str(level.get(
"id",
"")),
"equals": true}
306 level_item[
"sprite_id"] =
"lock" if bool(level.get(
"locked", false))
else (
"check" if bool(level.get(
"cleared", false))
else "play")
307 expanded.append(level_item)
311func _format_template(template:String, values:Dictionary) -> String:
312 var formatted = template
313 for key
in values.keys():
314 formatted = formatted.replace(
"{%s}" % str(key), str(values[key]))
318func _merge_template_item(template_item:Dictionary, source_item:Dictionary) -> Dictionary:
319 var merged = template_item.duplicate(true)
320 for key
in source_item.keys():
321 if key !=
"template":
322 merged[key] = source_item[key]