godot-accessibility/ScreenReader.gd

295 lines
6.7 KiB
GDScript3
Raw Normal View History

tool
extends Node
signal swipe_left
signal swipe_right
signal swipe_up
signal swipe_down
var Accessible = preload("Accessible.gd")
export var enabled = true setget _set_enabled, _get_enabled
export var min_swipe_distance = 5
2019-12-30 00:23:51 +00:00
export var tap_execute_interval = 125
2019-12-30 00:23:51 +00:00
export var explore_by_touch_interval = 200
export var enable_focus_mode = false
2020-05-19 17:03:59 +00:00
func _set_enabled(v):
2020-05-19 17:03:59 +00:00
if enabled:
augment_tree(get_tree().root)
else:
for accessible in get_tree().get_nodes_in_group("accessibles"):
accessible.queue_free()
2020-05-19 17:03:59 +00:00
enabled = v
func _get_enabled():
2020-05-19 17:03:59 +00:00
return enabled
2018-05-28 21:45:13 +00:00
func augment_node(node):
2020-05-19 17:03:59 +00:00
if not enabled:
return
if node is Control:
Accessible.new(node)
func augment_tree(node):
2020-05-19 17:03:59 +00:00
if not enabled:
return
if node is Accessible:
return
augment_node(node)
for child in node.get_children():
augment_tree(child)
2018-05-28 21:45:13 +00:00
func set_initial_screen_focus(screen):
2020-05-19 17:03:59 +00:00
TTS.speak("%s: screen" % screen, false)
var control = _find_focusable_control(get_tree().root)
2020-05-19 17:03:59 +00:00
if control.get_focus_owner() != null:
return
self.augment_tree(get_tree().root)
var focus = _find_focusable_control(get_tree().root)
2020-05-19 17:03:59 +00:00
if not focus:
return
focus.grab_click_focus()
focus.grab_focus()
func _find_focusable_control(node):
2020-05-19 17:03:59 +00:00
if (
node is Control
and node.is_visible_in_tree()
and (node.focus_mode == Control.FOCUS_CLICK or node.focus_mode == Control.FOCUS_ALL)
):
return node
for child in node.get_children():
var result = _find_focusable_control(child)
2020-05-19 17:03:59 +00:00
if result:
return result
return null
2018-05-28 21:45:13 +00:00
func set_initial_scene_focus(scene):
2020-05-19 17:03:59 +00:00
self.augment_tree(get_tree().root)
var focus = _find_focusable_control(get_tree().root)
2020-05-19 17:03:59 +00:00
if not focus:
return
focus.grab_click_focus()
focus.grab_focus()
func _enter_tree():
pause_mode = Node.PAUSE_MODE_PROCESS
2020-05-19 17:03:59 +00:00
if enabled:
augment_tree(get_tree().root)
get_tree().connect("node_added", self, "augment_node")
connect("swipe_right", self, "swipe_right")
connect("swipe_left", self, "swipe_left")
connect("swipe_up", self, "swipe_up")
connect("swipe_down", self, "swipe_down")
func _press_and_release(action, fake_via_keyboard = false):
if fake_via_keyboard:
for event in InputMap.get_action_list(action):
if event is InputEventKey:
event.pressed = true
Input.action_press(action)
get_tree().input_event(event)
event.pressed = false
Input.action_release(action)
get_tree().input_event(event)
return
2020-05-19 17:03:59 +00:00
var event = InputEventAction.new()
event.action = action
event.pressed = true
Input.action_press(action)
2020-05-19 17:03:59 +00:00
get_tree().input_event(event)
event.pressed = false
Input.action_release(action)
2020-05-19 17:03:59 +00:00
get_tree().input_event(event)
func _ui_left(fake_via_keyboard = false):
_press_and_release("ui_left", fake_via_keyboard)
func _ui_right(fake_via_keyboard = false):
_press_and_release("ui_right", fake_via_keyboard)
func _ui_up(fake_via_keyboard = false):
_press_and_release("ui_up", fake_via_keyboard)
func _ui_down(fake_via_keyboard = false):
_press_and_release("ui_down", fake_via_keyboard)
func _ui_focus_next(fake_via_keyboard = false):
_press_and_release("ui_focus_next", fake_via_keyboard)
func _ui_focus_prev(fake_via_keyboard = false):
_press_and_release("ui_focus_prev", fake_via_keyboard)
2020-05-19 17:03:59 +00:00
func swipe_right():
var fake_via_keyboard = false
if OS.get_name() == "Android":
fake_via_keyboard = true
_ui_focus_next(fake_via_keyboard)
2020-05-19 17:03:59 +00:00
func swipe_left():
var fake_via_keyboard = false
if OS.get_name() == "Android":
fake_via_keyboard = true
_ui_focus_prev(fake_via_keyboard)
2020-05-19 17:03:59 +00:00
func swipe_up():
var focus = _find_focusable_control(get_tree().root)
if focus:
focus = focus.get_focus_owner()
if focus:
if focus is Range:
_press_and_release("ui_right")
2020-05-19 17:03:59 +00:00
func swipe_down():
var focus = _find_focusable_control(get_tree().root)
if focus:
focus = focus.get_focus_owner()
if focus:
if focus is Range:
_press_and_release("ui_left")
2020-05-19 17:03:59 +00:00
var touch_index = null
var touch_position = null
var touch_start_time = null
var touch_stop_time = null
var explore_by_touch = false
var tap_count = 0
var focus_mode = false
var in_focus_mode_handler = false
2020-05-19 17:03:59 +00:00
func _input(event):
2020-05-19 17:03:59 +00:00
if not enabled:
return
if enable_focus_mode:
if (
event is InputEventKey
and Input.is_key_pressed(KEY_ESCAPE)
and Input.is_key_pressed(KEY_SHIFT)
and not event.echo
):
get_tree().set_input_as_handled()
if focus_mode:
focus_mode = false
TTS.speak("UI mode", true)
return
else:
focus_mode = true
TTS.speak("Focus mode", true)
return
if focus_mode:
if (
Input.is_action_just_pressed("ui_left")
or Input.is_action_just_pressed("ui_right")
or Input.is_action_just_pressed("ui_up")
or Input.is_action_just_pressed("ui_down")
or Input.is_action_just_pressed("ui_focus_next")
or Input.is_action_just_pressed("ui_focus_prev")
):
if in_focus_mode_handler:
return
in_focus_mode_handler = true
if Input.is_action_just_pressed("ui_left"):
_ui_left()
elif Input.is_action_just_pressed("ui_right"):
_ui_right()
elif Input.is_action_just_pressed("ui_up"):
_ui_up()
elif Input.is_action_just_pressed("ui_down"):
_ui_down()
elif Input.is_action_just_pressed("ui_focus_prev"):
_ui_focus_prev()
elif Input.is_action_just_pressed("ui_focus_next"):
_ui_focus_next()
get_tree().set_input_as_handled()
in_focus_mode_handler = false
return
2020-05-19 17:03:59 +00:00
if event is InputEventScreenTouch:
get_tree().set_input_as_handled()
if touch_index and event.index != touch_index:
return
if event.pressed:
touch_index = event.index
touch_position = event.position
touch_start_time = OS.get_ticks_msec()
touch_stop_time = null
2020-06-09 19:29:57 +00:00
elif touch_position:
2020-05-19 17:03:59 +00:00
touch_index = null
var relative = event.position - touch_position
if relative.length() < min_swipe_distance:
tap_count += 1
elif not explore_by_touch:
if abs(relative.x) > abs(relative.y):
if relative.x > 0:
emit_signal("swipe_right")
else:
emit_signal("swipe_left")
else:
if relative.y > 0:
emit_signal("swipe_down")
else:
emit_signal("swipe_up")
touch_position = null
touch_start_time = null
touch_stop_time = OS.get_ticks_msec()
explore_by_touch = false
elif event is InputEventScreenDrag:
if touch_index and event.index != touch_index:
return
if (
not explore_by_touch
and OS.get_ticks_msec() - touch_start_time >= explore_by_touch_interval
):
explore_by_touch = true
if event is InputEventMouseButton:
if event.device == -1 and not explore_by_touch:
get_tree().set_input_as_handled()
2019-12-27 18:54:27 +00:00
func _process(delta):
2020-05-19 17:03:59 +00:00
if not enabled:
return
if (
touch_stop_time
and OS.get_ticks_msec() - touch_stop_time >= tap_execute_interval
and tap_count != 0
):
touch_stop_time = null
if tap_count == 2:
_press_and_release("ui_accept")
2020-05-19 17:03:59 +00:00
tap_count = 0