2023-11-22 02:44:07 +02:00
|
|
|
extends Node
|
|
|
|
|
|
|
|
const FN_PREFIX = "_on_"
|
|
|
|
const SIGNAL_PREFIX = "on_"
|
|
|
|
|
|
|
|
# Interaction Events
|
|
|
|
signal on_click(event: EventRay)
|
|
|
|
signal on_press_down(event: EventRay)
|
|
|
|
signal on_press_move(event: EventRay)
|
|
|
|
signal on_press_up(event: EventRay)
|
|
|
|
signal on_grab_down(event: EventRay)
|
|
|
|
signal on_grab_move(event: EventRay)
|
|
|
|
signal on_grab_up(event: EventRay)
|
|
|
|
signal on_ray_enter(event: EventRay)
|
|
|
|
signal on_ray_leave(event: EventRay)
|
|
|
|
|
|
|
|
signal on_key_down(event: EventKey)
|
|
|
|
signal on_key_up(event: EventKey)
|
|
|
|
|
2023-11-22 18:35:54 +02:00
|
|
|
signal on_focus_in(event: EventFocus)
|
|
|
|
signal on_focus_out(event: EventFocus)
|
|
|
|
|
|
|
|
var active_node: Node = null
|
|
|
|
|
2023-11-22 02:44:07 +02:00
|
|
|
func emit(type: String, event: Event):
|
|
|
|
if event is EventBubble:
|
|
|
|
_bubble_call(type, event.target, event)
|
2023-11-22 18:35:54 +02:00
|
|
|
if event.target.is_in_group("ui_focus"):
|
|
|
|
_handle_focus(event.target)
|
|
|
|
else:
|
|
|
|
_handle_focus(null)
|
2023-11-22 02:44:07 +02:00
|
|
|
else:
|
|
|
|
_root_call(type, event)
|
|
|
|
|
2023-11-22 18:35:54 +02:00
|
|
|
func _handle_focus(node: Node):
|
|
|
|
var event = EventFocus.new()
|
|
|
|
event.previous_target = active_node
|
|
|
|
event.target = node
|
|
|
|
|
|
|
|
if active_node != null && active_node.has_method(FN_PREFIX + "focus_in"):
|
|
|
|
active_node.call(FN_PREFIX + "focus_out", event)
|
|
|
|
on_focus_out.emit(event)
|
|
|
|
|
|
|
|
active_node = node
|
|
|
|
|
|
|
|
if active_node != null:
|
|
|
|
active_node.call(FN_PREFIX + "focus_in", event)
|
|
|
|
on_focus_in.emit(event)
|
2023-11-22 02:44:07 +02:00
|
|
|
|
|
|
|
func _bubble_call(type: String, target: Variant, event: EventBubble):
|
|
|
|
if target == null:
|
2023-11-22 18:35:54 +02:00
|
|
|
return false
|
2023-11-22 02:44:07 +02:00
|
|
|
|
|
|
|
if target.has_method(FN_PREFIX + type):
|
|
|
|
var updated_event = target.call(FN_PREFIX + type, event)
|
|
|
|
|
|
|
|
if updated_event is EventBubble:
|
|
|
|
updated_event.merge(event)
|
|
|
|
event = updated_event
|
|
|
|
|
|
|
|
if event.bubbling == false:
|
2023-11-22 18:35:54 +02:00
|
|
|
return false
|
2023-11-22 02:44:07 +02:00
|
|
|
|
|
|
|
for child in target.get_children():
|
|
|
|
if child is Function && child.has_method(FN_PREFIX + type):
|
|
|
|
child.call(FN_PREFIX + type, event)
|
|
|
|
|
|
|
|
var parent = target.get_parent()
|
|
|
|
|
|
|
|
if parent != null && parent is Node:
|
|
|
|
_bubble_call(type, parent, event)
|
|
|
|
else:
|
|
|
|
# in case the top has been reached
|
|
|
|
_root_call(type, event)
|
|
|
|
|
2023-11-22 18:35:54 +02:00
|
|
|
return true
|
|
|
|
|
2023-11-22 02:44:07 +02:00
|
|
|
|
|
|
|
func _root_call(type: String, event: Event):
|
|
|
|
get(SIGNAL_PREFIX + type).emit(event)
|