diff --git a/ChatMarginContainer.cs b/ChatMarginContainer.cs new file mode 100644 index 0000000..d50e5d2 --- /dev/null +++ b/ChatMarginContainer.cs @@ -0,0 +1,17 @@ +using Godot; +using System; + +public partial class ChatMarginContainer : MarginContainer +{ + public readonly string Title = "Twitch"; + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + GetParentOrNull().SetTabTitle(GetIndex(), Title); + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(double delta) + { + } +} diff --git a/ConfigMarginContainer.cs b/ConfigMarginContainer.cs new file mode 100644 index 0000000..889714e --- /dev/null +++ b/ConfigMarginContainer.cs @@ -0,0 +1,17 @@ +using Godot; +using System; + +public partial class ConfigMarginContainer : MarginContainer +{ + public readonly string Title = "Config"; + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + GetParentOrNull().SetTabTitle(GetIndex(), Title); + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(double delta) + { + } +} diff --git a/ConfigStretchContainer.cs b/ConfigStretchContainer.cs index e2d6c48..203ec5f 100644 --- a/ConfigStretchContainer.cs +++ b/ConfigStretchContainer.cs @@ -47,7 +47,7 @@ public partial class ConfigStretchContainer : VBoxContainer return StretchMode.Stretch; throw new Exception($"No {nameof(StretchMode)} buttons pressed"); } - public void OkClicked() + public void Apply() { Settings.StretchMode = GetStretchMode(); } diff --git a/Extensions.cs b/Extensions.cs index 447d52d..fb12933 100644 --- a/Extensions.cs +++ b/Extensions.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using Godot; @@ -86,4 +87,8 @@ public static class ExtensionHelper else return par.GetParentOfType(); } + public static Vector2 Union(this Vector2 vect, Vector2 other) + => new(Math.Max(vect.X, other.X), Math.Max(vect.Y, other.Y)); + public static Vector2I Union(this Vector2I vect, Vector2 other) + => new((int)Math.Max(vect.X, other.X), (int)Math.Max(vect.Y, other.Y)); } diff --git a/TwitchChatWatcher.cs b/TwitchChatWatcher.cs index ae91585..f1e7fd8 100644 --- a/TwitchChatWatcher.cs +++ b/TwitchChatWatcher.cs @@ -12,7 +12,7 @@ public partial class TwitchChatWatcher : Node { private readonly ClientWebSocket Socket = new(); public readonly ConcurrentQueue Queue = new(); - private readonly CancellationTokenSource TokenSource = new(); + private CancellationTokenSource TokenSource = new(); public CancellationToken Token => TokenSource.Token; private CommandHandler CommandHandler { get; set; } public WebSocketState State => Socket.State; @@ -22,6 +22,11 @@ public partial class TwitchChatWatcher : Node [Signal] public delegate void IncomingCommandEventHandler(Command command); + [Signal] + public delegate void SocketConnectedEventHandler(); + [Signal] + public delegate void SocketDisconnectedEventHandler(); + public string Channel { get; private set ;} // Called when the node enters the scene tree for the first time. public override void _Ready() { @@ -30,16 +35,11 @@ public partial class TwitchChatWatcher : Node CommandHandler = GetNode("/root/CommandHandler") ?? throw new Exception($"{nameof(Command)} not found"); } - private readonly ConcurrentQueue PrintQueue = new(); - private readonly ConcurrentQueue ErrorQueue = new(); // Called every frame. 'delta' is the elapsed time since the previous frame. public override void _Process(double delta) { - if (PrintQueue.TryDequeue(out string s)) - GD.Print(s); - if (ErrorQueue.TryDequeue(out string e)) - GD.PrintErr(e); + } public async Task ConnectAsync() { @@ -47,9 +47,16 @@ public partial class TwitchChatWatcher : Node if (Socket.State == WebSocketState.Open) return; await Socket.ConnectAsync(new Uri("wss://irc-ws.chat.twitch.tv:443"), Token); - _ = Task.Run(GetPacketsTask, Token); - _ = Task.Run(HandleMessages, Token); - + if (Socket.State == WebSocketState.Open) + { + _ = Task.Run(GetPacketsTask, Token); + _ = Task.Run(HandleMessages, Token); + CallDeferred("emit_signal", nameof(SocketConnected)); + } + else + { + throw new Exception("Failed to connect to Twitch"); + } } public async Task Authenticate(string user = null, string pass = null) { @@ -65,10 +72,15 @@ public partial class TwitchChatWatcher : Node } public async Task JoinChannel(string channel) { - GD.Print("Joining channel"); channel = channel.TrimStart('#'); + if (Channel is not null) + { + await SendMessageAsync(TwitchChatMessageType.PART, + parameters: new string[] {"#" + Channel}); + } await SendMessageAsync(TwitchChatMessageType.JOIN, - parameters: new string[] {"#" + channel}); + parameters: new string[] {"#" + channel}); + Channel = channel; } public async Task SendMessageAsync(string message) { @@ -109,7 +121,6 @@ public partial class TwitchChatWatcher : Node } await SendMessageAsync(message); } - private static ulong PacketCount; private async Task GetPacketsTask() { try @@ -123,37 +134,29 @@ public partial class TwitchChatWatcher : Node return; if (Socket.State != WebSocketState.Open) { - ErrorQueue.Enqueue("Socket closed"); + GD.PrintErr("Socket closed"); + CallDeferred("emit_signal", nameof(SocketDisconnected)); return; } if (res.Count == 0) { - ErrorQueue.Enqueue("Empty packet received"); + GD.PrintErr("Empty packet received"); continue; } - PacketCount++; - PrintQueue.Enqueue($"Packet count: {PacketCount}"); stringData += Encoding.UTF8.GetString(arr, 0, res.Count); //PrintQueue.Enqueue(stringData); var lines = stringData.Split("\r\n", StringSplitOptions.TrimEntries); if (!lines.Any()) continue; stringData = lines.Last(); - PrintQueue.Enqueue($"Line count: {lines.SkipLast(1).Count()}"); foreach (var line in lines.SkipLast(1)) MessageStrings.Enqueue(line); } } - catch (Exception e) - { - ErrorQueue.Enqueue(e.ToString()); - } finally { if (!Token.IsCancellationRequested) - ErrorQueue.Enqueue($"{nameof(GetPacketsTask)} exited without cancellation"); - else - PrintQueue.Enqueue($"{nameof(GetPacketsTask)} cancelled and exited"); + GD.PushError($"{nameof(GetPacketsTask)} exited without cancellation"); } } private readonly ConcurrentQueue MessageStrings = new(); @@ -167,7 +170,7 @@ public partial class TwitchChatWatcher : Node { if (string.IsNullOrWhiteSpace(message)) continue; - PrintQueue.Enqueue(message); + GD.Print(message); // if (PrintAllIncoming) // PrintQueue.Enqueue(message); var tcm = TwitchChatMessage.Parse(message); @@ -180,6 +183,7 @@ public partial class TwitchChatWatcher : Node continue; var chat = p.ChatMessage; chat = chat[com.Length..].TrimStart(); + //TODO make better CallDeferred("emit_signal", SignalName.IncomingCommand, new Command(p.DisplayName, false, p.Moderator, chat)); @@ -188,17 +192,10 @@ public partial class TwitchChatWatcher : Node await Task.Delay(50); } } - catch (Exception e) - { - ErrorQueue.Enqueue(e.ToString() + System.Environment.NewLine - + e.StackTrace); - } finally { if (!Token.IsCancellationRequested) - ErrorQueue.Enqueue($"{nameof(HandleMessages)} exited without cancellation"); - else - ErrorQueue.Enqueue($"{nameof(HandleMessages)} cancelled and exited"); + GD.PushError($"{nameof(HandleMessages)} exited without cancellation"); } } private async Task SendPong(TwitchChatMessage ping) @@ -206,6 +203,6 @@ public partial class TwitchChatWatcher : Node var pong = TwitchChatMessage.MakePong(ping); await SendMessageAsync(TwitchChatMessageType.PONG, ping.Parameters, ping.MessageTags, ping.Prefix); - PrintQueue.Enqueue("Sent Pong"); + GD.Print("Sent Pong"); } } diff --git a/game.cs b/game.cs index 4768c4a..83ea69f 100644 --- a/game.cs +++ b/game.cs @@ -6,6 +6,14 @@ using System.Linq; public partial class game : Control { + private settings_popup _SettingsPopup; + private settings_popup SettingsPopup + { get + { + _SettingsPopup ??= GetNode("%SettingsPopup"); + return _SettingsPopup; + } + } [Export] private Vector2 _CardSize = new(200, 200); public Vector2 CardSize @@ -59,7 +67,14 @@ public partial class game : Control { if (@event.IsActionPressed("OpenMenu")) { - GetNode("%SettingsPopup").Visible = true; + if (SettingsPopup.Visible) + { + SettingsPopup.ClosePopup(); + } + else + { + SettingsPopup.ShowPopup(); + } GetViewport().SetInputAsHandled(); } } diff --git a/game.tscn b/game.tscn index 43b5baf..badf216 100644 --- a/game.tscn +++ b/game.tscn @@ -94,6 +94,7 @@ item_0/id = 0 [node name="SettingsPopup" parent="." instance=ExtResource("6_e1cou")] unique_name_in_owner = true visible = false +layout_mode = 0 [node name="CardEditPopup" parent="." instance=ExtResource("6_eqvov")] unique_name_in_owner = true diff --git a/project.godot b/project.godot index 3cd1926..98ea251 100644 --- a/project.godot +++ b/project.godot @@ -23,6 +23,11 @@ Settings="*res://Settings.cs" CommandHandler="*res://CommandHandler.cs" TwitchChatWatcher="*res://TwitchChatWatcher.cs" +[display] + +window/size/viewport_width=1280 +window/size/viewport_height=720 + [dotnet] project/assembly_name="TierMakerControl" diff --git a/settings_popup.cs b/settings_popup.cs index faebb65..0ffa7c2 100644 --- a/settings_popup.cs +++ b/settings_popup.cs @@ -6,17 +6,33 @@ using System.Net.NetworkInformation; using System.Runtime.CompilerServices; using System.Threading.Tasks; -public partial class settings_popup : PopupPanel +public partial class settings_popup : PanelContainer { + private defer_manager _Deferer = null; + private defer_manager Deferer + { get + { + _Deferer ??= GetNode("/root/DeferManager"); + return _Deferer; + } + } + public string Channel => GetNode("%ChannelNameEdit").Text; [Signal] public delegate void BeforeOkEventHandler(); // Called when the node enters the scene tree for the first time. public override void _Ready() { - Transient = true; - Exclusive = true; + DisplayServer.WindowSetMinSize( + DisplayServer.WindowGetMinSize().Union(Size)); + GetNode("/root/TwitchChatWatcher") + .Connect(TwitchChatWatcher.SignalName.SocketConnected, + new Callable(this, nameof(SocketConnected)), + (uint)ConnectFlags.Deferred); + GetNode("/root/TwitchChatWatcher") + .Connect(TwitchChatWatcher.SignalName.SocketDisconnected, + new Callable(this, nameof(SocketDisconnected)), + (uint)ConnectFlags.Deferred); } - private readonly ConcurrentQueue ActionQueue = new(); // Called every frame. 'delta' is the elapsed time since the previous frame. public override void _Process(double delta) { @@ -27,25 +43,43 @@ public partial class settings_popup : PopupPanel // a?.Invoke(); // } } + public void ShowPopup() + { + Visible = true; + } + public void ClosePopup() + { + Hide(); + } public void _on_cancel_button_pressed() { - GD.Print("Cancel pressed"); - Hide(); + ClosePopup(); } public void _on_ok_button_pressed() { - GD.Print("OK pressed"); + GetNode("%ConfigStretchContainer").Apply(); + ClosePopup(); + } + public void _on_connect_button_pressed() + { var tcw = GetNode("/root/TwitchChatWatcher"); - string chName = GetNode("%ChannelNameEdit").Text; + //string chName = GetNode("%ChannelNameEdit").Text; Task.Run(tcw.ConnectAsync).ContinueWith(t => tcw.Authenticate(null, null)) .ContinueWith(t => tcw.RequestTags()) - .ContinueWith(t => tcw.JoinChannel(chName)) + //.ContinueWith(t => tcw.JoinChannel(chName)) .ContinueWith(FinishConnection); ProcessMode = ProcessModeEnum.Disabled; } + public void _on_join_channel_button_pressed() + { + var channel = Channel; + if (string.IsNullOrWhiteSpace(channel)) + return; + var tcw = GetNode("/root/TwitchChatWatcher"); + _ = Task.Run(() => tcw.JoinChannel(channel)); + } private void FinishConnection(Task t) { - GD.Print(t.Status); if (t.IsCompletedSuccessfully) { CallDeferred(nameof(SuccessfulConnection)); @@ -53,12 +87,15 @@ public partial class settings_popup : PopupPanel else { GD.PrintErr(t.Exception); - ActionQueue.Enqueue(() => ProcessMode = ProcessModeEnum.Inherit); + CallDeferred(nameof(UnlockPopup)); } } + private void UnlockPopup() + { + ProcessMode = ProcessModeEnum.Inherit; + } private void SuccessfulConnection() { - GD.Print("Running completion task"); var tcw = GetNode("/root/TwitchChatWatcher"); if (tcw.State != System.Net.WebSockets.WebSocketState.Open) throw new Exception("Websocket closed"); @@ -69,7 +106,14 @@ public partial class settings_popup : PopupPanel StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries), GetNode("%BlackListEdit").Text.Split('\n', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)); - ProcessMode = ProcessModeEnum.Inherit; - Hide(); + UnlockPopup(); + } + private void SocketConnected() + { + GetNode("%ConnectButton").Disabled = true; + } + private void SocketDisconnected() + { + GetNode("%ConnectButton").Disabled = false; } } diff --git a/settings_popup.tscn b/settings_popup.tscn index 0baa999..da47af4 100644 --- a/settings_popup.tscn +++ b/settings_popup.tscn @@ -1,118 +1,155 @@ -[gd_scene load_steps=5 format=3 uid="uid://jm7tss267q8y"] +[gd_scene load_steps=7 format=3 uid="uid://jm7tss267q8y"] [ext_resource type="Script" path="res://settings_popup.cs" id="1_blkox"] [ext_resource type="Script" path="res://ConfigStretchContainer.cs" id="2_fhn7i"] +[ext_resource type="Script" path="res://ChatMarginContainer.cs" id="2_x6hlu"] +[ext_resource type="Script" path="res://ConfigMarginContainer.cs" id="3_pguul"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jcc71"] [sub_resource type="ButtonGroup" id="ButtonGroup_4itga"] -[node name="SettingsPopup" type="PopupPanel"] -title = "Settings" -size = Vector2i(728, 523) -visible = true +[node name="SettingsPopup" type="PanelContainer"] +offset_right = 728.0 +offset_bottom = 523.0 theme_override_styles/panel = SubResource("StyleBoxFlat_jcc71") script = ExtResource("1_blkox") [node name="SettingsDivider" type="VSplitContainer" parent="."] -offset_right = 728.0 -offset_bottom = 523.0 +layout_mode = 2 [node name="SettingsPopupContainer" type="TabContainer" parent="SettingsDivider"] custom_minimum_size = Vector2(720, 480) layout_mode = 2 -[node name="ChatContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer"] +[node name="ChatMarginContainer" type="MarginContainer" parent="SettingsDivider/SettingsPopupContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 5 +theme_override_constants/margin_top = 5 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_bottom = 5 +script = ExtResource("2_x6hlu") + +[node name="ChatContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer"] layout_mode = 2 -[node name="TopBoxContainer" type="GridContainer" parent="SettingsDivider/SettingsPopupContainer/ChatContainer"] +[node name="TopBoxContainer" type="GridContainer" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer"] layout_mode = 2 columns = 2 -[node name="ChannelNameLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/TopBoxContainer"] +[node name="ChannelNameLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/TopBoxContainer"] layout_mode = 2 text = "Channel Name" -[node name="ChannelNameEdit" type="LineEdit" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/TopBoxContainer"] +[node name="ChannelNameEdit" type="LineEdit" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/TopBoxContainer"] unique_name_in_owner = true custom_minimum_size = Vector2(500, 0) layout_mode = 2 -[node name="CommandLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/TopBoxContainer"] +[node name="CommandLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/TopBoxContainer"] layout_mode = 2 -text = "Command" +text = "Trigger" -[node name="CommandEdit" type="LineEdit" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/TopBoxContainer"] +[node name="CommandEdit" type="LineEdit" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/TopBoxContainer"] unique_name_in_owner = true custom_minimum_size = Vector2(500, 0) layout_mode = 2 -[node name="CheckBoxModerator" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ChatContainer"] +[node name="CheckBoxModerator" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer"] unique_name_in_owner = true layout_mode = 2 text = "Allow moderators" -[node name="UserListContainer" type="HBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ChatContainer"] +[node name="UserListContainer" type="HBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer"] layout_mode = 2 size_flags_vertical = 3 -[node name="WhiteListContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/UserListContainer"] +[node name="WhiteListContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/UserListContainer"] layout_mode = 2 size_flags_horizontal = 3 -[node name="WhiteListLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/UserListContainer/WhiteListContainer"] +[node name="WhiteListLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/UserListContainer/WhiteListContainer"] layout_mode = 2 text = "Whitelist" -[node name="WhiteListEdit" type="TextEdit" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/UserListContainer/WhiteListContainer"] +[node name="WhiteListEdit" type="TextEdit" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/UserListContainer/WhiteListContainer"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 -[node name="BlackListContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/UserListContainer"] +[node name="BlackListContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/UserListContainer"] layout_mode = 2 size_flags_horizontal = 3 -[node name="BlackListLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/UserListContainer/BlackListContainer"] +[node name="BlackListLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/UserListContainer/BlackListContainer"] layout_mode = 2 text = "Blacklist " -[node name="BlackListEdit" type="TextEdit" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/UserListContainer/BlackListContainer"] +[node name="BlackListEdit" type="TextEdit" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/UserListContainer/BlackListContainer"] unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 -[node name="ConfigContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer"] +[node name="ConnectButtonMarginContainer" type="MarginContainer" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer"] +layout_mode = 2 +size_flags_horizontal = 8 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 5 + +[node name="HBoxContainer" type="HBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/ConnectButtonMarginContainer"] +layout_mode = 2 +theme_override_constants/separation = 6 + +[node name="JoinChannelButton" type="Button" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/ConnectButtonMarginContainer/HBoxContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(125, 0) +layout_mode = 2 +size_flags_horizontal = 8 +text = "Join Channel" + +[node name="ConnectButton" type="Button" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/ConnectButtonMarginContainer/HBoxContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(125, 0) +layout_mode = 2 +size_flags_horizontal = 8 +text = "Connect" + +[node name="ConfigMarginContainer" type="MarginContainer" parent="SettingsDivider/SettingsPopupContainer"] visible = false layout_mode = 2 +script = ExtResource("3_pguul") -[node name="ConfigStretchContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ConfigContainer"] +[node name="ConfigContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer"] +layout_mode = 2 + +[node name="ConfigStretchContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer"] +unique_name_in_owner = true layout_mode = 2 size_flags_vertical = 3 alignment = 1 script = ExtResource("2_fhn7i") -[node name="ConfigStretchLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ConfigContainer/ConfigStretchContainer"] +[node name="ConfigStretchLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer/ConfigStretchContainer"] layout_mode = 2 text = " Default Stretch Mode" -[node name="ConfigStretchFitButton" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ConfigContainer/ConfigStretchContainer"] +[node name="ConfigStretchFitButton" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer/ConfigStretchContainer"] unique_name_in_owner = true layout_mode = 2 button_pressed = true button_group = SubResource("ButtonGroup_4itga") text = "Fit" -[node name="ConfigStretchStretchButton" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ConfigContainer/ConfigStretchContainer"] +[node name="ConfigStretchStretchButton" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer/ConfigStretchContainer"] unique_name_in_owner = true layout_mode = 2 button_group = SubResource("ButtonGroup_4itga") text = "Stretch" -[node name="ConfigStretchCropButton" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ConfigContainer/ConfigStretchContainer"] +[node name="ConfigStretchCropButton" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer/ConfigStretchContainer"] unique_name_in_owner = true layout_mode = 2 button_group = SubResource("ButtonGroup_4itga") @@ -136,6 +173,8 @@ layout_mode = 2 size_flags_horizontal = 8 text = "OK" -[connection signal="BeforeOk" from="." to="SettingsDivider/SettingsPopupContainer/ConfigContainer/ConfigStretchContainer" method="OkClicked"] +[connection signal="BeforeOk" from="." to="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer/ConfigStretchContainer" method="OkClicked"] +[connection signal="pressed" from="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/ConnectButtonMarginContainer/HBoxContainer/JoinChannelButton" to="." method="_on_join_channel_button_pressed"] +[connection signal="pressed" from="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/ConnectButtonMarginContainer/HBoxContainer/ConnectButton" to="." method="_on_connect_button_pressed"] [connection signal="pressed" from="SettingsDivider/ButtonContainer/CancelButton" to="." method="_on_cancel_button_pressed"] [connection signal="pressed" from="SettingsDivider/ButtonContainer/OkButton" to="." method="_on_ok_button_pressed"]