From cd9b9f7a4854db48477d29fdcd8df77b3200c878 Mon Sep 17 00:00:00 2001 From: Tim Yuen Date: Sun, 10 Oct 2021 14:16:44 -0400 Subject: [PATCH] more or less finish up plugin, add demo, add icon --- addons/obs_websocket_gd/obs_ui.gd | 88 ++++++++- addons/obs_websocket_gd/obs_ui.tscn | 172 ++++++++++++++---- addons/obs_websocket_gd/obs_websocket.gd | 52 ++++-- examples/demo.tscn | 220 ++++++++++++++++++++++- obs_godot_icon.png | Bin 0 -> 5793 bytes obs_godot_icon.png.import | 35 ++++ project.godot | 2 +- 7 files changed, 512 insertions(+), 57 deletions(-) create mode 100644 obs_godot_icon.png create mode 100644 obs_godot_icon.png.import diff --git a/addons/obs_websocket_gd/obs_ui.gd b/addons/obs_websocket_gd/obs_ui.gd index fc89d84..490378c 100644 --- a/addons/obs_websocket_gd/obs_ui.gd +++ b/addons/obs_websocket_gd/obs_ui.gd @@ -12,15 +12,28 @@ const STOP_RECORDING: String = "Stop Recording" var obs_websocket +var scene_data: Dictionary = {} # String: ObsScene + var current_scene: String = "changeme" -onready var scenes: VBoxContainer = $VBoxContainer/HBoxContainer/Scenes -onready var sources: VBoxContainer = $VBoxContainer/HBoxContainer/Sources +enum ButtonType { NONE = 0, SCENE, SOURCE } + +onready var source_items: HBoxContainer = $VBoxContainer/SourceItems +onready var render: CheckButton = $VBoxContainer/SourceItems/Render + +onready var scenes: VBoxContainer = $VBoxContainer/HBoxContainer/Scenes/ScenesScroll/VBoxContainer +var scene_button_group := ButtonGroup.new() + +onready var sources: VBoxContainer = $VBoxContainer/HBoxContainer/Sources/SourcesScroll/VBoxContainer +var source_button_group := ButtonGroup.new() onready var connect_button: Button = $VBoxContainer/HBoxContainer/Websocket/Connect var is_connection_established := false onready var host_value: LineEdit = $VBoxContainer/HBoxContainer/Websocket/Host/Value onready var port_value: LineEdit = $VBoxContainer/HBoxContainer/Websocket/Port/Value +onready var password_value: LineEdit = $VBoxContainer/HBoxContainer/Websocket/Password/Value + +onready var refresh_data: Button = $VBoxContainer/HBoxContainer/Websocket/RefreshData onready var stream: Button = $VBoxContainer/HBoxContainer/Controls/Stream var is_streaming := false @@ -41,9 +54,14 @@ func _ready(): # Setup connection values from script host_value.text = obs_websocket.host port_value.text = obs_websocket.port + password_value.text = obs_websocket.password + + render.connect("toggled", self, "_on_source_item_toggled", [render.text]) connect_button.connect("pressed", self, "_on_connect_pressed") + refresh_data.connect("pressed", self, "_on_refresh_data_pressed") + stream.text = START_STREAMING stream.connect("pressed", self, "_on_stream_pressed") @@ -63,6 +81,7 @@ func _on_connect_pressed() -> void: obs_websocket.host = host_value.text obs_websocket.port = port_value.text + obs_websocket.password = password_value.text match is_connection_established: true: @@ -103,22 +122,79 @@ func _on_obs_updated(obs_data: Dictionary) -> void: func _on_obs_connected() -> void: obs_websocket.get_scene_list() +func _on_refresh_data_pressed() -> void: + if obs_websocket.obs_client.get_connection_status() != WebSocketClient.CONNECTION_CONNECTED: + return + obs_websocket.get_scene_list() + func _on_obs_scene_list_returned(data) -> void: - print("asdf") current_scene = data.current_scene + scene_data.clear() + for child in scenes.get_children(): child.queue_free() + for child in sources.get_children(): + child.queue_free() + + # We clear everything, so no source item will be selected + source_items.visible = false + for i in data.scenes: - var button := Button.new() - button.text = i.obs_name - scenes.call_deferred("add_child", button) + var scene_button := CheckButton.new() + scene_button.text = i.obs_name + if scene_button.text == current_scene: + scene_button.set_pressed_no_signal(true) + scene_button.group = scene_button_group + scene_button.connect("toggled", self, "_on_button_toggled_with_name", [scene_button.text, ButtonType.SCENE]) + scenes.call_deferred("add_child", scene_button) + + if i.obs_name == current_scene: + for j in i.sources: + _create_source_button(j.obs_name) + + scene_data[i.obs_name] = i + +func _on_source_item_toggled(button_pressed: bool, button_name: String) -> void: + match button_name: + "Render": + obs_websocket.send_command("SetSceneItemRender", { + "source": source_button_group.get_pressed_button().text, + "render": button_pressed + }) + _: + print("Unhandled source item toggled") + +func _on_button_toggled_with_name(button_pressed: bool, button_name: String, button_type: int) -> void: + # Buttons cannot be unpressed with a button group I guess, so just match positives + match button_type: + ButtonType.SCENE: + source_items.visible = false + obs_websocket.send_command("SetCurrentScene", {"scene-name": button_name}) + for child in sources.get_children(): + child.free() + for i in scene_data[button_name].sources: + _create_source_button(i.obs_name) + ButtonType.SOURCE: + source_items.visible = true + # I like to live dangerously + # If you remove items in OBS without refreshing data, you might null pointer? + for i in scene_data[scene_button_group.get_pressed_button().text].sources: + if i.obs_name == button_name: + render.set_pressed_no_signal(i.render) ############################################################################### # Private functions # ############################################################################### +func _create_source_button(button_name: String) -> void: + var source_button := CheckButton.new() + source_button.text = button_name + source_button.group = source_button_group + source_button.connect("toggled", self, "_on_button_toggled_with_name", [source_button.text, ButtonType.SOURCE]) + sources.call_deferred("add_child", source_button) + ############################################################################### # Public functions # ############################################################################### diff --git a/addons/obs_websocket_gd/obs_ui.tscn b/addons/obs_websocket_gd/obs_ui.tscn index 1513c3b..70479a0 100644 --- a/addons/obs_websocket_gd/obs_ui.tscn +++ b/addons/obs_websocket_gd/obs_ui.tscn @@ -18,19 +18,28 @@ margin_right = 1017.0 margin_bottom = 593.0 [node name="SourceItems" type="HBoxContainer" parent="VBoxContainer"] +visible = false margin_right = 1010.0 -margin_bottom = 82.0 +margin_bottom = 40.0 size_flags_horizontal = 3 -size_flags_vertical = 3 + +[node name="Render" type="CheckButton" parent="VBoxContainer/SourceItems"] +margin_right = 125.0 +margin_bottom = 40.0 +text = "Render" + +[node name="VSeparator" type="VSeparator" parent="VBoxContainer/SourceItems"] +margin_left = 129.0 +margin_right = 133.0 +margin_bottom = 40.0 [node name="HSeparator" type="HSeparator" parent="VBoxContainer"] -margin_top = 86.0 margin_right = 1010.0 -margin_bottom = 90.0 +margin_bottom = 4.0 mouse_filter = 2 [node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] -margin_top = 94.0 +margin_top = 8.0 margin_right = 1010.0 margin_bottom = 586.0 size_flags_horizontal = 3 @@ -38,80 +47,175 @@ size_flags_vertical = 3 size_flags_stretch_ratio = 6.0 [node name="Scenes" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] -margin_right = 249.0 -margin_bottom = 492.0 +margin_right = 243.0 +margin_bottom = 578.0 size_flags_horizontal = 3 size_flags_vertical = 3 +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/Scenes"] +margin_right = 243.0 +margin_bottom = 14.0 +text = "Scenes" +align = 1 + +[node name="ScenesScroll" type="ScrollContainer" parent="VBoxContainer/HBoxContainer/Scenes"] +margin_top = 18.0 +margin_right = 243.0 +margin_bottom = 578.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/Scenes/ScenesScroll"] +margin_right = 243.0 +margin_bottom = 560.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="VSeparator" type="VSeparator" parent="VBoxContainer/HBoxContainer"] +margin_left = 247.0 +margin_right = 251.0 +margin_bottom = 578.0 + [node name="Sources" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] -margin_left = 253.0 -margin_right = 503.0 -margin_bottom = 492.0 +margin_left = 255.0 +margin_right = 499.0 +margin_bottom = 578.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/Sources"] +margin_right = 244.0 +margin_bottom = 14.0 +text = "Sources" +align = 1 + +[node name="SourcesScroll" type="ScrollContainer" parent="VBoxContainer/HBoxContainer/Sources"] +margin_top = 18.0 +margin_right = 244.0 +margin_bottom = 578.0 size_flags_horizontal = 3 size_flags_vertical = 3 +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/Sources/SourcesScroll"] +margin_right = 244.0 +margin_bottom = 560.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="VSeparator2" type="VSeparator" parent="VBoxContainer/HBoxContainer"] +margin_left = 503.0 +margin_right = 507.0 +margin_bottom = 578.0 + [node name="Controls" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] -margin_left = 507.0 -margin_right = 756.0 -margin_bottom = 492.0 +margin_left = 511.0 +margin_right = 754.0 +margin_bottom = 578.0 size_flags_horizontal = 3 size_flags_vertical = 3 +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/Controls"] +margin_right = 243.0 +margin_bottom = 14.0 +text = "Controls" +align = 1 + [node name="Stream" type="Button" parent="VBoxContainer/HBoxContainer/Controls"] -margin_right = 249.0 -margin_bottom = 20.0 +margin_top = 18.0 +margin_right = 243.0 +margin_bottom = 38.0 text = "Start Streaming" [node name="Record" type="Button" parent="VBoxContainer/HBoxContainer/Controls"] -margin_top = 24.0 -margin_right = 249.0 -margin_bottom = 44.0 +margin_top = 42.0 +margin_right = 243.0 +margin_bottom = 62.0 text = "Start Recording" +[node name="VSeparator3" type="VSeparator" parent="VBoxContainer/HBoxContainer"] +margin_left = 758.0 +margin_right = 762.0 +margin_bottom = 578.0 + [node name="Websocket" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] -margin_left = 760.0 +margin_left = 766.0 margin_right = 1010.0 -margin_bottom = 492.0 +margin_bottom = 578.0 size_flags_horizontal = 3 size_flags_vertical = 3 +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/Websocket"] +margin_right = 244.0 +margin_bottom = 14.0 +text = "OBS Websocket" +align = 1 + [node name="Host" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/Websocket"] -margin_right = 250.0 -margin_bottom = 24.0 +margin_top = 18.0 +margin_right = 244.0 +margin_bottom = 42.0 [node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/Websocket/Host"] margin_top = 5.0 -margin_right = 123.0 +margin_right = 120.0 margin_bottom = 19.0 size_flags_horizontal = 3 text = "Host:" [node name="Value" type="LineEdit" parent="VBoxContainer/HBoxContainer/Websocket/Host"] -margin_left = 127.0 -margin_right = 250.0 +margin_left = 124.0 +margin_right = 244.0 margin_bottom = 24.0 size_flags_horizontal = 3 +text = "127.0.0.1" [node name="Port" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/Websocket"] -margin_top = 28.0 -margin_right = 250.0 -margin_bottom = 52.0 +margin_top = 46.0 +margin_right = 244.0 +margin_bottom = 70.0 [node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/Websocket/Port"] margin_top = 5.0 -margin_right = 123.0 +margin_right = 120.0 margin_bottom = 19.0 size_flags_horizontal = 3 text = "Port:" [node name="Value" type="LineEdit" parent="VBoxContainer/HBoxContainer/Websocket/Port"] -margin_left = 127.0 -margin_right = 250.0 +margin_left = 124.0 +margin_right = 244.0 +margin_bottom = 24.0 +size_flags_horizontal = 3 +text = "4444" + +[node name="Password" type="HBoxContainer" parent="VBoxContainer/HBoxContainer/Websocket"] +margin_top = 74.0 +margin_right = 244.0 +margin_bottom = 98.0 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/Websocket/Password"] +margin_top = 5.0 +margin_right = 120.0 +margin_bottom = 19.0 +size_flags_horizontal = 3 +text = "Port:" + +[node name="Value" type="LineEdit" parent="VBoxContainer/HBoxContainer/Websocket/Password"] +margin_left = 124.0 +margin_right = 244.0 margin_bottom = 24.0 size_flags_horizontal = 3 +text = "password" +secret = true [node name="Connect" type="Button" parent="VBoxContainer/HBoxContainer/Websocket"] -margin_top = 56.0 -margin_right = 250.0 -margin_bottom = 76.0 +margin_top = 102.0 +margin_right = 244.0 +margin_bottom = 122.0 text = "Connect" + +[node name="RefreshData" type="Button" parent="VBoxContainer/HBoxContainer/Websocket"] +margin_top = 126.0 +margin_right = 244.0 +margin_bottom = 146.0 +text = "Refresh Data" diff --git a/addons/obs_websocket_gd/obs_websocket.gd b/addons/obs_websocket_gd/obs_websocket.gd index 5faa9d7..9769c27 100644 --- a/addons/obs_websocket_gd/obs_websocket.gd +++ b/addons/obs_websocket_gd/obs_websocket.gd @@ -7,13 +7,28 @@ signal obs_scene_list_returned(data) class ObsObject: var obs_name: String = "changeme" + + func _to_string() -> String: + return obs_name class ObsGetSceneListResponse: var current_scene: String var scenes: Array = [] # ObsScene + + func _to_string() -> String: + return str({ + "current_scene": current_scene, + "scenes": scenes + }) class ObsScene extends ObsObject: var sources: Array = [] # ObsSceneItem + + func _to_string() -> String: + return str({ + "obs_name": obs_name, + "sources": sources + }) class ObsSceneItem extends ObsObject: var cy: float @@ -25,7 +40,7 @@ class ObsSceneItem extends ObsObject: var locked: bool var source_cx: float var source_cy: float - var obs_type: ObsSourceType + var obs_type: String var volume: float var x: float var y: float @@ -44,7 +59,7 @@ class ObsSceneItem extends ObsObject: p_locked: bool, p_source_cx: float, p_source_cy: float, - p_obs_type: ObsSourceType, + p_obs_type: String, p_volume: float, p_x: float, p_y: float, @@ -67,18 +82,24 @@ class ObsSceneItem extends ObsObject: y = p_y # parent_group_name = p_parent_group_name # group_children = p_group_children - -class ObsSourceType: - const INPUT = "input" - const FILTER = "filter" - const TRANSTIION = "transition" - const SCENE = "scene" - const UNKNOWN = "unknown" - - var current_type: String = UNKNOWN - func _init(p_type: String): - current_type = p_type + func _to_string() -> String: + return str({ + "cy": cy, + "cx": cx, + "alignment": alignment, + "obs_name": obs_name, + "id": id, + "render": render, + "muted": muted, + "locked": locked, + "source_cx": source_cx, + "source_cy": source_cy, + "obs_type": obs_type, + "volume": volume, + "x": x, + "y": y + }) const URL_PATH: String = "ws://%s:%s" @@ -91,6 +112,7 @@ var request_counter: int = -1 export var host: String = "127.0.0.1" export var port: String = "4444" +export var password: String = "password" # It's plaintext lmao, you should be changing this programmatically const PreconfiguredCommands = { "GET_SCENE_LIST": "GetSceneList" @@ -146,7 +168,7 @@ func _on_data_received() -> void: return if json_response.has("authRequired"): - var secret_combined: String = "%s%s" % ["password", json_response["salt"]] + var secret_combined: String = "%s%s" % [password, json_response["salt"]] var secret_base64 = Marshalls.raw_to_base64(secret_combined.sha256_buffer()) var auth_combined: String = "%s%s" % [secret_base64, json_response["challenge"]] var auth_base64: String = Marshalls.raw_to_base64(auth_combined.sha256_buffer()) @@ -167,6 +189,7 @@ func _on_data_received() -> void: for i in json_response["scenes"]: var obs_scene := ObsScene.new() + obs_scene.obs_name = i["name"] for j in i["sources"]: var obs_scene_item := ObsSceneItem.new( j["cy"], @@ -187,6 +210,7 @@ func _on_data_received() -> void: obs_scene.sources.append(obs_scene_item) data.scenes.append(obs_scene) emit_signal("obs_scene_list_returned", data) + waiting_for_response = false return emit_signal("obs_updated", json_response) diff --git a/examples/demo.tscn b/examples/demo.tscn index 4514dd9..1cec15f 100644 --- a/examples/demo.tscn +++ b/examples/demo.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=2 format=2] -[ext_resource path="res://addons/obs_websocket_gd/obs_websocket.tscn" type="PackedScene" id=1] +[ext_resource path="res://addons/obs_websocket_gd/obs_ui.gd" type="Script" id=1] [node name="Demo" type="CanvasLayer"] @@ -12,4 +12,220 @@ __meta__ = { "_edit_use_anchors_": false } -[node name="ObsWebsocket" parent="." instance=ExtResource( 1 )] +[node name="ObsUi" type="PanelContainer" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 +mouse_filter = 2 +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="VBoxContainer" type="VBoxContainer" parent="ObsUi"] +margin_left = 7.0 +margin_top = 7.0 +margin_right = 1017.0 +margin_bottom = 593.0 + +[node name="SourceItems" type="HBoxContainer" parent="ObsUi/VBoxContainer"] +visible = false +margin_right = 1010.0 +margin_bottom = 40.0 +size_flags_horizontal = 3 + +[node name="Render" type="CheckButton" parent="ObsUi/VBoxContainer/SourceItems"] +margin_right = 125.0 +margin_bottom = 40.0 +text = "Render" + +[node name="VSeparator" type="VSeparator" parent="ObsUi/VBoxContainer/SourceItems"] +margin_left = 129.0 +margin_right = 133.0 +margin_bottom = 40.0 + +[node name="HSeparator" type="HSeparator" parent="ObsUi/VBoxContainer"] +margin_right = 1010.0 +margin_bottom = 4.0 +mouse_filter = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="ObsUi/VBoxContainer"] +margin_top = 8.0 +margin_right = 1010.0 +margin_bottom = 586.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +size_flags_stretch_ratio = 6.0 + +[node name="Scenes" type="VBoxContainer" parent="ObsUi/VBoxContainer/HBoxContainer"] +margin_right = 243.0 +margin_bottom = 578.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Label" type="Label" parent="ObsUi/VBoxContainer/HBoxContainer/Scenes"] +margin_right = 243.0 +margin_bottom = 14.0 +text = "Scenes" +align = 1 + +[node name="ScenesScroll" type="ScrollContainer" parent="ObsUi/VBoxContainer/HBoxContainer/Scenes"] +margin_top = 18.0 +margin_right = 243.0 +margin_bottom = 578.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="VBoxContainer" type="VBoxContainer" parent="ObsUi/VBoxContainer/HBoxContainer/Scenes/ScenesScroll"] +margin_right = 243.0 +margin_bottom = 560.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="VSeparator" type="VSeparator" parent="ObsUi/VBoxContainer/HBoxContainer"] +margin_left = 247.0 +margin_right = 251.0 +margin_bottom = 578.0 + +[node name="Sources" type="VBoxContainer" parent="ObsUi/VBoxContainer/HBoxContainer"] +margin_left = 255.0 +margin_right = 499.0 +margin_bottom = 578.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Label" type="Label" parent="ObsUi/VBoxContainer/HBoxContainer/Sources"] +margin_right = 244.0 +margin_bottom = 14.0 +text = "Sources" +align = 1 + +[node name="SourcesScroll" type="ScrollContainer" parent="ObsUi/VBoxContainer/HBoxContainer/Sources"] +margin_top = 18.0 +margin_right = 244.0 +margin_bottom = 578.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="VBoxContainer" type="VBoxContainer" parent="ObsUi/VBoxContainer/HBoxContainer/Sources/SourcesScroll"] +margin_right = 244.0 +margin_bottom = 560.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="VSeparator2" type="VSeparator" parent="ObsUi/VBoxContainer/HBoxContainer"] +margin_left = 503.0 +margin_right = 507.0 +margin_bottom = 578.0 + +[node name="Controls" type="VBoxContainer" parent="ObsUi/VBoxContainer/HBoxContainer"] +margin_left = 511.0 +margin_right = 754.0 +margin_bottom = 578.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Label" type="Label" parent="ObsUi/VBoxContainer/HBoxContainer/Controls"] +margin_right = 243.0 +margin_bottom = 14.0 +text = "Controls" +align = 1 + +[node name="Stream" type="Button" parent="ObsUi/VBoxContainer/HBoxContainer/Controls"] +margin_top = 18.0 +margin_right = 243.0 +margin_bottom = 38.0 +text = "Start Streaming" + +[node name="Record" type="Button" parent="ObsUi/VBoxContainer/HBoxContainer/Controls"] +margin_top = 42.0 +margin_right = 243.0 +margin_bottom = 62.0 +text = "Start Recording" + +[node name="VSeparator3" type="VSeparator" parent="ObsUi/VBoxContainer/HBoxContainer"] +margin_left = 758.0 +margin_right = 762.0 +margin_bottom = 578.0 + +[node name="Websocket" type="VBoxContainer" parent="ObsUi/VBoxContainer/HBoxContainer"] +margin_left = 766.0 +margin_right = 1010.0 +margin_bottom = 578.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[node name="Label" type="Label" parent="ObsUi/VBoxContainer/HBoxContainer/Websocket"] +margin_right = 244.0 +margin_bottom = 14.0 +text = "OBS Websocket" +align = 1 + +[node name="Host" type="HBoxContainer" parent="ObsUi/VBoxContainer/HBoxContainer/Websocket"] +margin_top = 18.0 +margin_right = 244.0 +margin_bottom = 42.0 + +[node name="Label" type="Label" parent="ObsUi/VBoxContainer/HBoxContainer/Websocket/Host"] +margin_top = 5.0 +margin_right = 120.0 +margin_bottom = 19.0 +size_flags_horizontal = 3 +text = "Host:" + +[node name="Value" type="LineEdit" parent="ObsUi/VBoxContainer/HBoxContainer/Websocket/Host"] +margin_left = 124.0 +margin_right = 244.0 +margin_bottom = 24.0 +size_flags_horizontal = 3 +text = "127.0.0.1" + +[node name="Port" type="HBoxContainer" parent="ObsUi/VBoxContainer/HBoxContainer/Websocket"] +margin_top = 46.0 +margin_right = 244.0 +margin_bottom = 70.0 + +[node name="Label" type="Label" parent="ObsUi/VBoxContainer/HBoxContainer/Websocket/Port"] +margin_top = 5.0 +margin_right = 120.0 +margin_bottom = 19.0 +size_flags_horizontal = 3 +text = "Port:" + +[node name="Value" type="LineEdit" parent="ObsUi/VBoxContainer/HBoxContainer/Websocket/Port"] +margin_left = 124.0 +margin_right = 244.0 +margin_bottom = 24.0 +size_flags_horizontal = 3 +text = "4444" + +[node name="Password" type="HBoxContainer" parent="ObsUi/VBoxContainer/HBoxContainer/Websocket"] +margin_top = 74.0 +margin_right = 244.0 +margin_bottom = 98.0 + +[node name="Label" type="Label" parent="ObsUi/VBoxContainer/HBoxContainer/Websocket/Password"] +margin_top = 5.0 +margin_right = 120.0 +margin_bottom = 19.0 +size_flags_horizontal = 3 +text = "Port:" + +[node name="Value" type="LineEdit" parent="ObsUi/VBoxContainer/HBoxContainer/Websocket/Password"] +margin_left = 124.0 +margin_right = 244.0 +margin_bottom = 24.0 +size_flags_horizontal = 3 +text = "password" +secret = true + +[node name="Connect" type="Button" parent="ObsUi/VBoxContainer/HBoxContainer/Websocket"] +margin_top = 102.0 +margin_right = 244.0 +margin_bottom = 122.0 +text = "Connect" + +[node name="RefreshData" type="Button" parent="ObsUi/VBoxContainer/HBoxContainer/Websocket"] +margin_top = 126.0 +margin_right = 244.0 +margin_bottom = 146.0 +text = "Refresh Data" diff --git a/obs_godot_icon.png b/obs_godot_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..825b8a8a6ef3d11074d86ee47c510f08565c0ab3 GIT binary patch literal 5793 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 literal 0 HcmV?d00001 diff --git a/obs_godot_icon.png.import b/obs_godot_icon.png.import new file mode 100644 index 0000000..d6787b0 --- /dev/null +++ b/obs_godot_icon.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/obs_godot_icon.png-7cc8dea5e5c65e9732918fc9f2defcba.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://obs_godot_icon.png" +dest_files=[ "res://.import/obs_godot_icon.png-7cc8dea5e5c65e9732918fc9f2defcba.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/project.godot b/project.godot index b1e93a5..cfadb24 100644 --- a/project.godot +++ b/project.godot @@ -12,7 +12,7 @@ config_version=4 config/name="OBS Websocket GD" run/main_scene="res://examples/demo.tscn" -config/icon="res://icon.png" +config/icon="res://obs_godot_icon.png" [physics]