From 7f9b6529183c2d82cffe2e8dcff93e8683310583 Mon Sep 17 00:00:00 2001 From: Max Litruv Boonzaayer Date: Sat, 19 Jul 2025 18:23:35 +1000 Subject: [PATCH] Re-Enabled streamdeck plugin --- .vscode/settings.json | 2 +- addons/godot-streamdeck-addon/plugin.gd | 11 ++++- addons/godot-streamdeck-addon/singleton.gd | 57 ++++++++++++++++++---- main_scenes/main.tscn | 5 +- ui_scenes/settings/settings_menu.gd | 18 ++++++- ui_scenes/settings/settings_menu.tscn | 21 ++++++-- 6 files changed, 96 insertions(+), 18 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 67aec9e..16c5cf1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "godotTools.editorPath.godot4": "c:\\Users\\litru\\Downloads\\Godot_v4.1.2-stable_win64.exe\\Godot_v4.1.2-stable_win64.exe" + "godotTools.editorPath.godot4": "c:\\Users\\litru\\Downloads\\Godot_v4.4.1-stable_win64.exe" } \ No newline at end of file diff --git a/addons/godot-streamdeck-addon/plugin.gd b/addons/godot-streamdeck-addon/plugin.gd index 81f15f5..6037549 100644 --- a/addons/godot-streamdeck-addon/plugin.gd +++ b/addons/godot-streamdeck-addon/plugin.gd @@ -1,12 +1,19 @@ @tool extends EditorPlugin +## StreamDeck Editor Plugin +## +## This plugin integrates Elgato StreamDeck hardware with the PNGTuber application. +## It registers the ElgatoStreamDeck singleton for WebSocket communication with StreamDeck software. + const AUTOLOAD_NAME = "ElgatoStreamDeck" +## Called when the plugin enters the editor tree +## Registers the StreamDeck singleton autoload func _enter_tree(): add_autoload_singleton(AUTOLOAD_NAME, "res://addons/godot-streamdeck-addon/singleton.gd") - pass +## Called when the plugin exits the editor tree +## Removes the StreamDeck singleton autoload func _exit_tree(): remove_autoload_singleton(AUTOLOAD_NAME) - pass diff --git a/addons/godot-streamdeck-addon/singleton.gd b/addons/godot-streamdeck-addon/singleton.gd index 4630a8b..ab72781 100644 --- a/addons/godot-streamdeck-addon/singleton.gd +++ b/addons/godot-streamdeck-addon/singleton.gd @@ -1,17 +1,27 @@ extends Node +## StreamDeck Integration Singleton +## +## This singleton manages WebSocket communication with Elgato StreamDeck software. +## It handles button press events and translates them into application actions like +## costume changes, signal emissions, and scene management. + +## Button actions supported by the StreamDeck plugin const ButtonAction = { EMIT_SIGNAL = "games.boyne.godot.emitsignal", SWITCH_SCENE = "games.boyne.godot.switchscene", RELOAD_SCENE = "games.boyne.godot.reloadscene", } +## Button events from StreamDeck hardware const ButtonEvent = { KEY_UP = "keyUp", KEY_DOWN = "keyDown" } +## Emitted when a StreamDeck button is released signal on_key_up +## Emitted when a StreamDeck button is pressed signal on_key_down const PLUGIN_NAME = "games.boyne.godot.sdPlugin" @@ -19,19 +29,36 @@ const WEBSOCKET_URL = "127.0.0.1:%s/ws" var _socket := WebSocketPeer.new() var _config := ConfigFile.new() +var _is_connected := false +## Initialize StreamDeck connection if enabled in settings func _ready() -> void: + _check_and_connect() + +## Check settings and connect/disconnect as needed +func _check_and_connect() -> void: + var should_connect = Saving.settings.get("useStreamDeck", false) - if Saving.settings.has("useStreamDeck"): - if !Saving.settings["useStreamDeck"]: - return - else: - return - - _load_config(_get_config_path()) - _socket.connect_to_url(_get_websocket_url()) + if should_connect and not _is_connected: + _load_config(_get_config_path()) + _socket.connect_to_url(_get_websocket_url()) + _is_connected = true + set_process(true) + elif not should_connect and _is_connected: + _socket.close() + _is_connected = false + set_process(false) +## Process WebSocket communication each frame +## Handles incoming button events and routes them to appropriate actions func _process(delta) -> void: + if not _is_connected: + return + + # Check if setting was changed and we need to disconnect + if not Saving.settings.get("useStreamDeck", false): + _check_and_connect() + return _socket.poll() var state = _socket.get_ready_state() @@ -68,9 +95,13 @@ func _process(delta) -> void: WebSocketPeer.STATE_CLOSED: set_process(false) +## Get the WebSocket URL with port from config +## Returns: String URL for WebSocket connection func _get_websocket_url() -> String: return WEBSOCKET_URL % _config.get_value("bridge", "port", "8080") +## Get the platform-specific path to StreamDeck plugin config +## Returns: String path to plugin.ini file func _get_config_path() -> String: match OS.get_name(): "Windows": @@ -79,6 +110,14 @@ func _get_config_path() -> String: return "%s/com.elgato.StreamDeck/Plugins/%s/plugin.ini" % [OS.get_config_dir(), PLUGIN_NAME] return "" +## Load configuration from StreamDeck plugin directory +## @param path: String path to the config file func _load_config(path: String) -> void: var file = FileAccess.open(path, FileAccess.READ) - _config.parse(file.get_as_text()) + if file: + _config.parse(file.get_as_text()) + file.close() + +## Force reconnection check - called when settings change +func refresh_connection() -> void: + _check_and_connect() diff --git a/main_scenes/main.tscn b/main_scenes/main.tscn index 171b29f..44b9bc3 100644 --- a/main_scenes/main.tscn +++ b/main_scenes/main.tscn @@ -14260,7 +14260,7 @@ flat = true [node name="SettingsMenu" parent="ControlPanel" instance=ExtResource("25_a76ao")] visible = false z_index = 4096 -position = Vector2(-431, -560) +position = Vector2(-431, -590) [node name="Edit" type="Sprite2D" parent="ControlPanel"] texture_repeat = 2 @@ -14385,7 +14385,6 @@ text = "v1.4.5" label_settings = SubResource("LabelSettings_xvf50") [node name="EditControls" type="Node2D" parent="."] -visible = false z_index = 4090 script = ExtResource("17_bf1ic") @@ -14573,6 +14572,7 @@ position = Vector2(122, -58) shape = SubResource("RectangleShape2D_1hek3") [node name="SpriteList" parent="EditControls" instance=ExtResource("27_614d2")] +visible = false z_index = 4065 position = Vector2(486, 12) @@ -14610,6 +14610,7 @@ patch_margin_right = 8 patch_margin_bottom = 8 [node name="Label" type="Label" parent="Tutorial/NinePatchRect"] +visible = false layout_mode = 0 offset_left = 15.0 offset_top = 14.0 diff --git a/ui_scenes/settings/settings_menu.gd b/ui_scenes/settings/settings_menu.gd index b237072..927dc4f 100644 --- a/ui_scenes/settings/settings_menu.gd +++ b/ui_scenes/settings/settings_menu.gd @@ -1,9 +1,15 @@ extends Node2D -var awaitingCostumeInput = -1 +## Settings Menu Controller +## +## Manages the settings UI and user preferences for the PNGTuber application. +## Handles various settings including background color, FPS, bounce physics, +## costume keys, and StreamDeck integration. +var awaitingCostumeInput = -1 var hasMouse = false +## Initialize all setting values to match current configuration func setvalues(): $Background/ColorPickerButton.color = Global.backgroundColor @@ -32,6 +38,8 @@ func setvalues(): $bounceOnCostume/costumeCheck.button_pressed = Global.main.bounceOnCostumeChange + $StreamDeck/streamDeckCheck.button_pressed = Saving.settings["useStreamDeck"] + var costumeLabels = [$CostumeInputs/ScrollContainer/VBoxContainer/costumeButton1/Label,$CostumeInputs/ScrollContainer/VBoxContainer/costumeButton2/Label,$CostumeInputs/ScrollContainer/VBoxContainer/costumeButton3/Label,$CostumeInputs/ScrollContainer/VBoxContainer/costumeButton4/Label,$CostumeInputs/ScrollContainer/VBoxContainer/costumeButton5/Label,$CostumeInputs/ScrollContainer/VBoxContainer/costumeButton6/Label,$CostumeInputs/ScrollContainer/VBoxContainer/costumeButton7/Label,$CostumeInputs/ScrollContainer/VBoxContainer/costumeButton8/Label,$CostumeInputs/ScrollContainer/VBoxContainer/costumeButton9/Label,$CostumeInputs/ScrollContainer/VBoxContainer/costumeButton10/Label,] var tag = 1 for label in costumeLabels: @@ -190,6 +198,14 @@ func _on_costume_check_toggled(button_pressed): Global.main.bounceOnCostumeChange = button_pressed Saving.settings["bounceOnCostumeChange"] = button_pressed +## Handle StreamDeck integration toggle +## @param button_pressed: bool - Whether StreamDeck should be enabled +func _on_stream_deck_check_toggled(button_pressed): + Saving.settings["useStreamDeck"] = button_pressed + if ElgatoStreamDeck: + ElgatoStreamDeck.refresh_connection() + Global.pushUpdate("StreamDeck integration " + ("enabled" if button_pressed else "disabled") + ".") + func _process(delta): var g = to_local(get_global_mouse_position()) diff --git a/ui_scenes/settings/settings_menu.tscn b/ui_scenes/settings/settings_menu.tscn index 4ca2e66..2678a02 100644 --- a/ui_scenes/settings/settings_menu.tscn +++ b/ui_scenes/settings/settings_menu.tscn @@ -14183,7 +14183,7 @@ script = ExtResource("1_ckdhy") [node name="NinePatchRect" type="NinePatchRect" parent="."] offset_right = 419.0 -offset_bottom = 423.0 +offset_bottom = 444.0 texture = ExtResource("1_ylauk") region_rect = Rect2(0, 0, 48, 48) patch_margin_left = 8 @@ -14288,9 +14288,23 @@ offset_right = 378.0 offset_bottom = 28.0 text = "confirm" -[node name="AntiAliasing" type="Node2D" parent="."] +[node name="StreamDeck" type="Node2D" parent="."] position = Vector2(16, 373) +[node name="Label" type="Label" parent="StreamDeck"] +offset_right = 138.0 +offset_bottom = 34.0 +text = "use streamdeck" + +[node name="streamDeckCheck" type="CheckBox" parent="StreamDeck"] +offset_left = 130.0 +offset_top = 1.0 +offset_right = 154.0 +offset_bottom = 25.0 + +[node name="AntiAliasing" type="Node2D" parent="."] +position = Vector2(16, 405) + [node name="Label" type="Label" parent="AntiAliasing"] offset_right = 138.0 offset_bottom = 34.0 @@ -14373,7 +14387,7 @@ position = Vector2(404, 305) offset_left = -226.0 offset_top = -78.0 offset_right = 7.0 -offset_bottom = 103.0 +offset_bottom = 123.0 horizontal_scroll_mode = 0 [node name="VBoxContainer" type="VBoxContainer" parent="CostumeInputs/ScrollContainer"] @@ -14868,6 +14882,7 @@ scrollable = false [connection signal="picker_created" from="Background/ColorPickerButton" to="." method="_on_color_picker_button_picker_created"] [connection signal="value_changed" from="MaxFPS/fpsDrag" to="." method="_on_fps_drag_value_changed"] [connection signal="pressed" from="MaxFPS/confirm" to="." method="_on_confirm_pressed"] +[connection signal="toggled" from="StreamDeck/streamDeckCheck" to="." method="_on_stream_deck_check_toggled"] [connection signal="toggled" from="AntiAliasing/CheckBox" to="." method="_on_check_box_toggled"] [connection signal="toggled" from="bounceOnCostume/costumeCheck" to="." method="_on_costume_check_toggled"] [connection signal="value_changed" from="BounceForce/bounceForce" to="." method="_on_bounce_force_value_changed"]