9func focus_first(root:Node) -> Control:
10 var control = find_first_focusable(root)
11 if control != null
and control.is_inside_tree():
17func focus_named(root:Node, node_name:String, fallback_to_first:bool = true) -> Control:
20 var target = root.find_child(node_name, true, false)
21 if target
is Control
and target.visible
and target.focus_mode != Control.FOCUS_NONE:
22 if not (target
is BaseButton)
or not target.disabled:
23 if target.is_inside_tree():
26 return focus_first(root)
if fallback_to_first
else null
30func focus_button_by_text(root:Node, labels:Array, fallback_to_first:bool = true) -> Control:
33 var target = _find_button_by_text(root, labels)
35 if target.is_inside_tree():
38 return focus_first(root)
if fallback_to_first
else null
43func focus_first_on_navigation(root:Node, event:InputEvent) -> bool:
44 if root == null
or event == null:
46 if not _is_navigation_event(event):
48 var viewport = root.get_viewport()
if root
is Control
else null
49 if viewport != null
and viewport.gui_get_focus_owner() != null:
51 return focus_first(root) != null
55func find_first_focusable(root:Node) -> Control:
58 for child
in root.get_children():
59 if child
is Control
and child.visible
and child.focus_mode != Control.FOCUS_NONE:
60 if not (child
is BaseButton)
or not child.disabled:
62 var nested = find_first_focusable(child)
69func set_focus_mode_recursive(root:Node, mode:int) -> void:
73 root.focus_mode = mode
74 for child
in root.get_children():
75 set_focus_mode_recursive(child, mode)
79func show_screen(screen_id:String, screens:Dictionary, scroll:ScrollContainer = null) -> String:
80 for id
in screens.keys():
81 var screen = screens[id]
83 screen.visible = str(id) == screen_id
85 call_deferred(
"_set_scroll_vertical_if_valid", scroll, 0)
90func shifted_id(current_id:String, ordered_ids:Array, delta:int) -> String:
91 if ordered_ids.is_empty():
93 var index = ordered_ids.find(current_id)
96 return str(ordered_ids[posmod(index + delta, ordered_ids.size())])
100func visible_screen_id(screens:Dictionary, fallback:String =
"") -> String:
101 for id
in screens.keys():
102 var screen = screens[id]
103 if screen
is Control
and screen.visible:
109func format_local_time(unix_time:float) -> String:
112 var value = Time.get_datetime_string_from_unix_time(int(unix_time), true)
113 return value.replace(
"T",
" ").substr(0, 16)
118func set_label_text_if_changed(label:Label, text:String) -> bool:
121 if label.text == text:
127func _is_navigation_event(event:InputEvent) -> bool:
128 for action
in [
"ui_up",
"ui_down",
"ui_left",
"ui_right"]:
129 if event.is_action_pressed(action):
134func _find_button_by_text(root:Node, labels:Array) -> Control:
135 for child
in root.get_children():
136 if child
is Button
and child.visible
and not child.disabled
and labels.has(str(child.text)):
138 var nested = _find_button_by_text(child, labels)
144func _set_scroll_vertical_if_valid(scroll:ScrollContainer, value:int) -> void:
145 if scroll != null
and is_instance_valid(scroll):
146 scroll.scroll_vertical = value