From 446e4a291cb065c62221d1fc0bfa65bd3243da55 Mon Sep 17 00:00:00 2001 From: Mario Steele Date: Tue, 10 Mar 2026 10:15:52 -0500 Subject: [PATCH 1/9] Updated Alerts Updated pathing for Alerts. --- UI/Alerts/cheer_alert.tscn | 7 +++---- UI/Alerts/follow_alert.tscn | 4 ++-- UI/Alerts/raid_alert.tscn | 6 +++--- UI/Alerts/subscriber_alert.tscn | 7 +++---- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/UI/Alerts/cheer_alert.tscn b/UI/Alerts/cheer_alert.tscn index a98e63cb..a970e116 100644 --- a/UI/Alerts/cheer_alert.tscn +++ b/UI/Alerts/cheer_alert.tscn @@ -190,7 +190,7 @@ offset_bottom = 270.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_7rajh") -path = "res://UI/assets/video/Backgrounds/Lightning-Synthwave.webm" +path = "res://assets/video/Backgrounds/Lightning-Synthwave.webm" metadata/_custom_type_script = "uid://ivx7m2bfysip" [node name="Icon" type="Control" parent="." unique_id=823113899] @@ -209,7 +209,7 @@ offset_bottom = -43.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_7rajh") -path = "res://UI/assets/video/Backgrounds/Bits-Synthwave.webm" +path = "res://assets/video/Backgrounds/Bits-Synthwave.webm" enable_audio = false metadata/_custom_type_script = "uid://ivx7m2bfysip" @@ -228,7 +228,7 @@ offset_right = 183.0 offset_bottom = -25.0 grow_horizontal = 2 grow_vertical = 2 -text = "x40 Bits" +text = "x0 bits" label_settings = SubResource("LabelSettings_t8pat") horizontal_alignment = 1 @@ -267,7 +267,6 @@ offset_right = 500.0 offset_bottom = 255.0 grow_horizontal = 2 grow_vertical = 2 -text = "Born to late to explore Earth, born to early to explore the universe" label_settings = SubResource("LabelSettings_vhkt3") horizontal_alignment = 1 autowrap_mode = 2 diff --git a/UI/Alerts/follow_alert.tscn b/UI/Alerts/follow_alert.tscn index 0991ae74..38242220 100644 --- a/UI/Alerts/follow_alert.tscn +++ b/UI/Alerts/follow_alert.tscn @@ -161,7 +161,7 @@ offset_bottom = 270.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_86a2m") -path = "res://UI/assets/video/Backgrounds/Stripes-Synthwave.webm" +path = "res://assets/video/Backgrounds/Stripes-Synthwave.webm" metadata/_custom_type_script = "uid://ivx7m2bfysip" [node name="Icon" type="Control" parent="." unique_id=823113899] @@ -180,7 +180,7 @@ offset_bottom = -43.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_86a2m") -path = "res://UI/assets/video/Icons/Joystick-Synthwave.webm" +path = "res://assets/video/Icons/Joystick-Synthwave.webm" enable_audio = false metadata/_custom_type_script = "uid://ivx7m2bfysip" diff --git a/UI/Alerts/raid_alert.tscn b/UI/Alerts/raid_alert.tscn index 675b4bbf..0e7fe7a8 100644 --- a/UI/Alerts/raid_alert.tscn +++ b/UI/Alerts/raid_alert.tscn @@ -163,7 +163,7 @@ offset_bottom = 270.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_yqbii") -path = "res://UI/assets/video/Backgrounds/Grid-Synthwave.webm" +path = "res://assets/video/Backgrounds/Grid-Synthwave.webm" metadata/_custom_type_script = "uid://ivx7m2bfysip" [node name="Icon" type="Control" parent="." unique_id=823113899] @@ -182,7 +182,7 @@ offset_bottom = -43.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_yqbii") -path = "res://UI/assets/video/Icons/Computer-Synthwave.webm" +path = "res://assets/video/Icons/Computer-Synthwave.webm" enable_audio = false metadata/_custom_type_script = "uid://ivx7m2bfysip" @@ -201,7 +201,7 @@ offset_right = 183.0 offset_bottom = -18.0 grow_horizontal = 2 grow_vertical = 2 -text = "Raid x10" +text = "Raid x0" label_settings = SubResource("LabelSettings_t8pat") horizontal_alignment = 1 diff --git a/UI/Alerts/subscriber_alert.tscn b/UI/Alerts/subscriber_alert.tscn index feee3889..a580e6d2 100644 --- a/UI/Alerts/subscriber_alert.tscn +++ b/UI/Alerts/subscriber_alert.tscn @@ -190,7 +190,7 @@ offset_bottom = 270.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_b3tp1") -path = "res://UI/assets/video/Backgrounds/Triangle-Synthwave.webm" +path = "res://assets/video/Backgrounds/Triangle-Synthwave.webm" metadata/_custom_type_script = "uid://ivx7m2bfysip" [node name="Icon" type="Control" parent="." unique_id=823113899] @@ -209,7 +209,7 @@ offset_bottom = -43.0 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("1_b3tp1") -path = "res://UI/assets/video/Icons/Hoverboard-Synthwave.webm" +path = "res://assets/video/Icons/Hoverboard-Synthwave.webm" enable_audio = false metadata/_custom_type_script = "uid://ivx7m2bfysip" @@ -228,7 +228,7 @@ offset_right = 183.0 offset_bottom = -25.0 grow_horizontal = 2 grow_vertical = 2 -text = "New Sub" +text = "New Teir 1 Sub" label_settings = SubResource("LabelSettings_t8pat") horizontal_alignment = 1 @@ -267,7 +267,6 @@ offset_right = 500.0 offset_bottom = 255.0 grow_horizontal = 2 grow_vertical = 2 -text = "Born to late to explore Earth, born to early to explore the universe" label_settings = SubResource("LabelSettings_dx50j") horizontal_alignment = 1 autowrap_mode = 2 From 23fdd1e972079ada8467cd60099e155ed0479b08 Mon Sep 17 00:00:00 2001 From: Mario Steele Date: Tue, 10 Mar 2026 10:16:33 -0500 Subject: [PATCH 2/9] Updated GameEntry Switched to using ImageLoader.load_image() Fixed bug in developer, to use itchio_data.authors --- UI/Controls/game_entry.gd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/UI/Controls/game_entry.gd b/UI/Controls/game_entry.gd index 80662597..4cb852c2 100644 --- a/UI/Controls/game_entry.gd +++ b/UI/Controls/game_entry.gd @@ -34,13 +34,13 @@ func populate() -> void: %GameName.text = steam_data.name %GameName.tooltip_text = steam_data.name var url_no_query: String = steam_data.header_image.split("?")[0] - %Background.texture = ImageTexture.create_from_image(await Globals.twitcher.media.load_image(url_no_query)) + %Background.texture = await ImageLoader.load_image(url_no_query) Type.ITCHIO: if not itchio_data: itchio_data = await %ItchIOService.get_itch_app_data(itchio_app_url) %GameName.text = itchio_data.title var url: String = itchio_data.cover_image - %Background.texture = ImageTexture.create_from_image(await Globals.twitcher.media.load_image(url)) + %Background.texture = await ImageLoader.load_image(url) func _reload_data() -> void: match type: @@ -72,7 +72,7 @@ func _promote_game() -> void: pass Type.ITCHIO: title = itchio_data.title - developer = itchio_data.developer + developer = itchio_data.authors.front()["name"] description = itchio_data.description.left(200) + "..." link = itchio_data.url msg = msg.format({ From cc01a207fcbd9a49feb4ca4346e57dae523a5172 Mon Sep 17 00:00:00 2001 From: Mario Steele Date: Tue, 10 Mar 2026 10:25:17 -0500 Subject: [PATCH 3/9] Updated InternalUserLive Added Offline details to Live panel. When user has an Offline Image, we load the image to display in the Stream Preview, otherwise we do a Generic Twitch Logo, with text saying the Stream is Offline. --- UI/Panels/User/internal_user_live.gd | 33 +++++++++++++++++++++++--- UI/Panels/User/internal_user_live.tscn | 31 ++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/UI/Panels/User/internal_user_live.gd b/UI/Panels/User/internal_user_live.gd index 6fb19b05..60152d9d 100644 --- a/UI/Panels/User/internal_user_live.gd +++ b/UI/Panels/User/internal_user_live.gd @@ -1,10 +1,14 @@ extends PanelContainer +var _offline_color := Color.html("d36dff4e") +var _offline_no_thumbnail := preload("res://assets/bootstrap/twitch_large.svg") + var chatter: Chatter: set(value): chatter = value if not chatter: live = null + clear() return live = Globals.live_streamers[chatter.twitch_id] if chatter.twitch_id in Globals.live_streamers.keys() else null _populate_view() @@ -17,21 +21,44 @@ var _ticks: int = 0 func _ready() -> void: %StreamTitle.pressed.connect(_open_stream) %RaidCurrentUser.pressed.connect(_raid_stream) - if not chatter: return + if not chatter: + clear() + return if not live and chatter.twitch_id in Globals.live_streamers.keys(): live = Globals.live_streamers[chatter.twitch_id] _populate_view() + elif not live: + clear() + return + +func clear() -> void: + %StreamTitle.text = "Not Live" + %StreamViewerCount.text = "0" + %StreamTime.text = "00:00:00" + %StreamThumbnail.visible = false + %OfflineThumbnail.visible = true + %NoThumbText.visible = true + if chatter: + if chatter.user.offline_image_url != "": + %OfflineThumbnail.texture = await ImageLoader.load_image(chatter.user.offline_image_url) + %OfflineThumbnail.self_modulate = Color.WHITE + %NoThumbText.visible = false + return + %OfflineThumbnail.texture = _offline_no_thumbnail + %OfflineThumbnail.self_modulate = _offline_color func _populate_view() -> void: if not live: set_process(false) + clear() return set_process(true) %StreamTitle.text = live.title %StreamViewerCount.text = str(live.viewer_count) var url := live.thumbnail_url.format({"width": 640, "height": 360}) - var img = await Globals.twitcher.media.load_image(url) - %StreamThumbnail.texture = ImageTexture.create_from_image(img) + %StreamThumbnail.texture = await ImageLoader.load_image(url) + %StreamThumbnail.visible = true + %OfflineThumbnail.visible = false func _process(_d: float) -> void: if not live: diff --git a/UI/Panels/User/internal_user_live.tscn b/UI/Panels/User/internal_user_live.tscn index 02702326..fa5e48d6 100644 --- a/UI/Panels/User/internal_user_live.tscn +++ b/UI/Panels/User/internal_user_live.tscn @@ -2,8 +2,12 @@ [ext_resource type="Script" uid="uid://cdtfvedghei5f" path="res://UI/Panels/User/internal_user_live.gd" id="1_rl2q8"] [ext_resource type="Texture2D" uid="uid://b3372gsnwqsyn" path="res://assets/bootstrap/twitch.svg" id="1_sw5jj"] +[ext_resource type="Texture2D" uid="uid://bvmx86tvio46h" path="res://assets/bootstrap/twitch_large.svg" id="2_lcbo3"] [ext_resource type="Texture2D" uid="uid://bu2juj2beyws7" path="res://assets/twitch_user_profile_pic.png" id="2_rl2q8"] +[sub_resource type="LabelSettings" id="LabelSettings_2ohcs"] +font_size = 72 + [node name="InternalUserLive" type="PanelContainer" unique_id=17956466] anchors_preset = 15 anchor_right = 1.0 @@ -26,11 +30,38 @@ size_flags_vertical = 3 [node name="StreamThumbnail" type="TextureRect" parent="VBoxContainer/HBoxContainer" unique_id=641456832] unique_name_in_owner = true +visible = false layout_mode = 2 size_flags_horizontal = 3 expand_mode = 1 stretch_mode = 5 +[node name="OfflineThumbnail" type="TextureRect" parent="VBoxContainer/HBoxContainer" unique_id=924088665] +unique_name_in_owner = true +self_modulate = Color(0.827451, 0.42745098, 1, 0.30588236) +layout_mode = 2 +size_flags_horizontal = 3 +texture = ExtResource("2_lcbo3") +expand_mode = 1 +stretch_mode = 5 + +[node name="NoThumbText" type="Label" parent="VBoxContainer/HBoxContainer/OfflineThumbnail" unique_id=1187072643] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -20.0 +offset_top = -11.5 +offset_right = 20.0 +offset_bottom = 11.5 +grow_horizontal = 2 +grow_vertical = 2 +text = "Stream Offline" +label_settings = SubResource("LabelSettings_2ohcs") + [node name="UserChat" type="PanelContainer" parent="VBoxContainer/HBoxContainer" unique_id=1609959534] unique_name_in_owner = true visible = false From eb16b80134a136df3af1e2c2123bf52666cf5e6f Mon Sep 17 00:00:00 2001 From: Mario Steele Date: Tue, 10 Mar 2026 10:27:40 -0500 Subject: [PATCH 4/9] Updated UserGames Renamed search and add functions for Steam to _handle_steam_*, Added ItchIO handlers Updated Steam Add to check and see if we have already fetched the App information, and if so, use it, otherwise try to search. *Note* Need to clear after adding, so we don't accidently add to the wrong user, and need to validate if the game has already been added or not. Added Logic to for ItchIO. --- UI/Panels/User/user_games.gd | 76 ++++++++++++++++++++++++---------- UI/Panels/User/user_games.tscn | 4 +- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/UI/Panels/User/user_games.gd b/UI/Panels/User/user_games.gd index b45a1b89..6dfb25ca 100644 --- a/UI/Panels/User/user_games.gd +++ b/UI/Panels/User/user_games.gd @@ -11,10 +11,13 @@ var chatter: Chatter: populate_games() func _ready() -> void: - %SteamSearch.pressed.connect(_handle_search) - %AddSteamGame.pressed.connect(_handle_add) + %SteamSearch.pressed.connect(_handle_steam_search) + %AddSteamGame.pressed.connect(_handle_steam_add) + %ItchFetch.pressed.connect(_handle_itch_search) + %ItchAdd.pressed.connect(_handle_itch_add) -func _handle_search() -> void: +#region Steam Search +func _handle_steam_search() -> void: var info: String = %SteamGameInput.text var app_id: int = -1 if info.begins_with("https:"): @@ -32,27 +35,58 @@ func _handle_search() -> void: %SteamAppPanel.display_app_info(data) %SteamAppPanel.show() -func _handle_add() -> void: - var info: String = %SteamGameInput.text - var app_id: int = -1 - if info.begins_with("https:"): - var parts = Array(info.split("/")) - parts.reverse() - for part in parts: - if part.is_valid_int(): - app_id = part.to_int() - break - elif info.is_valid_int(): - app_id = info.to_int() +func _handle_steam_add() -> void: + if %SteamAppPanel.data: + var app: SteamAppData = %SteamAppPanel.data + chatter.steam_games.append(app.steam_app_id) + else: + var info: String = %SteamGameInput.text + var app_id: int = -1 + if info.begins_with("https:"): + var parts = Array(info.split("/")) + parts.reverse() + for part in parts: + if part.is_valid_int(): + app_id = part.to_int() + break + elif info.is_valid_int(): + app_id = info.to_int() - if app_id == -1: return + if app_id == -1: return - var data: SteamAppData = await %SteamService.get_steam_app_data(app_id) + var data: SteamAppData = await %SteamService.get_steam_app_data(app_id) + if data: + chatter.steam_games.append(app_id) + + chatter.save() + clear() + populate_games() +#endregion + +#region Itch Search +func _handle_itch_search() -> void: + var info: String = %ItchInput.text + if not (info.begins_with("http://") or info.begins_with("https://")): return + var data: ItchIOAppData = await %ItchIOService.get_itch_app_data(info) if data: - chatter.steam_games.append(app_id) - chatter.save() - clear() - populate_games() + %ItchAppPanel.display_app_info(data) + %ItchAppPanel.show() + +func _handle_itch_add() -> void: + if %ItchAppPanel.data: + var app: ItchIOAppData = %ItchAppPanel.data + chatter.itch_games[app.title] = app.url + else: + var info: String = %ItchInput.text + if not (info.begins_with("http://") or info.begins_with("https://")): return + + var data: ItchIOAppData = await %ItchIOService.get_itch_app_data(info) + if data: + chatter.itch_games[data.title] = data.url + chatter.save() + clear() + populate_games() +#endregion func populate_games() -> void: for game in chatter.steam_games: diff --git a/UI/Panels/User/user_games.tscn b/UI/Panels/User/user_games.tscn index 45ec8033..a585fabc 100644 --- a/UI/Panels/User/user_games.tscn +++ b/UI/Panels/User/user_games.tscn @@ -9,7 +9,7 @@ [ext_resource type="Script" uid="uid://bllsv2cy6komw" path="res://lib/models/steam_app_data.gd" id="4_myc1y"] [ext_resource type="PackedScene" uid="uid://c0ahhupmdstxq" path="res://UI/Panels/itch_app_panel.tscn" id="8_hk3mv"] -[sub_resource type="Resource" id="Resource_hk3mv"] +[sub_resource type="Resource" id="Resource_yiww1"] script = ExtResource("4_myc1y") steam_app_id = 3712430 type = "game" @@ -240,7 +240,7 @@ tabs_visible = false unique_name_in_owner = true visible = false layout_mode = 2 -test_data = SubResource("Resource_hk3mv") +test_data = SubResource("Resource_yiww1") metadata/_tab_index = 0 [node name="ItchAppPanel" parent="Splitter/TabContainer" unique_id=691251029 instance=ExtResource("8_hk3mv")] From f782cc32d4fb13af63590f6e7589fed6b38eec08 Mon Sep 17 00:00:00 2001 From: Mario Steele Date: Tue, 10 Mar 2026 10:29:46 -0500 Subject: [PATCH 5/9] Updated Custom Runner Added check to see if the setting exists, before setting it to prevent over-writting. Need to figure out if output is working or not, since not able to clear() the RichTextLabel. Changed launch parameters to use Remote Debug. Need to ensure that Debug > Keep Debug Server Open in order to use. --- addons/custom_runner/plugin.gd | 38 ++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/addons/custom_runner/plugin.gd b/addons/custom_runner/plugin.gd index 3a54ce04..3f02f8e8 100644 --- a/addons/custom_runner/plugin.gd +++ b/addons/custom_runner/plugin.gd @@ -6,7 +6,8 @@ var _play_icon: Texture2D var _stop_icon: Texture2D func _enter_tree() -> void: - ProjectSettings.set("application/run/custom_runner", "") + if not ProjectSettings.has_setting("application/run/custom_rinner"): + ProjectSettings.set("application/run/custom_runner", "") ProjectSettings.add_property_info({ "name": "application/run/custom_runner", "type": TYPE_STRING, @@ -25,7 +26,6 @@ func _exit_tree() -> void: _runner_btn.queue_free() _runner_btn = null - class RunnerButton: extends Button @@ -34,6 +34,7 @@ class RunnerButton: var _running_pid: int = -1 var _io: FileAccess = null var _err: FileAccess = null + var _output: RichTextLabel = null func _init() -> void: _play = EditorInterface.get_editor_theme().get_icon(&"Play", &"EditorIcons") @@ -85,13 +86,16 @@ class RunnerButton: var run_arguments := [ godot, "--path", project, - "-d" - #"--remote-debug", "tcp://%s:%s" % [host, port], - #"--editor-pid", "%s" % pid, - #"--position", "320,-24", - #"--scene", main_scene + #"-d" + "--remote-debug", "tcp://%s:%s" % [host, port], + "--editor-pid", "%s" % pid, + "--position", "320,-24", + "--scene", main_scene ] # --remote-debug tcp://127.0.0.1:6007 --editor-pid 3480813 --position 320,-24 --scene uid://2t2hslaaewee + if not _output: _output = _get_output() + if _output: + _output.clear() print("Executing project with the following Command Line: %s %s" % [runner, run_arguments]) @@ -117,12 +121,12 @@ class RunnerButton: await get_tree().process_frame var res := _read_io(_io, output) - if res != "": - print_rich(res) + #if res != "": + #print_rich(res) res = _read_io(_err, err) - if res != "": - print_rich(res) + #if res != "": + #print_rich(res) await get_tree().process_frame var str := _read_io(_io, output) @@ -149,3 +153,15 @@ class RunnerButton: buffer.clear() buffer.append_array(leftover) return part.get_string_from_utf8() + + func _get_output() -> RichTextLabel: + return _find_output(get_tree().root) + + func _find_output(current: Node) -> RichTextLabel: + if current is RichTextLabel and current.get_parent() and current.get_parent().get_parent() and current.get_parent().get_parent().name.begins_with("@EditorLog"): + return current + for c in current.get_children(true): + var r = _find_output(c) + if r: + return r + return null From 7b1237b70237b37ea36ab2ba96f1ebf09a47929d Mon Sep 17 00:00:00 2001 From: Mario Steele Date: Tue, 10 Mar 2026 10:30:50 -0500 Subject: [PATCH 6/9] Created Larger Logo This is the same as twitch.svg, but since we can't "update" svg to have multiple sizes, manually setup size of the same SVG as a new file of the same content. --- assets/bootstrap/twitch_large.svg | 5 +++ assets/bootstrap/twitch_large.svg.import | 43 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 assets/bootstrap/twitch_large.svg create mode 100644 assets/bootstrap/twitch_large.svg.import diff --git a/assets/bootstrap/twitch_large.svg b/assets/bootstrap/twitch_large.svg new file mode 100644 index 00000000..3e72a83d --- /dev/null +++ b/assets/bootstrap/twitch_large.svg @@ -0,0 +1,5 @@ + + + +> + \ No newline at end of file diff --git a/assets/bootstrap/twitch_large.svg.import b/assets/bootstrap/twitch_large.svg.import new file mode 100644 index 00000000..ecf2e798 --- /dev/null +++ b/assets/bootstrap/twitch_large.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bvmx86tvio46h" +path="res://.godot/imported/twitch_large.svg-f412c62f24767edcd1ef4fb3abeb1597.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/bootstrap/twitch_large.svg" +dest_files=["res://.godot/imported/twitch_large.svg-f412c62f24767edcd1ef4fb3abeb1597.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=20.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false From eb64045e41b428c4244edd89e4698c1f1ac6ec5b Mon Sep 17 00:00:00 2001 From: Mario Steele Date: Tue, 10 Mar 2026 10:31:16 -0500 Subject: [PATCH 7/9] Updated OverlayPlugin Added send_message() function, more functionality to be implemented. --- lib/scripting/overlay_plugin.gd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/scripting/overlay_plugin.gd b/lib/scripting/overlay_plugin.gd index 44512ac7..237c6f7d 100644 --- a/lib/scripting/overlay_plugin.gd +++ b/lib/scripting/overlay_plugin.gd @@ -19,6 +19,9 @@ func _get_script_name() -> String: return self.get_script().get_global_name() #endregion +func send_message(msg: String) -> void: + _twitch.send_message(msg) + func send_notification(message: String) -> void: EventManager.test_notification(message) From 4d6de8d46f82566f6874bbc85eac041324183eb8 Mon Sep 17 00:00:00 2001 From: Mario Steele Date: Tue, 10 Mar 2026 10:32:06 -0500 Subject: [PATCH 8/9] Created ImageLoader class. Created ImageLoader class to load images. Since Twitch doesn't always send proper information about the file, we detect image format by the file byte header, to ensure we are loading the correct image format. --- lib/image_loader.gd | 56 +++++++++++++++++++++++++++++++++++++++++ lib/image_loader.gd.uid | 1 + 2 files changed, 57 insertions(+) create mode 100644 lib/image_loader.gd create mode 100644 lib/image_loader.gd.uid diff --git a/lib/image_loader.gd b/lib/image_loader.gd new file mode 100644 index 00000000..2b631783 --- /dev/null +++ b/lib/image_loader.gd @@ -0,0 +1,56 @@ +extends Node + +var _client: BufferedHTTPClient + +enum ImgFmt { PNG, JPG, WEBP, BMP, GIF, UNKNOWN } + +func _identify_image(byte_array: PackedByteArray) -> ImgFmt: + if byte_array.size() < 8: + return ImgFmt.UNKNOWN + + # PNG magic bytes: 0x89, P, N, G, \r, \n, 0x1a, \n + if byte_array[0] == 0x89 and byte_array[1] == 0x50 and byte_array[2] == 0x4E and byte_array[3] == 0x47: + return ImgFmt.PNG + + # JPEG magic bytes (starts with 0xFF, 0xD8) + if byte_array[0] == 0xFF and byte_array[1] == 0xD8: + return ImgFmt.JPG + + # WebP magic bytes (RIFF header, "WEBP" at offset 8) + if byte_array[0] == 0x52 and byte_array[1] == 0x49 and byte_array[2] == 0x46 and byte_array[3] == 0x46 and \ + byte_array[8] == 0x57 and byte_array[9] == 0x45 and byte_array[10] == 0x42 and byte_array[11] == 0x50: + return ImgFmt.JPG + + # BMP Magic (Starts with 0x42, 0x4D + if byte_array[0] == 0x42 and byte_array[1] == 0x4D: + return ImgFmt.BMP + + if byte_array[0] == 0x47 and byte_array[1] == 0x49 and byte_array[2] == 0x46: + return ImgFmt.GIF + + return ImgFmt.UNKNOWN + +func _ready() -> void: + _client = BufferedHTTPClient.new() + _client.name = "ImageLoaderHTTPClient" + add_child(_client) + +func load_image(url: String) -> ImageTexture: + var request : BufferedHTTPClient.RequestData = _client.request(url, HTTPClient.METHOD_GET, {}, "") + var response : BufferedHTTPClient.ResponseData = await _client.wait_for_request(request) + var img_buffer: PackedByteArray = response.response_data + var img: Image = Image.new() + match _identify_image(img_buffer): + ImgFmt.PNG: + img.load_png_from_buffer(img_buffer) + ImgFmt.JPG: + img.load_jpg_from_buffer(img_buffer) + ImgFmt.WEBP: + img.load_webp_from_buffer(img_buffer) + ImgFmt.BMP: + img.load_bmp_from_buffer(img_buffer) + ImgFmt.GIF: + push_error("Attempting to load a GIF image, use media loader to load.") + ImgFmt.UNKNOWN: + push_error("Failed to identify file!") + return ImageTexture.create_from_image(img) diff --git a/lib/image_loader.gd.uid b/lib/image_loader.gd.uid new file mode 100644 index 00000000..10b85724 --- /dev/null +++ b/lib/image_loader.gd.uid @@ -0,0 +1 @@ +uid://b1m82tihhr2p7 From 33b5e826bdc52289d9094efc269fd57f2b5a7251 Mon Sep 17 00:00:00 2001 From: Mario Steele Date: Tue, 10 Mar 2026 10:32:31 -0500 Subject: [PATCH 9/9] Updated Project Settings Added custom run command /usr/bin/obs-gamecapture. --- project.godot | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/project.godot b/project.godot index 4b95eb92..84064aed 100644 --- a/project.godot +++ b/project.godot @@ -15,7 +15,7 @@ config/description="Enter an interesting project description here!" run/main_scene="uid://2t2hslaaewee" config/features=PackedStringArray("4.6") config/icon="res://icon.png" -run/custom_runner="" +run/custom_runner="/usr/bin/obs-gamecapture" GData_ORM/migration/use_number=true GData_ORM/migration/folder="res://migrations" GData_ORM/migration/debug_migrations=true @@ -26,6 +26,7 @@ Globals="*uid://cuap0k5jagdtj" ChatManager="*uid://ct1s5eymb8mns" EventManager="*uid://cvjhecj1me4xl" ObsManager="*uid://c447ij3oc24q3" +ImageLoader="*uid://b1m82tihhr2p7" [display] @@ -41,7 +42,7 @@ window/per_pixel_transparency/allowed=true [editor_plugins] -enabled=PackedStringArray("res://addons/gdata_orm/plugin.cfg", "res://addons/gde_gozen/plugin.cfg", "res://addons/kenny_spritesheet_importer/plugin.cfg", "res://addons/no-obs-ws/plugin.cfg", "res://addons/sc_editor/plugin.cfg", "res://addons/twitcher/plugin.cfg") +enabled=PackedStringArray("res://addons/custom_runner/plugin.cfg", "res://addons/gdata_orm/plugin.cfg", "res://addons/gde_gozen/plugin.cfg", "res://addons/kenny_spritesheet_importer/plugin.cfg", "res://addons/no-obs-ws/plugin.cfg", "res://addons/sc_editor/plugin.cfg", "res://addons/twitcher/plugin.cfg") [gui]