diff --git a/ClearButton.cs b/ClearButton.cs new file mode 100644 index 0000000..5438d99 --- /dev/null +++ b/ClearButton.cs @@ -0,0 +1,23 @@ +using Godot; +using System; + +public partial class ClearButton : 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) + { + } + public void EnableToggled(bool newState) + { + Disabled = !newState; + } + public void ClearPressed() + { + this.GetParentOfType().Clear(); + } +} diff --git a/CommandHandler.cs b/CommandHandler.cs index 0f247c5..de04e50 100644 --- a/CommandHandler.cs +++ b/CommandHandler.cs @@ -51,14 +51,11 @@ public partial class CommandHandler : Node private void IncomingCommand(Command command) { - GD.Print("Received command"); if (!Settings.IsUserAuthorized(command.User, command.IsStreamer, command.IsModerator)) return; - GD.Print($"User {command.User} is authorized"); var baseArgs = command.GetArgs(); var type = CommandTypeHelper.ParseCommand(baseArgs.Pop()); - GD.Print($"Command type: {type}"); var args = baseArgs.DuplicateAtState(); switch (type) { diff --git a/ExportButton.cs b/ExportButton.cs new file mode 100644 index 0000000..062b5ae --- /dev/null +++ b/ExportButton.cs @@ -0,0 +1,19 @@ +using Godot; +using System; + +public partial class ExportButton : 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) + { + } + public void ExportPressed() + { + GetNode("%ExportDialog").Show(); + } +} diff --git a/ExportSettings.cs b/ExportSettings.cs new file mode 100644 index 0000000..e37e4f9 --- /dev/null +++ b/ExportSettings.cs @@ -0,0 +1,9 @@ +using Godot; + +public partial class ExportSettings : GodotObject +{ + /// + /// Scales images down to size of the + /// + public bool ScaleImages { get; set; } = false; +} \ No newline at end of file diff --git a/Extensions.cs b/Extensions.cs index fb12933..77e7d77 100644 --- a/Extensions.cs +++ b/Extensions.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Godot; +using Godot.NativeInterop; public static class ExtensionHelper { @@ -65,10 +66,11 @@ public static class ExtensionHelper i++; } } - public static string GetUnusedCardId(this SceneTree tree) + public static string GetUnusedCardId(this SceneTree tree, params string[] otherIds) { //use hashset because there are (probably) more cards than rows - var ids = tree.GetNodesInGroup("CardGroup").OfType().Select(c => c.CardId).ToHashSet(); + var ids = tree.GetNodesInGroup("CardGroup").OfType().Select(c => c.CardId) + .Concat(otherIds).ToHashSet(); int i = 1; while (true) { @@ -91,4 +93,17 @@ public static class ExtensionHelper => 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)); + public static System.Drawing.Color ToSystemColor(this Godot.Color color) + => System.Drawing.Color.FromArgb( + (int)(color.R * 255), + (int)(color.G * 255), + (int)(color.B * 255) + ); + public static Godot.Color ToGodotColor(this System.Drawing.Color color) + => new Godot.Color( + color.R / 255.0f, + color.G / 255.0f, + color.B / 255.0f, + 1 + ); } diff --git a/ImportButton.cs b/ImportButton.cs new file mode 100644 index 0000000..4af983e --- /dev/null +++ b/ImportButton.cs @@ -0,0 +1,19 @@ +using Godot; +using System; + +public partial class ImportButton : 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) + { + } + public void ImportPressed() + { + GetNode("%ImportDialog").Show(); + } +} diff --git a/ImportMarginContainer.cs b/ImportMarginContainer.cs new file mode 100644 index 0000000..c93aeaa --- /dev/null +++ b/ImportMarginContainer.cs @@ -0,0 +1,17 @@ +using Godot; +using System; + +public partial class ImportMarginContainer : MarginContainer +{ + public readonly string Title = "Import"; + // 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/RowCardContainer.cs b/RowCardContainer.cs index f19b86b..a990985 100644 --- a/RowCardContainer.cs +++ b/RowCardContainer.cs @@ -18,6 +18,6 @@ public partial class RowCardContainer : HFlowContainer } public override void _DropData(Vector2 atPosition, Variant data) { - this.GetParentOfType().DropOn(atPosition, data); + this.GetParentOfType().DropCardOn(atPosition, data); } } diff --git a/RowTitleBoxBackground.cs b/RowTitleBoxBackground.cs new file mode 100644 index 0000000..047aa86 --- /dev/null +++ b/RowTitleBoxBackground.cs @@ -0,0 +1,39 @@ +using Godot; +using System; + +public partial class RowTitleBoxBackground : Panel +{ + // 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.IsActionPressed("LocationMenu")) + { + RowMenu(); + } + } + private void RowMenu() + { + this.GetParentOfType().EditRowInMenu(this.GetParentOfType()); + } + public override Variant _GetDragData(Vector2 atPosition) + { + var prev = MakePreview(); + var prev_root = new Control(); + prev_root.AddChild(prev); + prev.Position = prev.Size / -2; + SetDragPreview(prev_root); + return this.GetParentOfType(); + } + private Panel MakePreview() + { + return Duplicate(0) as Panel; + } +} diff --git a/Serialization/SerialCard.cs b/Serialization/SerialCard.cs new file mode 100644 index 0000000..f965500 --- /dev/null +++ b/Serialization/SerialCard.cs @@ -0,0 +1,29 @@ +using Godot; +using System; +using System.Data.Common; +using System.Linq; +using System.Text.Json.Serialization; + +public class SerialCard +{ + [JsonInclude] + public string Text { get; set; } + [JsonInclude] + public SerialImage Image { get; set; } + public card ToCard(SceneTree tree) + { + var c = card.MakeCard(tree); + c.CardName = Text; + if (Image.DataWebp.Any()) + { + var iwm = Image.ToImageWithMetadata(); + c.SetTexture(ImageTexture.CreateFromImage(iwm.Image)); + c.SetStretchMode(iwm.StretchMode); + } + else + { + c.SetStretchMode(Image.StretchMode); + } + return c; + } +} diff --git a/Serialization/SerialColor.cs b/Serialization/SerialColor.cs new file mode 100644 index 0000000..435ccdd --- /dev/null +++ b/Serialization/SerialColor.cs @@ -0,0 +1,42 @@ +using Godot; +using System.Text.Json.Serialization; + +public class SerialColor +{ + [JsonInclude] + public float R { get; set; } + [JsonInclude] + public float G { get; set; } + [JsonInclude] + public float B { get; set; } + public void Deconstruct(out float r, out float g, out float b) + { + r = R; + g = G; + b = B; + } + public SerialColor() + { + R = 0; + G = 0; + B = 0; + } + public SerialColor(float r, float g, float b) + { + R = r; + G = g; + B = b; + } + public SerialColor(Color c) + { + R = c.R; + G = c.G; + B = c.B; + } + public static implicit operator Color(SerialColor sc) + => new( + sc.R, + sc.G, + sc.B + ); +} \ No newline at end of file diff --git a/Serialization/SerialGame.cs b/Serialization/SerialGame.cs new file mode 100644 index 0000000..6bbd669 --- /dev/null +++ b/Serialization/SerialGame.cs @@ -0,0 +1,9 @@ +using System.Text.Json.Serialization; + +public class SerialGame +{ + [JsonInclude] + public SerialRow[] Rows { get; set; } + [JsonInclude] + public SerialCard[] UnassignedCards { get; set; } +} \ No newline at end of file diff --git a/Serialization/SerialImage.cs b/Serialization/SerialImage.cs new file mode 100644 index 0000000..fa7bdcd --- /dev/null +++ b/Serialization/SerialImage.cs @@ -0,0 +1,17 @@ +using System.Text.Json.Serialization; +using Godot; + +public class SerialImage +{ + [JsonInclude] + public byte[] DataWebp { get; set; } + [JsonInclude] + [JsonConverter(typeof(JsonStringEnumConverter))] + public StretchMode StretchMode { get; set; } + public ImageWithMetadata ToImageWithMetadata() + { + var im = new Image(); + im.LoadWebpFromBuffer(DataWebp); + return new(im, StretchMode); + } +} diff --git a/Serialization/SerialRow.cs b/Serialization/SerialRow.cs new file mode 100644 index 0000000..65a8964 --- /dev/null +++ b/Serialization/SerialRow.cs @@ -0,0 +1,24 @@ +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Godot; + +public class SerialRow +{ + [JsonInclude] + public string Text { get; set; } + [JsonInclude] + public SerialColor Color { get; set; } + [JsonInclude] + public SerialCard[] Cards { get; set; } + public row ToRow(SceneTree tree) + { + var r = row.MakeRow(tree); + r.RowText = Text; + r.RowColor = Color; + foreach (var c in Cards) + r.AddCard(c.ToCard(tree)); + return r; + } +} + diff --git a/Serialization/Serializer.cs b/Serialization/Serializer.cs new file mode 100644 index 0000000..35a3c4f --- /dev/null +++ b/Serialization/Serializer.cs @@ -0,0 +1,65 @@ +using Godot; +using System; +using System.Linq; +using System.Text.Json; + +public static class Serializer +{ + public static string CreateGameJson(game g, ExportSettings es) + => JsonSerializer.Serialize(CreateGameObject(g, es)); + private static SerialGame CreateGameObject(game g, ExportSettings es) + => new() + { + Rows = g.GetNode("%RowContainer").GetChildren().OfType() + .Select(r => RowToSerial(r, es)).ToArray(), + UnassignedCards = g.GetNode("%UnassignedCardContainer").GetChildren() + .OfType().Select(c => CardToSerial(c, es)).ToArray(), + }; + private static SerialRow RowToSerial(row r, ExportSettings es) + => new() + { + Color = new(r.RowColor), + Cards = r.Cards.Select(c => CardToSerial(c, es)).ToArray(), + Text = r.RowText + }; + private static SerialCard CardToSerial(card c, ExportSettings es) + { + byte[] imData; + var i = c.GetTexture()?.GetImage(); + if (i is Image img) + { + if (es.ScaleImages) + { + Image copy = new(); + copy.CopyFrom(img); + copy.Resize(500, 500); + imData = copy.SaveWebpToBuffer(true); + } + else + imData = img.SaveWebpToBuffer(false); + } + else + imData = Array.Empty(); + return new() + { + Text = c.CardName, + Image = new() + { + DataWebp = imData, + StretchMode = c.GetStretchMode(), + }, + }; + } + public static void LoadFromSerial(game g, string jsonString) + { + var sg = JsonSerializer.Deserialize(jsonString) + ?? throw new Exception("Failed to deserialize game"); + g.Clear(); + using var context = card.MakeContext(g.GetTree()); + foreach (var r in sg.Rows) + g.AddRow(r.ToRow(g.GetTree())); + foreach (var c in sg.UnassignedCards) + g.AddUnassignedCard(c.ToCard(g.GetTree())); + g.PropogateCardSize(); + } +} diff --git a/SettingsOverlayStyleBox.tres b/SettingsOverlayStyleBox.tres new file mode 100644 index 0000000..15a9004 --- /dev/null +++ b/SettingsOverlayStyleBox.tres @@ -0,0 +1,4 @@ +[gd_resource type="StyleBoxFlat" format=3 uid="uid://cota68polt1iy"] + +[resource] +bg_color = Color(0.32549, 0.32549, 0.32549, 1) diff --git a/TwitchChatWatcher.cs b/TwitchChatWatcher.cs index f1e7fd8..e7b24da 100644 --- a/TwitchChatWatcher.cs +++ b/TwitchChatWatcher.cs @@ -179,6 +179,8 @@ public partial class TwitchChatWatcher : Node else if (tcm is Privmsg p) { var com = Settings.Command; + if (string.IsNullOrWhiteSpace(com)) + break; if (!p.ChatMessage.StartsWith(com)) continue; var chat = p.ChatMessage; diff --git a/card.cs b/card.cs index 486b2b3..d0fea95 100644 --- a/card.cs +++ b/card.cs @@ -1,4 +1,9 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; using Godot; +using Microsoft.VisualBasic; public partial class card : Panel { @@ -150,11 +155,40 @@ public partial class card : Panel { this.GetParentOfType().EditCardInMenu(this); } + //TODO need to completely rework this public static card MakeCard(SceneTree tree) { var scene = GD.Load("res://card.tscn"); var c = scene.Instantiate(); - c.CardId = tree.GetUnusedCardId(); + string[] ids = {}; + if (Context is CardMakerContext cme) + ids = cme.Ids.ToArray(); + c.CardId = tree.GetUnusedCardId(ids); + if (Context is CardMakerContext cme2) + cme2.AddNewId(c.CardId); return c; } + public class CardMakerContext : IDisposable + { + private readonly SceneTree Tree; + private readonly List NewCards = new(); + public IEnumerable Ids => NewCards; + public void AddNewId(string id) => NewCards.Add(id); + public CardMakerContext(SceneTree tree) + { + Tree = tree; + } + public void Dispose() + { + card.Context = null; + } + } + private static CardMakerContext Context = null; + public static CardMakerContext MakeContext(SceneTree tree) + { + if (Context is not null) + return null; + Context = new(tree); + return Context; + } } diff --git a/card_edit_popup.cs b/card_edit_popup.cs index 6f46d3f..a3aab7c 100644 --- a/card_edit_popup.cs +++ b/card_edit_popup.cs @@ -120,6 +120,11 @@ public partial class card_edit_popup : ConfirmationDialog { // Hide(); } + public void DeleteCard() + { + this.GetParentOfType().DeleteCards(EditingCard.CardId); + Hide(); + } public void FileSelected(string path) { Image image = new(); diff --git a/card_edit_popup.tscn b/card_edit_popup.tscn index ef85fbd..3246fa8 100644 --- a/card_edit_popup.tscn +++ b/card_edit_popup.tscn @@ -11,7 +11,7 @@ [node name="CardEditPopup" type="ConfirmationDialog"] title = "Edit Card" position = Vector2i(0, 36) -size = Vector2i(350, 320) +size = Vector2i(350, 327) visible = true unresizable = true always_on_top = true @@ -24,7 +24,7 @@ anchor_bottom = 1.0 offset_left = 8.0 offset_top = 8.0 offset_right = 342.0 -offset_bottom = 271.0 +offset_bottom = 278.0 grow_horizontal = 2 grow_vertical = 2 @@ -88,10 +88,18 @@ layout_mode = 2 button_group = SubResource("ButtonGroup_t74v5") text = "Crop" +[node name="DeleteCardButton" type="Button" parent="CardEditContainer"] +custom_minimum_size = Vector2(100, 0) +layout_mode = 2 +size_flags_horizontal = 8 +size_flags_vertical = 8 +text = "DELETE" + [node name="CardImagePicker" parent="." instance=ExtResource("3_4k21m")] 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="file_selected" from="CardImagePicker" to="." method="FileSelected"] diff --git a/debug.log b/debug.log new file mode 100644 index 0000000..b3b9786 --- /dev/null +++ b/debug.log @@ -0,0 +1 @@ +[0423/181235.827:ERROR:registration_protocol_win.cc(107)] CreateFile: The system cannot find the file specified. (0x2) diff --git a/game.cs b/game.cs index 83ea69f..09c88cd 100644 --- a/game.cs +++ b/game.cs @@ -2,7 +2,9 @@ using Godot; using System; using System.Collections; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Threading.Tasks; public partial class game : Control { @@ -30,16 +32,18 @@ public partial class game : Control { CardSize = size; } - protected void PropogateCardSize() + public void PropogateCardSize() { foreach (var r in GetNode("%RowContainer").GetChildren().OfType()) r.CardSize = _CardSize; foreach (var c in GetNode("%UnassignedCardContainer").GetChildren().OfType()) c.CustomMinimumSize = _CardSize; - SetContainerMinima(); } + public bool AllowDragging = true; public IEnumerable Rows - => GetNode("%RowContainer").GetChildren().OfType(); + => GetNode("%RowContainer").GetChildren().OfType(); + public IEnumerable UnassignedCards + => GetNode("%UnassignedCardContainer").GetChildren().OfType(); // Called when the node enters the scene tree for the first time. public override void _Ready() { @@ -78,38 +82,38 @@ public partial class game : Control GetViewport().SetInputAsHandled(); } } + public void Clear() + { + var rowContainer = GetNode("%RowContainer"); + var unContainer = GetNode("%UnassignedCardContainer"); + foreach (var r in rowContainer.GetChildren()) + { + rowContainer.RemoveChild(r); + r.QueueFree(); + } + foreach (var c in unContainer.GetChildren()) + { + unContainer.RemoveChild(c); + c.QueueFree(); + } + } // Called every frame. 'delta' is the elapsed time since the previous frame. public override void _Process(double delta) { } - public void SetContainerMinima() - { - // var node = GetNode("%RowContainer"); - // node.CustomMinimumSize = new Vector2(0, _CardSize.Y * node.GetChildCount()); - } public row GetRowById(string id) => GetTree().GetNodesInGroup("RowGroup").OfType() .FirstOrDefault(r => r.RowId == id); - public void AddRow(row row, string after = null) + public void AddRow(row row, int index = -1) { - if (after is not null) - { - var r = GetRowById(after) ?? throw new Exception("row id does not exist"); - r.AddSibling(row); - } - else - { - var node = GetNode("%RowContainer"); - node.AddChild(row); - node.MoveChild(row, 0); - } - SetContainerMinima(); + var node = GetNode("%RowContainer"); + node.AddChild(row); + node.MoveChild(row, index); } public void RemoveRow(string id) { var r = GetRowById(id); GetNode("%RowContainer").RemoveChild(r); - SetContainerMinima(); } public void AddUnassignedCard(card c) { @@ -131,6 +135,10 @@ public partial class game : Control { GetNode("%CardEditPopup").ActivateForCard(c); } + public void EditRowInMenu(row r) + { + GetNode("%RowEditPopup").OpenWithRow(r); + } public card ClaimCard(string id) { foreach (row r in Rows) @@ -157,6 +165,28 @@ public partial class game : Control return null; } + public void MenuOpenDisableInteraction() + { + GetNode("%UiMask").MouseFilter = MouseFilterEnum.Stop; + } + public void MenuClosedEnableInteraction() + { + GetNode("%UiMask").MouseFilter = MouseFilterEnum.Ignore; + } + public void ImportGame(string filename) + { + GD.Print($"Importing from {filename}"); + Serializer.LoadFromSerial(this, + File.ReadAllText(filename) + ); + } + public void ExportGame(string filename, ExportSettings es) + { + GD.Print($"Exporting to {filename}"); + File.WriteAllText(filename, + Serializer.CreateGameJson(this, es) + ); + } #region Commands public void MoveCard(string cardId, string targetRowId, int? toIndex = null) { diff --git a/game.tscn b/game.tscn index badf216..6a9eb4b 100644 --- a/game.tscn +++ b/game.tscn @@ -1,11 +1,13 @@ -[gd_scene load_steps=7 format=3 uid="uid://ck0t4k3guvmfm"] +[gd_scene load_steps=9 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"] [ext_resource type="Script" path="res://UnassignedCardPanel.cs" id="3_dbs2t"] [ext_resource type="Script" path="res://PictureDropHandler.cs" id="3_owd27"] +[ext_resource type="StyleBox" uid="uid://cota68polt1iy" path="res://SettingsOverlayStyleBox.tres" id="6_8am6d"] [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"] [node name="Game" type="Control"] layout_mode = 3 @@ -27,6 +29,7 @@ grow_horizontal = 2 grow_vertical = 2 [node name="GameContainer" type="VBoxContainer" parent="GameScrollContainer"] +unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 @@ -79,23 +82,31 @@ layout_mode = 2 unique_name_in_owner = true script = ExtResource("3_owd27") -[node name="CardContextMenu" type="PopupMenu" parent="."] -item_count = 2 -item_0/text = "Rename" -item_0/id = 0 -item_1/text = "Change Picture" -item_1/id = 1 - -[node name="RowContextMenu" type="PopupMenu" parent="."] -item_count = 1 -item_0/text = "" -item_0/id = 0 +[node name="UiMask" type="Control" parent="."] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 [node name="SettingsPopup" parent="." instance=ExtResource("6_e1cou")] unique_name_in_owner = true visible = false layout_mode = 0 +theme_override_styles/panel = ExtResource("6_8am6d") + +[node name="RowEditPopup" parent="." instance=ExtResource("7_nyiqt")] +unique_name_in_owner = true +visible = false +layout_mode = 0 +theme_override_styles/panel = ExtResource("6_8am6d") [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"] diff --git a/row.cs b/row.cs index 65c05ad..714f1eb 100644 --- a/row.cs +++ b/row.cs @@ -98,7 +98,7 @@ public partial class row : Control { } - public void DropOn(Vector2 atPosition, Variant data) + public void DropCardOn(Vector2 atPosition, Variant data) { GD.Print($"Dropping at {atPosition}"); card c = data.As() @@ -128,6 +128,23 @@ public partial class row : Control { throw new Exception($"Can't find card {c.CardId}"); } + } + public override bool _CanDropData(Vector2 atPosition, Variant data) + { + return data.As() is not null; + } + public override void _DropData(Vector2 atPosition, Variant data) + { + var r = data.As() + ?? throw new Exception("Invalid drop row"); + if (ReferenceEquals(this, r)) + return; + var toIndex = GetIndex(); + if (atPosition.Y > Size.Y / 2) + toIndex++; + if (r.GetIndex() < GetIndex()) + toIndex--; + GetParent().MoveChild(r, toIndex); } public void AddCard(card card, int? toIndex = null) { diff --git a/row.tscn b/row.tscn index d528e52..dfea5b2 100644 --- a/row.tscn +++ b/row.tscn @@ -1,8 +1,9 @@ -[gd_scene load_steps=8 format=3 uid="uid://b7pebyti48f7b"] +[gd_scene load_steps=9 format=3 uid="uid://b7pebyti48f7b"] [ext_resource type="Script" path="res://row.cs" id="1_dodxa"] [ext_resource type="Script" path="res://RowGrid.cs" id="2_h4wwk"] [ext_resource type="Script" path="res://RowCardContainer.cs" id="3_0etg2"] +[ext_resource type="Script" path="res://RowTitleBoxBackground.cs" id="3_y52xd"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_spa1m"] @@ -46,8 +47,9 @@ unique_name_in_owner = true layout_mode = 2 size_flags_horizontal = 0 size_flags_vertical = 0 -mouse_filter = 2 +mouse_filter = 1 theme_override_styles/panel = SubResource("StyleBoxFlat_22f0d") +script = ExtResource("3_y52xd") [node name="RowTitleBoxLabel" type="Label" parent="RowGrid/RowBaseContainer/RowTitleBoxBackground"] unique_name_in_owner = true diff --git a/row_edit_popup.cs b/row_edit_popup.cs new file mode 100644 index 0000000..5e57011 --- /dev/null +++ b/row_edit_popup.cs @@ -0,0 +1,48 @@ +using Godot; +using System; + +public partial class row_edit_popup : PanelContainer +{ + [Export] + private Color DefaultColor = new(0, 0, 0, 1); + [Signal] + public delegate void NowVisibleEventHandler(); + [Signal] + public delegate void NowInvisibleEventHandler(); + public row EditingRow; + // 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 OpenWithRow(row r) + { + EditingRow = r; + GetNode("%ColorPickerButton").Color = r.RowColor; + GetNode("%RowTextEdit").Text = r.RowText; + this.GetParentOfType().MenuOpenDisableInteraction(); + Show(); + } + public void OkClicked() + { + EditingRow.RowColor = GetNode("%ColorPickerButton").Color; + EditingRow.RowText = GetNode("%RowTextEdit").Text; + Reset(); + } + public void CancelClicked() + { + Reset(); + } + public void Reset() + { + GetNode("%ColorPickerButton").Color = DefaultColor; + GetNode("%RowTextEdit").Text = ""; + EditingRow = null; + Hide(); + this.GetParentOfType().MenuClosedEnableInteraction(); + } +} diff --git a/row_edit_popup.tscn b/row_edit_popup.tscn new file mode 100644 index 0000000..475429c --- /dev/null +++ b/row_edit_popup.tscn @@ -0,0 +1,52 @@ +[gd_scene load_steps=2 format=3 uid="uid://dwtxrx5xtewur"] + +[ext_resource type="Script" path="res://row_edit_popup.cs" id="1_1wf8q"] + +[node name="RowEditPopup" type="PanelContainer"] +script = ExtResource("1_1wf8q") + +[node name="RowEditMarginContainer" type="MarginContainer" parent="."] +layout_mode = 2 +theme_override_constants/margin_right = 5 +theme_override_constants/margin_bottom = 5 + +[node name="VSplitContainer" type="VSplitContainer" parent="RowEditMarginContainer"] +layout_mode = 2 +dragger_visibility = 1 + +[node name="RowEditVbox" type="HSplitContainer" parent="RowEditMarginContainer/VSplitContainer"] +layout_mode = 2 + +[node name="ColorPickerButton" type="ColorPickerButton" parent="RowEditMarginContainer/VSplitContainer/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="RowEditMarginContainer/VSplitContainer/RowEditVbox"] +unique_name_in_owner = true +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 + +[node name="RowEditButtonContainer" type="HBoxContainer" parent="RowEditMarginContainer/VSplitContainer"] +layout_mode = 2 +alignment = 2 + +[node name="RowEditCancelButton" type="Button" parent="RowEditMarginContainer/VSplitContainer/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"] +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"] diff --git a/settings_popup.cs b/settings_popup.cs index 0ffa7c2..d56fdfe 100644 --- a/settings_popup.cs +++ b/settings_popup.cs @@ -19,6 +19,10 @@ public partial class settings_popup : PanelContainer public string Channel => GetNode("%ChannelNameEdit").Text; [Signal] public delegate void BeforeOkEventHandler(); + [Signal] + public delegate void ImportSelectedEventHandler(string filename); + [Signal] + public delegate void ExportSelectedEventHandler(string filename, ExportSettings settings); // Called when the node enters the scene tree for the first time. public override void _Ready() { @@ -45,11 +49,13 @@ public partial class settings_popup : PanelContainer } public void ShowPopup() { - Visible = true; + this.GetParentOfType().MenuOpenDisableInteraction(); + Show(); } public void ClosePopup() { Hide(); + this.GetParentOfType().MenuClosedEnableInteraction(); } public void _on_cancel_button_pressed() { @@ -116,4 +122,16 @@ public partial class settings_popup : PanelContainer { GetNode("%ConnectButton").Disabled = false; } + private void ImportFileSelected(string filename) + { + EmitSignal(SignalName.ImportSelected, filename); + } + private void ExportFileSelected(string filename) + { + ExportSettings es = new() + { + ScaleImages = GetNode("%ExportCompressPicturesButton").ButtonPressed, + }; + EmitSignal(SignalName.ExportSelected, filename, Variant.From(es)); + } } diff --git a/settings_popup.tscn b/settings_popup.tscn index da47af4..d4f6dd2 100644 --- a/settings_popup.tscn +++ b/settings_popup.tscn @@ -1,9 +1,13 @@ -[gd_scene load_steps=7 format=3 uid="uid://jm7tss267q8y"] +[gd_scene load_steps=11 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"] +[ext_resource type="Script" path="res://ClearButton.cs" id="5_71uyg"] +[ext_resource type="Script" path="res://ImportMarginContainer.cs" id="5_b5ygb"] +[ext_resource type="Script" path="res://ImportButton.cs" id="6_mxvlq"] +[ext_resource type="Script" path="res://ExportButton.cs" id="7_lurd3"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jcc71"] @@ -155,6 +159,66 @@ layout_mode = 2 button_group = SubResource("ButtonGroup_4itga") text = "Crop" +[node name="ClearMarginContainer" type="HBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer"] +layout_mode = 2 + +[node name="CheckBox" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer/ClearMarginContainer"] +layout_mode = 2 + +[node name="ClearButton" type="Button" parent="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer/ClearMarginContainer"] +layout_mode = 2 +disabled = true +text = "Clear Everything" +script = ExtResource("5_71uyg") + +[node name="ImportMarginContainer" type="MarginContainer" parent="SettingsDivider/SettingsPopupContainer"] +visible = false +layout_mode = 2 +script = ExtResource("5_b5ygb") + +[node name="ImportBoxContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ImportMarginContainer"] +layout_mode = 2 +alignment = 1 + +[node name="ImportButton" type="Button" parent="SettingsDivider/SettingsPopupContainer/ImportMarginContainer/ImportBoxContainer"] +custom_minimum_size = Vector2(120, 0) +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +text = "Import" +script = ExtResource("6_mxvlq") + +[node name="ImportDialog" type="FileDialog" parent="SettingsDivider/SettingsPopupContainer/ImportMarginContainer/ImportBoxContainer/ImportButton"] +unique_name_in_owner = true +title = "Open a File" +ok_button_text = "Open" +file_mode = 0 +access = 2 +filters = PackedStringArray("*.tier; Tier Files") +use_native_dialog = true + +[node name="ExportButton" type="Button" parent="SettingsDivider/SettingsPopupContainer/ImportMarginContainer/ImportBoxContainer"] +custom_minimum_size = Vector2(120, 0) +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +text = "Export" +script = ExtResource("7_lurd3") + +[node name="ExportDialog" type="FileDialog" parent="SettingsDivider/SettingsPopupContainer/ImportMarginContainer/ImportBoxContainer/ExportButton"] +unique_name_in_owner = true +size = Vector2i(312, 154) +access = 2 +filters = PackedStringArray("*.tier; Tier Files") +use_native_dialog = true + +[node name="ExportCompressPicturesButton" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ImportMarginContainer/ImportBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 4 +text = "Scale Images" + [node name="ButtonContainer" type="HBoxContainer" parent="SettingsDivider"] layout_mode = 2 alignment = 2 @@ -176,5 +240,11 @@ text = "OK" [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="toggled" from="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer/ClearMarginContainer/CheckBox" to="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer/ClearMarginContainer/ClearButton" method="EnableToggled"] +[connection signal="pressed" from="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer/ClearMarginContainer/ClearButton" to="SettingsDivider/SettingsPopupContainer/ConfigMarginContainer/ConfigContainer/ClearMarginContainer/ClearButton" method="ClearPressed"] +[connection signal="pressed" from="SettingsDivider/SettingsPopupContainer/ImportMarginContainer/ImportBoxContainer/ImportButton" to="SettingsDivider/SettingsPopupContainer/ImportMarginContainer/ImportBoxContainer/ImportButton" method="ImportPressed"] +[connection signal="file_selected" from="SettingsDivider/SettingsPopupContainer/ImportMarginContainer/ImportBoxContainer/ImportButton/ImportDialog" to="." method="ImportFileSelected"] +[connection signal="pressed" from="SettingsDivider/SettingsPopupContainer/ImportMarginContainer/ImportBoxContainer/ExportButton" to="SettingsDivider/SettingsPopupContainer/ImportMarginContainer/ImportBoxContainer/ExportButton" method="ExportPressed"] +[connection signal="file_selected" from="SettingsDivider/SettingsPopupContainer/ImportMarginContainer/ImportBoxContainer/ExportButton/ExportDialog" to="." method="ExportFileSelected"] [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"]