extends Node #region Signals signal live_streamers_updating signal live_streamers_updated #endregion #region Public Variables var twitcher: TwitcherExtended: set(val): twitcher = val twitcher.streamer_token_validated.connect(_setup_live_stream_timer) var context: OverlayContext var settings: OverlaySettings var main_win: OverlayWindow var live_streamers: Dictionary[String, TwitchStream] = {} #endregion #region Private Variables var _pt_except: Array[Control] = [] var _pt_mouse: bool = false var _current_pt_mask: PackedVector2Array = [] var _hull_points: PackedVector2Array = [] var _debug_draw: DebugDraw var _tmr_live_stream: Timer #endregion # Called when the node enters the scene tree for the first time. func _ready() -> void: context = OverlayContext.new() context.setup() context.open_db("user://overlay.db") # Method one, just create all tables, prevents alterations to existing tables. #context.ensure_tables() # Method two, use migrations to handle setting up database tables, ensuring that # tables can be modified in the future context.run_migrations() if FileAccess.file_exists("user://settings.tres"): settings = load("user://settings.tres") else: settings = OverlaySettings.new() func _exit_tree() -> void: save_settings() func _input(_event: InputEvent) -> void: if Input.is_action_just_pressed("debug_draw"): if _debug_draw: _debug_draw.queue_free() _debug_draw = null else: _debug_draw = DebugDraw.new() add_child(_debug_draw) func _setup_live_stream_timer() -> void: if _tmr_live_stream: return _tmr_live_stream = Timer.new() _tmr_live_stream.name = "TimerLiveStreamCheck" _tmr_live_stream.wait_time = 240 _tmr_live_stream.one_shot = false _tmr_live_stream.timeout.connect(_run_live_streamer_update) add_child(_tmr_live_stream) _run_live_streamer_update() _tmr_live_stream.start() func _run_live_streamer_update() -> void: live_streamers_updating.emit() live_streamers = await twitcher.get_live_streamers_data() live_streamers_updated.emit() func save_settings() -> void: ResourceSaver.save(settings, "user://settings.tres") func clear_mouse_passthrough() -> void: DisplayServer.window_set_mouse_passthrough([]) func _update_mouse_passthrough() -> void: if not _pt_mouse: return var _pt_mask: PackedVector2Array = [] for node in _pt_except: var rect := node.get_global_rect() _pt_mask.append_array([ rect.position, Vector2(rect.position.x + rect.size.x, rect.position.y), rect.position + rect.size, Vector2(rect.position.x, rect.position.y + rect.size.y) ]) _current_pt_mask = _pt_mask var hull_points := Geometry2D.convex_hull(_pt_mask) _hull_points = hull_points DisplayServer.window_set_mouse_passthrough(hull_points) func _process(_d: float) -> void: if _pt_except.size() == 0: return if not _pt_mouse: return _update_mouse_passthrough() func add_to_passthrough_exception(control: Control) -> void: if not _pt_except.has(control): _pt_except.append(control) control.item_rect_changed.connect(_update_mouse_passthrough) func add_children_to_passthrough_exception(control: Control, ignore: Array[Control] = []) -> void: if not _pt_except.has(control): _pt_except.append(control) for child in control.get_children(): if child in ignore: continue if child.get_child_count() > 0: add_children_to_passthrough_exception(child, ignore) else: _pt_except.append(child) child.item_rect_changed.connect(_update_mouse_passthrough) func remove_from_passthrough_exceptioon(control: Control) -> void: if _pt_except.has(control): _pt_except.erase(control) control.item_rect_changed.disconnect(_update_mouse_passthrough) func enable_mouse_passthrough() -> void: if _pt_mouse: return _pt_mouse = true _update_mouse_passthrough() func disable_mouse_passthrough() -> void: if not _pt_mouse: return _pt_mouse = false clear_mouse_passthrough() func get_exception_points() -> PackedVector2Array: return _current_pt_mask func get_polygon_points() -> PackedVector2Array: return _hull_points