diff --git a/CardCreateImageBox.cs b/CardCreateImageBox.cs new file mode 100644 index 0000000..314e6a5 --- /dev/null +++ b/CardCreateImageBox.cs @@ -0,0 +1,25 @@ +using Godot; +using System; + +public partial class CardCreateImageBox : TextureRect +{ + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(double delta) + { + } + public override void _GuiInput(InputEvent @event) + { + if (@event is InputEventMouseButton iemb) + { + if (iemb.Pressed && iemb.ButtonIndex == MouseButton.Left) + { + GetNode("%CardImagePicker").Show(); + } + } + } +} diff --git a/CardCreateMarginContainer.cs b/CardCreateMarginContainer.cs new file mode 100644 index 0000000..932dd38 --- /dev/null +++ b/CardCreateMarginContainer.cs @@ -0,0 +1,102 @@ + using Godot; +using System; + +public partial class CardCreateMarginContainer : MarginContainer +{ + public readonly string Title = "Card"; + public string CardTitle + { + get => GetNode("%TitleEdit").Text; + set => GetNode("%TitleEdit").Text = value; + } + public void SetStretchMode(StretchMode stretchMode) + { + switch (stretchMode) + { + case StretchMode.Unspecified: + case StretchMode.Fit: + default: + GetNode("%StretchModeFitButton").ButtonPressed = true; + break; + case StretchMode.Stretch: + GetNode("%StretchModeStretchButton").ButtonPressed = true; + break; + case StretchMode.Crop: + GetNode("%StretchModeCropButton").ButtonPressed = true; + break; + } + } + public StretchMode GetStretchMode() + { + if (GetNode("%StretchModeFitButton").ButtonPressed) + return StretchMode.Fit; + else if (GetNode("%StretchModeStretchButton").ButtonPressed) + return StretchMode.Stretch; + else if (GetNode("%StretchModeCropButton").ButtonPressed) + return StretchMode.Crop; + return StretchMode.Unspecified; + } + private void StetchModeChanged(BaseButton button) + { + var ci = GetNode("%CardCreateImageBox"); + switch (GetStretchMode()) + { + case StretchMode.Stretch: + ci.ExpandMode = TextureRect.ExpandModeEnum.IgnoreSize; + ci.StretchMode = TextureRect.StretchModeEnum.Scale; + break; + case StretchMode.Crop: + ci.ExpandMode = TextureRect.ExpandModeEnum.IgnoreSize; + ci.StretchMode = TextureRect.StretchModeEnum.KeepAspectCovered; + break; + case StretchMode.Unspecified: + case StretchMode.Fit: + default: + ci.ExpandMode = TextureRect.ExpandModeEnum.IgnoreSize; + ci.StretchMode = TextureRect.StretchModeEnum.KeepAspectCentered; + break; + } + } + public Image Image + { + get => GetNode("%CardCreateImageBox").Texture?.GetImage(); + set => GetNode("%CardCreateImageBox").Texture + = ImageTexture.CreateFromImage(value); + } + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + (GetParent() as TabContainer)?.SetTabTitle(GetIndex(), Title); + GetNode("%StretchModeFitButton").ButtonGroup.Pressed + += StetchModeChanged; + GetNode("%TitleEdit").TextSubmitted += + (s) => GetNode("%CreateMenuOkButton") + .EmitSignal(Button.SignalName.Pressed); + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(double delta) + { + } + public void ClearMenu() + { + GetNode("%CardCreateImageBox").Texture = new Texture2D(); + CardTitle = ""; + SetStretchMode(StretchMode.Unspecified); + } + public void SendCardToGame() + { + var c = card.MakeCard(GetTree()); + if (Image is Image im) + c.SetImage(ImageTexture.CreateFromImage(im)); + c.SetStretchMode(GetStretchMode()); + c.CardName = CardTitle; + this.GetParentOfType().AddUnassignedCard(c); + } + public void FileSelected(string path) + { + Image image = new(); + image.Load(path); + Image = image; + } +} diff --git a/CardEditImageBox.cs b/CardEditImageBox.cs index a43bdd8..96c2951 100644 --- a/CardEditImageBox.cs +++ b/CardEditImageBox.cs @@ -18,13 +18,7 @@ public partial class CardEditImageBox : TextureRect { if (iemb.Pressed && iemb.ButtonIndex == MouseButton.Left) { - // bool inControl = _HasPoint(iemb.Position); - // GD.Print(inControl); - // if (iemb.Position.X >= 0 && iemb.Position.X <= Size.X - // && iemb.Position.Y >= 0 && iemb.Position.Y <= Size.Y) - // if (inControl) - GetNode("%CardImagePicker").Show(); - + GetNode("%CardImagePicker").Show(); } } } diff --git a/CommandHandler.cs b/CommandHandler.cs index de04e50..f0b8b86 100644 --- a/CommandHandler.cs +++ b/CommandHandler.cs @@ -34,6 +34,8 @@ public partial class CommandHandler : Node // Called when the node enters the scene tree for the first time. public override void _Ready() { + //force initialization of Deferer in main thread + _ = Deferer; Settings = GetNode("/root/Settings"); Game = GetNode("/root/Game"); GetNode("/root/TwitchChatWatcher").IncomingCommand @@ -51,6 +53,7 @@ public partial class CommandHandler : Node private void IncomingCommand(Command command) { + GD.Print(command.GetArgs().Remaining()); if (!Settings.IsUserAuthorized(command.User, command.IsStreamer, command.IsModerator)) return; @@ -167,7 +170,6 @@ public partial class CommandHandler : Node var rowId = args.Pop(); var colorStr = args.Pop(); var color = Color.FromString(colorStr, new Color(0, 0, 0, 0)); - GD.Print($"Recoloring row to {color}"); if (color.IsEqualApprox(new Color(0, 0, 0, 0))) throw new Exception($"invalid color {colorStr}"); Game.RecolorRow(rowId, color); @@ -195,7 +197,6 @@ public partial class CommandHandler : Node _ => throw new Exception($"Unrecognized {nameof(StretchMode)}"), }; } - GD.Print($"Stretch mode: {mode}"); var uri = new Uri(url); GD.Print("Starting image download"); var resp = await Client.GetAsync(uri); diff --git a/DeleteCardButton.cs b/DeleteCardButton.cs new file mode 100644 index 0000000..8351aa8 --- /dev/null +++ b/DeleteCardButton.cs @@ -0,0 +1,19 @@ +using Godot; +using System; + +public partial class DeleteCardButton : Button +{ + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(double delta) + { + } + private void EnableToggled(bool newState) + { + Disabled = !newState; + } +} diff --git a/Extensions.cs b/Extensions.cs index 77e7d77..0228a8b 100644 --- a/Extensions.cs +++ b/Extensions.cs @@ -57,12 +57,14 @@ public static class ExtensionHelper } public static string GetUnusedRowId(this SceneTree tree) { - var ids = tree.GetNodesInGroup("RowGroup").OfType().Select(r => r.RowId).ToArray(); + var ids = tree.GetNodesInGroup("RowGroup").OfType().Select(r => r.RowId) + .ToList(); int i = 1; while (true) { - if (!ids.Contains(i.ToString())) - return i.ToString(); + var s = i.ToString(); + if (!ids.Contains(s)) + return s; i++; } } diff --git a/RowCardContainer.cs b/RowCardContainer.cs index a990985..8deab49 100644 --- a/RowCardContainer.cs +++ b/RowCardContainer.cs @@ -14,7 +14,7 @@ public partial class RowCardContainer : HFlowContainer } public override bool _CanDropData(Vector2 atPosition, Variant data) { - return data.As() is not null; + return data.Obj is card; } public override void _DropData(Vector2 atPosition, Variant data) { diff --git a/RowCreateMarginContainer.cs b/RowCreateMarginContainer.cs new file mode 100644 index 0000000..a61b148 --- /dev/null +++ b/RowCreateMarginContainer.cs @@ -0,0 +1,32 @@ +using Godot; +using System; + +public partial class RowCreateMarginContainer : MarginContainer +{ + [Export] + public Color DefaultColor = new(0, 0, 0, 1); + public readonly string Title = "Row"; + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + (GetParent() as TabContainer).SetTabTitle(GetIndex(), Title); + ClearMenu(); + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(double delta) + { + } + public void SendRowToGame() + { + var r = row.MakeRow(GetTree()); + r.RowColor = GetNode("%RowCreateColorPickerButton").Color; + r.RowText = GetNode("%RowTextEdit").Text; + this.GetParentOfType().CallDeferred("AddRow", r, -1); + } + public void ClearMenu() + { + GetNode("%RowCreateColorPickerButton").Color = DefaultColor; + GetNode("%RowTextEdit").Text = ""; + } +} diff --git a/RowDeleteButton.cs b/RowDeleteButton.cs new file mode 100644 index 0000000..d7a6a67 --- /dev/null +++ b/RowDeleteButton.cs @@ -0,0 +1,20 @@ +using Godot; +using System; + +public partial class RowDeleteButton : Button +{ + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(double delta) + { + } + private void ToggleEnable(bool newState) + { + Disabled = !newState; + } +} diff --git a/Settings.cs b/Settings.cs index 5ca4441..225dc9c 100644 --- a/Settings.cs +++ b/Settings.cs @@ -9,7 +9,7 @@ public partial class Settings : Node [Export] public bool AllowModerators { get; set; } [Export] - public string Command { get; set; } + public string Trigger { get; set; } public List UserWhitelist { get; } = new(); public List UserBlacklist { get; } = new(); public Vector2 CardSize { get; private set; } diff --git a/TwitchChatWatcher.cs b/TwitchChatWatcher.cs index e7b24da..41632bb 100644 --- a/TwitchChatWatcher.cs +++ b/TwitchChatWatcher.cs @@ -178,13 +178,13 @@ public partial class TwitchChatWatcher : Node _ = Task.Run(() => SendPong(tcm), Token); else if (tcm is Privmsg p) { - var com = Settings.Command; - if (string.IsNullOrWhiteSpace(com)) + var trig = Settings.Trigger; + if (string.IsNullOrWhiteSpace(trig)) break; - if (!p.ChatMessage.StartsWith(com)) + if (!p.ChatMessage.StartsWith(trig)) continue; var chat = p.ChatMessage; - chat = chat[com.Length..].TrimStart(); + chat = chat[trig.Length..].TrimStart(); //TODO make better CallDeferred("emit_signal", SignalName.IncomingCommand, new Command(p.DisplayName, diff --git a/card.cs b/card.cs index d0fea95..5367310 100644 --- a/card.cs +++ b/card.cs @@ -124,7 +124,6 @@ public partial class card : Panel } public override Variant _GetDragData(Vector2 atPosition) { - GD.Print($"starting to drag {CardId}"); var prev = card_preview.MakePreview(this); var prev_root = new Control(); prev_root.AddChild(prev); diff --git a/card_edit_popup.tscn b/card_edit_popup.tscn index 3246fa8..ab1a760 100644 --- a/card_edit_popup.tscn +++ b/card_edit_popup.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=6 format=3 uid="uid://dxvues6b3g2tn"] +[gd_scene load_steps=7 format=3 uid="uid://dxvues6b3g2tn"] [ext_resource type="Script" path="res://card_edit_popup.cs" id="1_xxurr"] [ext_resource type="Script" path="res://CardEditImageBox.cs" id="2_flth7"] +[ext_resource type="Script" path="res://DeleteCardButton.cs" id="3_0btkn"] [ext_resource type="PackedScene" uid="uid://bhlqt64wrhx83" path="res://card_image_picker.tscn" id="3_4k21m"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_nx8uj"] @@ -88,12 +89,22 @@ layout_mode = 2 button_group = SubResource("ButtonGroup_t74v5") text = "Crop" -[node name="DeleteCardButton" type="Button" parent="CardEditContainer"] +[node name="DeleteCardHsplit" type="HSplitContainer" parent="CardEditContainer"] +layout_mode = 2 +size_flags_horizontal = 8 +dragger_visibility = 1 + +[node name="DeleteCardEnable" type="CheckBox" parent="CardEditContainer/DeleteCardHsplit"] +layout_mode = 2 + +[node name="DeleteCardButton" type="Button" parent="CardEditContainer/DeleteCardHsplit"] custom_minimum_size = Vector2(100, 0) layout_mode = 2 size_flags_horizontal = 8 size_flags_vertical = 8 +disabled = true text = "DELETE" +script = ExtResource("3_0btkn") [node name="CardImagePicker" parent="." instance=ExtResource("3_4k21m")] unique_name_in_owner = true @@ -101,5 +112,6 @@ unique_name_in_owner = true [connection signal="canceled" from="." to="." method="CancelClicked"] [connection signal="confirmed" from="." to="." method="OkClicked"] [connection signal="visibility_changed" from="." to="." method="OnVisibilityChange"] -[connection signal="pressed" from="CardEditContainer/DeleteCardButton" to="." method="DeleteCard"] +[connection signal="toggled" from="CardEditContainer/DeleteCardHsplit/DeleteCardEnable" to="CardEditContainer/DeleteCardHsplit/DeleteCardButton" method="EnableToggled"] +[connection signal="pressed" from="CardEditContainer/DeleteCardHsplit/DeleteCardButton" to="." method="DeleteCard"] [connection signal="file_selected" from="CardImagePicker" to="." method="FileSelected"] diff --git a/card_image_picker.tscn b/card_image_picker.tscn index cbed41f..6291526 100644 --- a/card_image_picker.tscn +++ b/card_image_picker.tscn @@ -1,6 +1,4 @@ -[gd_scene load_steps=2 format=3 uid="uid://bhlqt64wrhx83"] - -[ext_resource type="Script" path="res://CardImagePicker.cs" id="1_j0c8l"] +[gd_scene format=3 uid="uid://bhlqt64wrhx83"] [node name="CardImagePicker" type="FileDialog"] title = "Choose Picture" @@ -12,4 +10,3 @@ file_mode = 0 access = 2 filters = PackedStringArray("*.png, *.jpg, *.jpeg, *.webp, *.svg; Supported Images") use_native_dialog = true -script = ExtResource("1_j0c8l") diff --git a/card_preview.cs b/card_preview.cs index 30af9ac..6055d2e 100644 --- a/card_preview.cs +++ b/card_preview.cs @@ -55,7 +55,6 @@ public partial class card_preview : PanelContainer { PropogateCardId(); PropogateCardName(); - GD.Print(Size); } // Called every frame. 'delta' is the elapsed time since the previous frame. diff --git a/create_menu_popup.cs b/create_menu_popup.cs new file mode 100644 index 0000000..e4668a6 --- /dev/null +++ b/create_menu_popup.cs @@ -0,0 +1,79 @@ +using Godot; +using System; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Linq.Expressions; + +public partial class create_menu_popup : PanelContainer +{ + [Signal] + public delegate void ClearMenuEventHandler(); + private CardCreateMarginContainer _CardContainer; + public CardCreateMarginContainer CardContainer + { get + { + _CardContainer ??= GetNode("%CardCreateMarginContainer"); + return _CardContainer; + } + } + private RowCreateMarginContainer _RowContainer; + public RowCreateMarginContainer RowContainer + { get + { + _RowContainer ??= GetNode("%RowCreateMarginContainer"); + return _RowContainer; + } + } + // Called when the node enters the scene tree for the first time. + public override void _Ready() + { + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(double delta) + { + } + + public void ShowPopup() + { + this.GetParentOfType().MenuOpenDisableInteraction(); + Show(); + } + public void ClosePopup() + { + Hide(); + EmitSignal(SignalName.ClearMenu); + this.GetParentOfType().MenuClosedEnableInteraction(); + } + public void OkPressed() + { + var current = GetNode("%CreateTabContainer").CurrentTab; + if (current == 0) + { + CardContainer.SendCardToGame(); + ClosePopup(); + } + else if (current == 1) + { + RowContainer.SendRowToGame(); + ClosePopup(); + } + else + { + throw new Exception("No create container visible"); + } + } + public void CancelPressed() + { + ClosePopup(); + } + private void OnVisibilityChange(bool visibility) + { + // EmitSignal(SignalName.Clear); + var tabs = GetNode("%CreateTabContainer"); + if (tabs.SelectNextAvailable()) + tabs.SelectPreviousAvailable(); + if (tabs.SelectPreviousAvailable()) + tabs.SelectNextAvailable(); + } +} diff --git a/create_menu_popup.tscn b/create_menu_popup.tscn new file mode 100644 index 0000000..978249f --- /dev/null +++ b/create_menu_popup.tscn @@ -0,0 +1,155 @@ +[gd_scene load_steps=9 format=3 uid="uid://kyaqu004qlcq"] + +[ext_resource type="Script" path="res://create_menu_popup.cs" id="1_b3hbh"] +[ext_resource type="StyleBox" uid="uid://cota68polt1iy" path="res://SettingsOverlayStyleBox.tres" id="1_tgffv"] +[ext_resource type="Script" path="res://CardCreateMarginContainer.cs" id="2_ak8l2"] +[ext_resource type="Script" path="res://CardCreateImageBox.cs" id="4_jjllr"] +[ext_resource type="Script" path="res://RowCreateMarginContainer.cs" id="4_ro4l1"] +[ext_resource type="PackedScene" uid="uid://bhlqt64wrhx83" path="res://card_image_picker.tscn" id="5_mnbvn"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_p58nf"] + +[sub_resource type="ButtonGroup" id="ButtonGroup_54l0c"] + +[node name="CreateMenuPopup" type="PanelContainer"] +clip_contents = true +offset_right = 40.0 +offset_bottom = 40.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_styles/panel = ExtResource("1_tgffv") +script = ExtResource("1_b3hbh") + +[node name="CreateMarginContainer" type="MarginContainer" parent="."] +layout_mode = 2 +theme_override_constants/margin_left = 8 +theme_override_constants/margin_top = 8 +theme_override_constants/margin_right = 8 +theme_override_constants/margin_bottom = 8 + +[node name="TabSplitContainer" type="VSplitContainer" parent="CreateMarginContainer"] +layout_mode = 2 + +[node name="CreateTabContainer" type="TabContainer" parent="CreateMarginContainer/TabSplitContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_vertical = 3 + +[node name="CardCreateMarginContainer" type="MarginContainer" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer"] +unique_name_in_owner = true +layout_mode = 2 +theme_override_constants/margin_left = 10 +theme_override_constants/margin_top = 6 +theme_override_constants/margin_right = 10 +theme_override_constants/margin_bottom = 6 +script = ExtResource("2_ak8l2") + +[node name="CardEditContainer" type="VBoxContainer" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer"] +layout_mode = 2 + +[node name="TitleContainer" type="HBoxContainer" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer"] +layout_mode = 2 + +[node name="TitleLabel" type="Label" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer/TitleContainer"] +layout_mode = 2 +text = "Text" + +[node name="TitleEdit" type="LineEdit" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer/TitleContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="CardDetailsContainer" type="HSplitContainer" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer"] +layout_mode = 2 +split_offset = 6 +dragger_visibility = 1 + +[node name="CardImageSelectContainer" type="PanelContainer" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer/CardDetailsContainer"] +clip_contents = true +layout_mode = 2 +size_flags_horizontal = 0 +size_flags_vertical = 0 +mouse_filter = 1 +theme_override_styles/panel = SubResource("StyleBoxFlat_p58nf") + +[node name="CardCreateImageBox" type="TextureRect" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer/CardDetailsContainer/CardImageSelectContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(200, 200) +layout_mode = 2 +expand_mode = 1 +stretch_mode = 5 +script = ExtResource("4_jjllr") + +[node name="CardImagePicker" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer/CardDetailsContainer/CardImageSelectContainer/CardCreateImageBox" instance=ExtResource("5_mnbvn")] +unique_name_in_owner = true + +[node name="ImageStretchButtonsContainer" type="VBoxContainer" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer/CardDetailsContainer"] +layout_mode = 2 +alignment = 1 + +[node name="StretchModeLabel" type="Label" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer/CardDetailsContainer/ImageStretchButtonsContainer"] +layout_mode = 2 +text = " Stretch Mode" + +[node name="StretchModeFitButton" type="CheckBox" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer/CardDetailsContainer/ImageStretchButtonsContainer"] +unique_name_in_owner = true +layout_mode = 2 +button_pressed = true +button_group = SubResource("ButtonGroup_54l0c") +text = "Fit" + +[node name="StretchModeStretchButton" type="CheckBox" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer/CardDetailsContainer/ImageStretchButtonsContainer"] +unique_name_in_owner = true +layout_mode = 2 +button_group = SubResource("ButtonGroup_54l0c") +text = "Stretch" + +[node name="StretchModeCropButton" type="CheckBox" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer/CardDetailsContainer/ImageStretchButtonsContainer"] +unique_name_in_owner = true +layout_mode = 2 +button_group = SubResource("ButtonGroup_54l0c") +text = "Crop" + +[node name="RowCreateMarginContainer" type="MarginContainer" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer"] +unique_name_in_owner = true +visible = false +layout_mode = 2 +script = ExtResource("4_ro4l1") + +[node name="RowEditVbox" type="HSplitContainer" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/RowCreateMarginContainer"] +layout_mode = 2 + +[node name="RowCreateColorPickerButton" type="ColorPickerButton" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/RowCreateMarginContainer/RowEditVbox"] +unique_name_in_owner = true +custom_minimum_size = Vector2(200, 200) +layout_mode = 2 +size_flags_horizontal = 0 +size_flags_vertical = 0 +edit_alpha = false + +[node name="RowTextEdit" type="TextEdit" parent="CreateMarginContainer/TabSplitContainer/CreateTabContainer/RowCreateMarginContainer/RowEditVbox"] +unique_name_in_owner = true +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 + +[node name="CreateMenuButtonContainer" type="HBoxContainer" parent="CreateMarginContainer/TabSplitContainer"] +layout_mode = 2 +alignment = 2 + +[node name="CreateMenuCancelButton" type="Button" parent="CreateMarginContainer/TabSplitContainer/CreateMenuButtonContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(100, 0) +layout_mode = 2 +size_flags_horizontal = 8 +text = "Cancel" + +[node name="CreateMenuOkButton" type="Button" parent="CreateMarginContainer/TabSplitContainer/CreateMenuButtonContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(100, 0) +layout_mode = 2 +size_flags_horizontal = 8 +text = "OK" + +[connection signal="file_selected" from="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer/CardEditContainer/CardDetailsContainer/CardImageSelectContainer/CardCreateImageBox/CardImagePicker" to="CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer" method="FileSelected"] +[connection signal="pressed" from="CreateMarginContainer/TabSplitContainer/CreateMenuButtonContainer/CreateMenuCancelButton" to="." method="CancelPressed"] +[connection signal="pressed" from="CreateMarginContainer/TabSplitContainer/CreateMenuButtonContainer/CreateMenuOkButton" to="." method="OkPressed"] diff --git a/game.cs b/game.cs index 09c88cd..735d313 100644 --- a/game.cs +++ b/game.cs @@ -3,6 +3,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Threading.Tasks; @@ -16,6 +17,14 @@ public partial class game : Control return _SettingsPopup; } } + private create_menu_popup _CreateMenuPopup; + private create_menu_popup CreateMenuPopup + { get + { + _CreateMenuPopup ??= GetNode("%CreateMenuPopup"); + return _CreateMenuPopup; + } + } [Export] private Vector2 _CardSize = new(200, 200); public Vector2 CardSize @@ -77,10 +86,24 @@ public partial class game : Control } else { + CreateMenuPopup.ClosePopup(); SettingsPopup.ShowPopup(); } GetViewport().SetInputAsHandled(); } + else if (@event.IsActionPressed("CreationMenu")) + { + if (CreateMenuPopup.Visible) + { + CreateMenuPopup.ClosePopup(); + } + else + { + SettingsPopup.ClosePopup(); + CreateMenuPopup.ShowPopup(); + } + GetViewport().SetInputAsHandled(); + } } public void Clear() { @@ -109,6 +132,7 @@ public partial class game : Control var node = GetNode("%RowContainer"); node.AddChild(row); node.MoveChild(row, index); + PropogateCardSize(); } public void RemoveRow(string id) { @@ -175,17 +199,25 @@ public partial class game : Control } public void ImportGame(string filename) { - GD.Print($"Importing from {filename}"); - Serializer.LoadFromSerial(this, - File.ReadAllText(filename) + using var reader = new StreamReader( + new DeflateStream( + new FileStream(filename, FileMode.Open), + CompressionMode.Decompress + ) ); + var s = reader.ReadToEnd(); + Serializer.LoadFromSerial(this, s); } public void ExportGame(string filename, ExportSettings es) { - GD.Print($"Exporting to {filename}"); - File.WriteAllText(filename, - Serializer.CreateGameJson(this, es) + using var writer = new StreamWriter( + new DeflateStream( + new FileStream(filename, FileMode.OpenOrCreate), + CompressionLevel.Optimal + ) ); + var json = Serializer.CreateGameJson(this, es); + writer.Write(json); } #region Commands public void MoveCard(string cardId, string targetRowId, int? toIndex = null) @@ -244,8 +276,7 @@ public partial class game : Control } public void CreateRow(Color? color = null, string title = null) { - var scn = GD.Load("res://row.tscn"); - var r = scn.Instantiate() as row; + var r = row.MakeRow(GetTree()); if (!string.IsNullOrWhiteSpace(title)) r.RowText = title; if (color is Color color1) diff --git a/game.tscn b/game.tscn index 6a9eb4b..e61dbf7 100644 --- a/game.tscn +++ b/game.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=9 format=3 uid="uid://ck0t4k3guvmfm"] +[gd_scene load_steps=10 format=3 uid="uid://ck0t4k3guvmfm"] [ext_resource type="PackedScene" uid="uid://b7pebyti48f7b" path="res://row.tscn" id="1_numg7"] [ext_resource type="Script" path="res://game.cs" id="1_vl33u"] @@ -8,6 +8,7 @@ [ext_resource type="PackedScene" uid="uid://jm7tss267q8y" path="res://settings_popup.tscn" id="6_e1cou"] [ext_resource type="PackedScene" uid="uid://dxvues6b3g2tn" path="res://card_edit_popup.tscn" id="6_eqvov"] [ext_resource type="PackedScene" uid="uid://dwtxrx5xtewur" path="res://row_edit_popup.tscn" id="7_nyiqt"] +[ext_resource type="PackedScene" uid="uid://kyaqu004qlcq" path="res://create_menu_popup.tscn" id="8_f2hb2"] [node name="Game" type="Control"] layout_mode = 3 @@ -104,9 +105,16 @@ visible = false layout_mode = 0 theme_override_styles/panel = ExtResource("6_8am6d") +[node name="CreateMenuPopup" parent="." instance=ExtResource("8_f2hb2")] +unique_name_in_owner = true +visible = false +layout_mode = 0 + [node name="CardEditPopup" parent="." instance=ExtResource("6_eqvov")] unique_name_in_owner = true visible = false [connection signal="ExportSelected" from="SettingsPopup" to="." method="ExportGame"] [connection signal="ImportSelected" from="SettingsPopup" to="." method="ImportGame"] +[connection signal="ClearMenu" from="CreateMenuPopup" to="CreateMenuPopup/CreateMarginContainer/TabSplitContainer/CreateTabContainer/CardCreateMarginContainer" method="ClearMenu"] +[connection signal="ClearMenu" from="CreateMenuPopup" to="CreateMenuPopup/CreateMarginContainer/TabSplitContainer/CreateTabContainer/RowCreateMarginContainer" method="ClearMenu"] diff --git a/project.godot b/project.godot index 98ea251..b39feae 100644 --- a/project.godot +++ b/project.godot @@ -50,3 +50,9 @@ LocationMenu={ , Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":2,"position":Vector2(193, 8),"global_position":Vector2(197, 49),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null) ] } +CreationMenu={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194333,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":4,"position":Vector2(159, 18),"global_position":Vector2(163, 59),"factor":1.0,"button_index":3,"canceled":false,"pressed":true,"double_click":false,"script":null) +] +} diff --git a/row.cs b/row.cs index 714f1eb..ab02562 100644 --- a/row.cs +++ b/row.cs @@ -100,7 +100,6 @@ public partial class row : Control } public void DropCardOn(Vector2 atPosition, Variant data) { - GD.Print($"Dropping at {atPosition}"); card c = data.As() ?? throw new Exception("invalid drag data"); var g = this.GetParentOfType() @@ -131,7 +130,7 @@ public partial class row : Control } public override bool _CanDropData(Vector2 atPosition, Variant data) { - return data.As() is not null; + return data.Obj is row; } public override void _DropData(Vector2 atPosition, Variant data) { diff --git a/row_edit_popup.cs b/row_edit_popup.cs index 5e57011..43b710b 100644 --- a/row_edit_popup.cs +++ b/row_edit_popup.cs @@ -39,10 +39,15 @@ public partial class row_edit_popup : PanelContainer } public void Reset() { + Hide(); GetNode("%ColorPickerButton").Color = DefaultColor; GetNode("%RowTextEdit").Text = ""; EditingRow = null; - Hide(); this.GetParentOfType().MenuClosedEnableInteraction(); } + public void DeleteRow() + { + EditingRow.QueueFree(); + Reset(); + } } diff --git a/row_edit_popup.tscn b/row_edit_popup.tscn index 475429c..f7a7d63 100644 --- a/row_edit_popup.tscn +++ b/row_edit_popup.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=2 format=3 uid="uid://dwtxrx5xtewur"] +[gd_scene load_steps=3 format=3 uid="uid://dwtxrx5xtewur"] [ext_resource type="Script" path="res://row_edit_popup.cs" id="1_1wf8q"] +[ext_resource type="Script" path="res://RowDeleteButton.cs" id="2_wjpay"] [node name="RowEditPopup" type="PanelContainer"] script = ExtResource("1_1wf8q") @@ -10,14 +11,19 @@ layout_mode = 2 theme_override_constants/margin_right = 5 theme_override_constants/margin_bottom = 5 -[node name="VSplitContainer" type="VSplitContainer" parent="RowEditMarginContainer"] +[node name="RowEditOuterVbox" type="VSplitContainer" parent="RowEditMarginContainer"] layout_mode = 2 dragger_visibility = 1 -[node name="RowEditVbox" type="HSplitContainer" parent="RowEditMarginContainer/VSplitContainer"] +[node name="RowEditInnerVbox" type="VSplitContainer" parent="RowEditMarginContainer/RowEditOuterVbox"] layout_mode = 2 +dragger_visibility = 1 -[node name="ColorPickerButton" type="ColorPickerButton" parent="RowEditMarginContainer/VSplitContainer/RowEditVbox"] +[node name="RowEditVbox" type="HSplitContainer" parent="RowEditMarginContainer/RowEditOuterVbox/RowEditInnerVbox"] +layout_mode = 2 +dragger_visibility = 1 + +[node name="ColorPickerButton" type="ColorPickerButton" parent="RowEditMarginContainer/RowEditOuterVbox/RowEditInnerVbox/RowEditVbox"] unique_name_in_owner = true custom_minimum_size = Vector2(200, 200) layout_mode = 2 @@ -25,28 +31,45 @@ size_flags_horizontal = 0 size_flags_vertical = 0 edit_alpha = false -[node name="RowTextEdit" type="TextEdit" parent="RowEditMarginContainer/VSplitContainer/RowEditVbox"] +[node name="RowTextEdit" type="TextEdit" parent="RowEditMarginContainer/RowEditOuterVbox/RowEditInnerVbox/RowEditVbox"] unique_name_in_owner = true custom_minimum_size = Vector2(200, 0) layout_mode = 2 -[node name="RowEditButtonContainer" type="HBoxContainer" parent="RowEditMarginContainer/VSplitContainer"] +[node name="RowDeleteHbox" type="HSplitContainer" parent="RowEditMarginContainer/RowEditOuterVbox/RowEditInnerVbox"] +layout_mode = 2 +size_flags_horizontal = 8 +dragger_visibility = 1 + +[node name="RowDeleteEnableButton" type="CheckBox" parent="RowEditMarginContainer/RowEditOuterVbox/RowEditInnerVbox/RowDeleteHbox"] +layout_mode = 2 + +[node name="RowDeleteButton" type="Button" parent="RowEditMarginContainer/RowEditOuterVbox/RowEditInnerVbox/RowDeleteHbox"] +custom_minimum_size = Vector2(135, 0) +layout_mode = 2 +disabled = true +text = "DELETE" +script = ExtResource("2_wjpay") + +[node name="RowEditButtonContainer" type="HBoxContainer" parent="RowEditMarginContainer/RowEditOuterVbox"] layout_mode = 2 alignment = 2 -[node name="RowEditCancelButton" type="Button" parent="RowEditMarginContainer/VSplitContainer/RowEditButtonContainer"] +[node name="RowEditCancelButton" type="Button" parent="RowEditMarginContainer/RowEditOuterVbox/RowEditButtonContainer"] unique_name_in_owner = true custom_minimum_size = Vector2(100, 0) layout_mode = 2 size_flags_horizontal = 8 text = "Cancel" -[node name="RowEditOkButton" type="Button" parent="RowEditMarginContainer/VSplitContainer/RowEditButtonContainer"] +[node name="RowEditOkButton" type="Button" parent="RowEditMarginContainer/RowEditOuterVbox/RowEditButtonContainer"] unique_name_in_owner = true custom_minimum_size = Vector2(100, 0) layout_mode = 2 size_flags_horizontal = 8 text = "OK" -[connection signal="pressed" from="RowEditMarginContainer/VSplitContainer/RowEditButtonContainer/RowEditCancelButton" to="." method="CancelClicked"] -[connection signal="pressed" from="RowEditMarginContainer/VSplitContainer/RowEditButtonContainer/RowEditOkButton" to="." method="OkClicked"] +[connection signal="toggled" from="RowEditMarginContainer/RowEditOuterVbox/RowEditInnerVbox/RowDeleteHbox/RowDeleteEnableButton" to="RowEditMarginContainer/RowEditOuterVbox/RowEditInnerVbox/RowDeleteHbox/RowDeleteButton" method="ToggleEnable"] +[connection signal="pressed" from="RowEditMarginContainer/RowEditOuterVbox/RowEditInnerVbox/RowDeleteHbox/RowDeleteButton" to="." method="DeleteRow"] +[connection signal="pressed" from="RowEditMarginContainer/RowEditOuterVbox/RowEditButtonContainer/RowEditCancelButton" to="." method="CancelClicked"] +[connection signal="pressed" from="RowEditMarginContainer/RowEditOuterVbox/RowEditButtonContainer/RowEditOkButton" to="." method="OkClicked"] diff --git a/settings_popup.cs b/settings_popup.cs index d56fdfe..17058e7 100644 --- a/settings_popup.cs +++ b/settings_popup.cs @@ -63,6 +63,13 @@ public partial class settings_popup : PanelContainer } public void _on_ok_button_pressed() { + var settings = GetNode("/root/Settings"); + settings.AllowModerators = GetNode("%CheckBoxModerator").ButtonPressed; + settings.Trigger = GetNode("%CommandEdit").Text; + settings.SetUserLists(GetNode("%WhiteListEdit").Text.Split('\n', + StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries), + GetNode("%BlackListEdit").Text.Split('\n', + StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)); GetNode("%ConfigStretchContainer").Apply(); ClosePopup(); } @@ -102,16 +109,11 @@ public partial class settings_popup : PanelContainer } private void SuccessfulConnection() { + GD.Print(nameof(SuccessfulConnection)); var tcw = GetNode("/root/TwitchChatWatcher"); if (tcw.State != System.Net.WebSockets.WebSocketState.Open) throw new Exception("Websocket closed"); - var settings = GetNode("/root/Settings"); - settings.AllowModerators = GetNode("%CheckBoxModerator").ButtonPressed; - settings.Command = GetNode("%CommandEdit").Text; - settings.SetUserLists(GetNode("%WhiteListEdit").Text.Split('\n', - StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries), - GetNode("%BlackListEdit").Text.Split('\n', - StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)); + GetNode("%JoinChannelButton").Disabled = false; UnlockPopup(); } private void SocketConnected() diff --git a/settings_popup.tscn b/settings_popup.tscn index d4f6dd2..63563a3 100644 --- a/settings_popup.tscn +++ b/settings_popup.tscn @@ -112,6 +112,7 @@ unique_name_in_owner = true custom_minimum_size = Vector2(125, 0) layout_mode = 2 size_flags_horizontal = 8 +disabled = true text = "Join Channel" [node name="ConnectButton" type="Button" parent="SettingsDivider/SettingsPopupContainer/ChatMarginContainer/ChatContainer/ConnectButtonMarginContainer/HBoxContainer"] @@ -217,6 +218,7 @@ unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 4 size_flags_vertical = 4 +button_pressed = true text = "Scale Images" [node name="ButtonContainer" type="HBoxContainer" parent="SettingsDivider"]