mirror of
https://codeberg.org/Ikatono/TierMaker.git
synced 2025-10-28 20:45:35 -05:00
Compare commits
4 Commits
8e01e9cb9b
...
v0.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 8753d6134d | |||
| e25e7da40f | |||
| f67885d217 | |||
| 56dcbb62af |
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,2 +1,11 @@
|
||||
# Godot 4+ specific ignores
|
||||
.godot/
|
||||
debug.log
|
||||
|
||||
# vscode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
25
CardCreateImageBox.cs
Normal file
25
CardCreateImageBox.cs
Normal file
@@ -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<FileDialog>("%CardImagePicker").Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
102
CardCreateMarginContainer.cs
Normal file
102
CardCreateMarginContainer.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using Godot;
|
||||
using System;
|
||||
|
||||
public partial class CardCreateMarginContainer : MarginContainer
|
||||
{
|
||||
public readonly string Title = "Card";
|
||||
public string CardTitle
|
||||
{
|
||||
get => GetNode<LineEdit>("%TitleEdit").Text;
|
||||
set => GetNode<LineEdit>("%TitleEdit").Text = value;
|
||||
}
|
||||
public void SetStretchMode(StretchMode stretchMode)
|
||||
{
|
||||
switch (stretchMode)
|
||||
{
|
||||
case StretchMode.Unspecified:
|
||||
case StretchMode.Fit:
|
||||
default:
|
||||
GetNode<BaseButton>("%StretchModeFitButton").ButtonPressed = true;
|
||||
break;
|
||||
case StretchMode.Stretch:
|
||||
GetNode<BaseButton>("%StretchModeStretchButton").ButtonPressed = true;
|
||||
break;
|
||||
case StretchMode.Crop:
|
||||
GetNode<BaseButton>("%StretchModeCropButton").ButtonPressed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
public StretchMode GetStretchMode()
|
||||
{
|
||||
if (GetNode<BaseButton>("%StretchModeFitButton").ButtonPressed)
|
||||
return StretchMode.Fit;
|
||||
else if (GetNode<BaseButton>("%StretchModeStretchButton").ButtonPressed)
|
||||
return StretchMode.Stretch;
|
||||
else if (GetNode<BaseButton>("%StretchModeCropButton").ButtonPressed)
|
||||
return StretchMode.Crop;
|
||||
return StretchMode.Unspecified;
|
||||
}
|
||||
private void StetchModeChanged(BaseButton button)
|
||||
{
|
||||
var ci = GetNode<CardCreateImageBox>("%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<TextureRect>("%CardCreateImageBox").Texture?.GetImage();
|
||||
set => GetNode<TextureRect>("%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<BaseButton>("%StretchModeFitButton").ButtonGroup.Pressed
|
||||
+= StetchModeChanged;
|
||||
GetNode<LineEdit>("%TitleEdit").TextSubmitted +=
|
||||
(s) => GetNode<BaseButton>("%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<TextureRect>("%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<game>().AddUnassignedCard(c);
|
||||
}
|
||||
public void FileSelected(string path)
|
||||
{
|
||||
Image image = new();
|
||||
image.Load(path);
|
||||
Image = image;
|
||||
}
|
||||
}
|
||||
@@ -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<FileDialog>("%CardImagePicker").Show();
|
||||
|
||||
GetNode<FileDialog>("%CardImagePicker").Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
23
ClearButton.cs
Normal file
23
ClearButton.cs
Normal file
@@ -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<game>().Clear();
|
||||
}
|
||||
}
|
||||
@@ -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<Settings>("/root/Settings");
|
||||
Game = GetNode<game>("/root/Game");
|
||||
GetNode<TwitchChatWatcher>("/root/TwitchChatWatcher").IncomingCommand
|
||||
@@ -51,14 +53,12 @@ public partial class CommandHandler : Node
|
||||
|
||||
private void IncomingCommand(Command command)
|
||||
{
|
||||
GD.Print("Received command");
|
||||
GD.Print(command.GetArgs().Remaining());
|
||||
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)
|
||||
{
|
||||
@@ -170,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);
|
||||
@@ -198,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);
|
||||
|
||||
19
DeleteCardButton.cs
Normal file
19
DeleteCardButton.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
19
ExportButton.cs
Normal file
19
ExportButton.cs
Normal file
@@ -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<FileDialog>("%ExportDialog").Show();
|
||||
}
|
||||
}
|
||||
9
ExportSettings.cs
Normal file
9
ExportSettings.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Godot;
|
||||
|
||||
public partial class ExportSettings : GodotObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Scales images down to size of the
|
||||
/// </summary>
|
||||
public bool ScaleImages { get; set; } = false;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Godot;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
public static class ExtensionHelper
|
||||
{
|
||||
@@ -56,19 +57,22 @@ public static class ExtensionHelper
|
||||
}
|
||||
public static string GetUnusedRowId(this SceneTree tree)
|
||||
{
|
||||
var ids = tree.GetNodesInGroup("RowGroup").OfType<row>().Select(r => r.RowId).ToArray();
|
||||
var ids = tree.GetNodesInGroup("RowGroup").OfType<row>().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++;
|
||||
}
|
||||
}
|
||||
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<card>().Select(c => c.CardId).ToHashSet();
|
||||
var ids = tree.GetNodesInGroup("CardGroup").OfType<card>().Select(c => c.CardId)
|
||||
.Concat(otherIds).ToHashSet();
|
||||
int i = 1;
|
||||
while (true)
|
||||
{
|
||||
@@ -91,4 +95,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
|
||||
);
|
||||
}
|
||||
|
||||
19
ImportButton.cs
Normal file
19
ImportButton.cs
Normal file
@@ -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<FileDialog>("%ImportDialog").Show();
|
||||
}
|
||||
}
|
||||
17
ImportMarginContainer.cs
Normal file
17
ImportMarginContainer.cs
Normal file
@@ -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<TabContainer>().SetTabTitle(GetIndex(), Title);
|
||||
}
|
||||
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
}
|
||||
}
|
||||
75
README.md
Normal file
75
README.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Tier Maker
|
||||
|
||||
A basic tierlist maker that also connects to Twitch chat so your moderators can control it for you.
|
||||
|
||||
## How to
|
||||
|
||||
Drag cards to move them and rearrange them. Drag rows by their title cards (box on the left) to rearrange them.
|
||||
|
||||
Right click on a card to open the card edit/delete menu. You can change the text, image, and stretch mode here, or delete the card. Right click on a row title card to open the row edit/delete menu. You can edit the text and color here, or delete the row. For safety, delete buttons are locked by default.
|
||||
|
||||
Drag images onto the window to import them as a new card.
|
||||
|
||||
### Main menu
|
||||
|
||||
F1 opens the main menu. The first tab is for Twitch chat integration. Set channel, click "connect", then click "join". You can change the channel later with "join". Set the trigger command (documentation uses !tier) and grant user permissions here.
|
||||
|
||||
The second tab is for configuration. There's very little here right now.
|
||||
|
||||
The third tab is for import/export. Tier Maker exports to .tier files (deflate-compressed json) with card images embedded. These can be ver big if you unset the "scale images" button.
|
||||
|
||||
### Create menu
|
||||
|
||||
F2 opens the create menu. The first tab lets you create a new card, the second a new row. These are very similar to the edit menus.
|
||||
|
||||
NOTE: due to a bug (possibly in Godot itself), when you open the create menu it may not show the whole menu. Changing tabs should fix this.
|
||||
|
||||
### Twitch connection
|
||||
|
||||
After connected to Twitch chat, authorized users can control the tier list with the following commands. These commands reference cards and rows by their IDs, the number in the bottom left. When moving a row or placing a card within a row, *index* refers to how many cards/rows are before it, meaning *0* is the first spot.
|
||||
|
||||
Commands are written as:
|
||||
|
||||
*trigger* *commandname* arg1 arg2...
|
||||
|
||||
#### Command names:
|
||||
|
||||
movecard CardID RowID [index]
|
||||
|
||||
Move card *CardID* to the row *RowID*. Placed at the end of the row unless index is provided. Use _ for *RowID* to move the card to the unassigned region at the bottom.
|
||||
|
||||
moverow RowID index
|
||||
|
||||
Move row *RowID* to the given index.
|
||||
|
||||
deletecard CardID [CardID2...]
|
||||
|
||||
Deletes one or more cards with the given IDs.
|
||||
|
||||
deleterow RowId [DeleteCards?]
|
||||
|
||||
Deletes a single row with the given ID. By default, cards in this row are moved to the unassigned region, but if you end the command with "true" (!tier deleterow 4 true) then the cards will be deleted instead.
|
||||
|
||||
createcard ImageUrl "Card text with spaces"
|
||||
|
||||
Creates a new card. Attempts to download the image from the provided URL (or use _ if there is no image). Everything after the URL is the card text, and spaces are kept.
|
||||
|
||||
createrow Color "Row text with spaces"
|
||||
|
||||
Creates a new row. Accepts either hex color codes or some color names. Everything after the color is the row text, and spaces are kept.
|
||||
|
||||
renamecard CardID "New card text with spaces"
|
||||
|
||||
Changes the text on an existing card.
|
||||
|
||||
renamerow RowID "New row text with spaces"
|
||||
|
||||
Changes the text on an existing row.
|
||||
|
||||
recolorrow RowID Color
|
||||
|
||||
Changes the color of an existing row.
|
||||
|
||||
changecardimage CardID ImageUrl
|
||||
|
||||
Changes the image for an existing card.
|
||||
@@ -14,10 +14,10 @@ public partial class RowCardContainer : HFlowContainer
|
||||
}
|
||||
public override bool _CanDropData(Vector2 atPosition, Variant data)
|
||||
{
|
||||
return data.As<card>() is not null;
|
||||
return data.Obj is card;
|
||||
}
|
||||
public override void _DropData(Vector2 atPosition, Variant data)
|
||||
{
|
||||
this.GetParentOfType<row>().DropOn(atPosition, data);
|
||||
this.GetParentOfType<row>().DropCardOn(atPosition, data);
|
||||
}
|
||||
}
|
||||
|
||||
32
RowCreateMarginContainer.cs
Normal file
32
RowCreateMarginContainer.cs
Normal file
@@ -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<ColorPickerButton>("%RowCreateColorPickerButton").Color;
|
||||
r.RowText = GetNode<TextEdit>("%RowTextEdit").Text;
|
||||
this.GetParentOfType<game>().CallDeferred("AddRow", r, -1);
|
||||
}
|
||||
public void ClearMenu()
|
||||
{
|
||||
GetNode<ColorPickerButton>("%RowCreateColorPickerButton").Color = DefaultColor;
|
||||
GetNode<TextEdit>("%RowTextEdit").Text = "";
|
||||
}
|
||||
}
|
||||
20
RowDeleteButton.cs
Normal file
20
RowDeleteButton.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
39
RowTitleBoxBackground.cs
Normal file
39
RowTitleBoxBackground.cs
Normal file
@@ -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<game>().EditRowInMenu(this.GetParentOfType<row>());
|
||||
}
|
||||
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<row>();
|
||||
}
|
||||
private Panel MakePreview()
|
||||
{
|
||||
return Duplicate(0) as Panel;
|
||||
}
|
||||
}
|
||||
29
Serialization/SerialCard.cs
Normal file
29
Serialization/SerialCard.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
42
Serialization/SerialColor.cs
Normal file
42
Serialization/SerialColor.cs
Normal file
@@ -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
|
||||
);
|
||||
}
|
||||
9
Serialization/SerialGame.cs
Normal file
9
Serialization/SerialGame.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class SerialGame
|
||||
{
|
||||
[JsonInclude]
|
||||
public SerialRow[] Rows { get; set; }
|
||||
[JsonInclude]
|
||||
public SerialCard[] UnassignedCards { get; set; }
|
||||
}
|
||||
17
Serialization/SerialImage.cs
Normal file
17
Serialization/SerialImage.cs
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
24
Serialization/SerialRow.cs
Normal file
24
Serialization/SerialRow.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
65
Serialization/Serializer.cs
Normal file
65
Serialization/Serializer.cs
Normal file
@@ -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<row>()
|
||||
.Select(r => RowToSerial(r, es)).ToArray(),
|
||||
UnassignedCards = g.GetNode("%UnassignedCardContainer").GetChildren()
|
||||
.OfType<card>().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<byte>();
|
||||
return new()
|
||||
{
|
||||
Text = c.CardName,
|
||||
Image = new()
|
||||
{
|
||||
DataWebp = imData,
|
||||
StretchMode = c.GetStretchMode(),
|
||||
},
|
||||
};
|
||||
}
|
||||
public static void LoadFromSerial(game g, string jsonString)
|
||||
{
|
||||
var sg = JsonSerializer.Deserialize<SerialGame>(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();
|
||||
}
|
||||
}
|
||||
@@ -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<string> UserWhitelist { get; } = new();
|
||||
public List<string> UserBlacklist { get; } = new();
|
||||
public Vector2 CardSize { get; private set; }
|
||||
|
||||
4
SettingsOverlayStyleBox.tres
Normal file
4
SettingsOverlayStyleBox.tres
Normal file
@@ -0,0 +1,4 @@
|
||||
[gd_resource type="StyleBoxFlat" format=3 uid="uid://cota68polt1iy"]
|
||||
|
||||
[resource]
|
||||
bg_color = Color(0.32549, 0.32549, 0.32549, 1)
|
||||
@@ -178,11 +178,13 @@ public partial class TwitchChatWatcher : Node
|
||||
_ = Task.Run(() => SendPong(tcm), Token);
|
||||
else if (tcm is Privmsg p)
|
||||
{
|
||||
var com = Settings.Command;
|
||||
if (!p.ChatMessage.StartsWith(com))
|
||||
var trig = Settings.Trigger;
|
||||
if (string.IsNullOrWhiteSpace(trig))
|
||||
break;
|
||||
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,
|
||||
|
||||
37
card.cs
37
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
|
||||
{
|
||||
@@ -119,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);
|
||||
@@ -150,11 +154,40 @@ public partial class card : Panel
|
||||
{
|
||||
this.GetParentOfType<game>().EditCardInMenu(this);
|
||||
}
|
||||
//TODO need to completely rework this
|
||||
public static card MakeCard(SceneTree tree)
|
||||
{
|
||||
var scene = GD.Load<PackedScene>("res://card.tscn");
|
||||
var c = scene.Instantiate<card>();
|
||||
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<string> NewCards = new();
|
||||
public IEnumerable<string> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,11 @@ public partial class card_edit_popup : ConfirmationDialog
|
||||
{
|
||||
// Hide();
|
||||
}
|
||||
public void DeleteCard()
|
||||
{
|
||||
this.GetParentOfType<game>().DeleteCards(EditingCard.CardId);
|
||||
Hide();
|
||||
}
|
||||
public void FileSelected(string path)
|
||||
{
|
||||
Image image = new();
|
||||
|
||||
@@ -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"]
|
||||
@@ -11,7 +12,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 +25,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 +89,29 @@ layout_mode = 2
|
||||
button_group = SubResource("ButtonGroup_t74v5")
|
||||
text = "Crop"
|
||||
|
||||
[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
|
||||
|
||||
[connection signal="canceled" from="." to="." method="CancelClicked"]
|
||||
[connection signal="confirmed" from="." to="." method="OkClicked"]
|
||||
[connection signal="visibility_changed" from="." to="." method="OnVisibilityChange"]
|
||||
[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"]
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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.
|
||||
|
||||
79
create_menu_popup.cs
Normal file
79
create_menu_popup.cs
Normal file
@@ -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>("%CardCreateMarginContainer");
|
||||
return _CardContainer;
|
||||
}
|
||||
}
|
||||
private RowCreateMarginContainer _RowContainer;
|
||||
public RowCreateMarginContainer RowContainer
|
||||
{ get
|
||||
{
|
||||
_RowContainer ??= GetNode<RowCreateMarginContainer>("%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<game>().MenuOpenDisableInteraction();
|
||||
Show();
|
||||
}
|
||||
public void ClosePopup()
|
||||
{
|
||||
Hide();
|
||||
EmitSignal(SignalName.ClearMenu);
|
||||
this.GetParentOfType<game>().MenuClosedEnableInteraction();
|
||||
}
|
||||
public void OkPressed()
|
||||
{
|
||||
var current = GetNode<TabContainer>("%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<TabContainer>("%CreateTabContainer");
|
||||
if (tabs.SelectNextAvailable())
|
||||
tabs.SelectPreviousAvailable();
|
||||
if (tabs.SelectPreviousAvailable())
|
||||
tabs.SelectNextAvailable();
|
||||
}
|
||||
}
|
||||
155
create_menu_popup.tscn
Normal file
155
create_menu_popup.tscn
Normal file
@@ -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"]
|
||||
1
debug.log
Normal file
1
debug.log
Normal file
@@ -0,0 +1 @@
|
||||
[0423/181235.827:ERROR:registration_protocol_win.cc(107)] CreateFile: The system cannot find the file specified. (0x2)
|
||||
65
export_presets.cfg
Normal file
65
export_presets.cfg
Normal file
@@ -0,0 +1,65 @@
|
||||
[preset.0]
|
||||
|
||||
name="Windows Desktop"
|
||||
platform="Windows Desktop"
|
||||
runnable=true
|
||||
dedicated_server=false
|
||||
custom_features=""
|
||||
export_filter="all_resources"
|
||||
include_filter=""
|
||||
exclude_filter=""
|
||||
export_path="../TierMakerControl.exe"
|
||||
encryption_include_filters=""
|
||||
encryption_exclude_filters=""
|
||||
encrypt_pck=false
|
||||
encrypt_directory=false
|
||||
|
||||
[preset.0.options]
|
||||
|
||||
custom_template/debug=""
|
||||
custom_template/release=""
|
||||
debug/export_console_wrapper=1
|
||||
binary_format/embed_pck=true
|
||||
texture_format/bptc=true
|
||||
texture_format/s3tc=true
|
||||
texture_format/etc=false
|
||||
texture_format/etc2=false
|
||||
binary_format/architecture="x86_64"
|
||||
codesign/enable=false
|
||||
codesign/timestamp=true
|
||||
codesign/timestamp_server_url=""
|
||||
codesign/digest_algorithm=1
|
||||
codesign/description=""
|
||||
codesign/custom_options=PackedStringArray()
|
||||
application/modify_resources=true
|
||||
application/icon=""
|
||||
application/console_wrapper_icon=""
|
||||
application/icon_interpolation=4
|
||||
application/file_version=""
|
||||
application/product_version=""
|
||||
application/company_name=""
|
||||
application/product_name=""
|
||||
application/file_description=""
|
||||
application/copyright=""
|
||||
application/trademarks=""
|
||||
application/export_angle=0
|
||||
ssh_remote_deploy/enabled=false
|
||||
ssh_remote_deploy/host="user@host_ip"
|
||||
ssh_remote_deploy/port="22"
|
||||
ssh_remote_deploy/extra_args_ssh=""
|
||||
ssh_remote_deploy/extra_args_scp=""
|
||||
ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}'
|
||||
$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}'
|
||||
$trigger = New-ScheduledTaskTrigger -Once -At 00:00
|
||||
$settings = New-ScheduledTaskSettingsSet
|
||||
$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings
|
||||
Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true
|
||||
Start-ScheduledTask -TaskName godot_remote_debug
|
||||
while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 }
|
||||
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue"
|
||||
ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue
|
||||
Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue
|
||||
Remove-Item -Recurse -Force '{temp_dir}'"
|
||||
dotnet/include_scripts_content=false
|
||||
dotnet/include_debug_symbols=true
|
||||
dotnet/embed_build_outputs=false
|
||||
159
game.cs
159
game.cs
@@ -2,7 +2,11 @@ using Godot;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public partial class game : Control
|
||||
{
|
||||
@@ -14,6 +18,14 @@ public partial class game : Control
|
||||
return _SettingsPopup;
|
||||
}
|
||||
}
|
||||
private create_menu_popup _CreateMenuPopup;
|
||||
private create_menu_popup CreateMenuPopup
|
||||
{ get
|
||||
{
|
||||
_CreateMenuPopup ??= GetNode<create_menu_popup>("%CreateMenuPopup");
|
||||
return _CreateMenuPopup;
|
||||
}
|
||||
}
|
||||
[Export]
|
||||
private Vector2 _CardSize = new(200, 200);
|
||||
public Vector2 CardSize
|
||||
@@ -30,35 +42,37 @@ public partial class game : Control
|
||||
{
|
||||
CardSize = size;
|
||||
}
|
||||
protected void PropogateCardSize()
|
||||
public void PropogateCardSize()
|
||||
{
|
||||
foreach (var r in GetNode("%RowContainer").GetChildren().OfType<row>())
|
||||
r.CardSize = _CardSize;
|
||||
foreach (var c in GetNode("%UnassignedCardContainer").GetChildren().OfType<card>())
|
||||
c.CustomMinimumSize = _CardSize;
|
||||
SetContainerMinima();
|
||||
}
|
||||
public bool AllowDragging = true;
|
||||
public IEnumerable<row> Rows
|
||||
=> GetNode<VBoxContainer>("%RowContainer").GetChildren().OfType<row>();
|
||||
=> GetNode("%RowContainer").GetChildren().OfType<row>();
|
||||
public IEnumerable<card> UnassignedCards
|
||||
=> GetNode("%UnassignedCardContainer").GetChildren().OfType<card>();
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready()
|
||||
{
|
||||
var rows = this.GetAllDescendents<row>().ToArray();
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
var c = card.MakeCard(GetTree());
|
||||
c.CardName = $"Card {c.CardId}";
|
||||
if (GD.RandRange(0, 1) == 1)
|
||||
{
|
||||
//add to a row
|
||||
var r = rows[GD.RandRange(0, rows.Length - 1)];
|
||||
r.AddCard(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddUnassignedCard(c);
|
||||
}
|
||||
}
|
||||
// var rows = this.GetAllDescendents<row>().ToArray();
|
||||
// for (int i = 0; i < 20; i++)
|
||||
// {
|
||||
// var c = card.MakeCard(GetTree());
|
||||
// c.CardName = $"Card {c.CardId}";
|
||||
// if (GD.RandRange(0, 1) == 1)
|
||||
// {
|
||||
// //add to a row
|
||||
// var r = rows[GD.RandRange(0, rows.Length - 1)];
|
||||
// r.AddCard(c);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// AddUnassignedCard(c);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
PropogateCardSize();
|
||||
@@ -73,43 +87,58 @@ 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()
|
||||
{
|
||||
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<VBoxContainer>("%RowContainer");
|
||||
// node.CustomMinimumSize = new Vector2(0, _CardSize.Y * node.GetChildCount());
|
||||
}
|
||||
public row GetRowById(string id)
|
||||
=> GetTree().GetNodesInGroup("RowGroup").OfType<row>()
|
||||
.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<VBoxContainer>("%RowContainer");
|
||||
node.AddChild(row);
|
||||
node.MoveChild(row, 0);
|
||||
}
|
||||
SetContainerMinima();
|
||||
var node = GetNode<VBoxContainer>("%RowContainer");
|
||||
node.AddChild(row);
|
||||
node.MoveChild(row, index);
|
||||
PropogateCardSize();
|
||||
}
|
||||
public void RemoveRow(string id)
|
||||
{
|
||||
var r = GetRowById(id);
|
||||
GetNode<VBoxContainer>("%RowContainer").RemoveChild(r);
|
||||
SetContainerMinima();
|
||||
}
|
||||
public void AddUnassignedCard(card c)
|
||||
{
|
||||
@@ -131,6 +160,10 @@ public partial class game : Control
|
||||
{
|
||||
GetNode<card_edit_popup>("%CardEditPopup").ActivateForCard(c);
|
||||
}
|
||||
public void EditRowInMenu(row r)
|
||||
{
|
||||
GetNode<row_edit_popup>("%RowEditPopup").OpenWithRow(r);
|
||||
}
|
||||
public card ClaimCard(string id)
|
||||
{
|
||||
foreach (row r in Rows)
|
||||
@@ -157,16 +190,55 @@ public partial class game : Control
|
||||
return null;
|
||||
}
|
||||
|
||||
public void MenuOpenDisableInteraction()
|
||||
{
|
||||
GetNode<Control>("%UiMask").MouseFilter = MouseFilterEnum.Stop;
|
||||
}
|
||||
public void MenuClosedEnableInteraction()
|
||||
{
|
||||
GetNode<Control>("%UiMask").MouseFilter = MouseFilterEnum.Ignore;
|
||||
}
|
||||
public void ImportGame(string 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
var r = FindRow(targetRowId);
|
||||
if (r is null)
|
||||
throw new Exception($"row {r.RowId} not found");
|
||||
row r;
|
||||
if (targetRowId == "_")
|
||||
r = null;
|
||||
else
|
||||
{
|
||||
r = FindRow(targetRowId);
|
||||
if (r is null)
|
||||
throw new Exception($"row {r.RowId} not found");
|
||||
}
|
||||
var c = ClaimCard(cardId);
|
||||
if (c is null)
|
||||
throw new Exception($"card {c.CardId} not found");
|
||||
r.AddCard(c, toIndex);
|
||||
if (r is not null)
|
||||
r.AddCard(c, toIndex);
|
||||
else
|
||||
AddUnassignedCard(c);
|
||||
}
|
||||
public void MoveRow(string rowId, int toIndex)
|
||||
{
|
||||
@@ -214,8 +286,7 @@ public partial class game : Control
|
||||
}
|
||||
public void CreateRow(Color? color = null, string title = null)
|
||||
{
|
||||
var scn = GD.Load<PackedScene>("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)
|
||||
|
||||
43
game.tscn
43
game.tscn
@@ -1,11 +1,14 @@
|
||||
[gd_scene load_steps=7 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"]
|
||||
[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"]
|
||||
[ext_resource type="PackedScene" uid="uid://kyaqu004qlcq" path="res://create_menu_popup.tscn" id="8_f2hb2"]
|
||||
|
||||
[node name="Game" type="Control"]
|
||||
layout_mode = 3
|
||||
@@ -27,6 +30,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 +83,38 @@ 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="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"]
|
||||
|
||||
@@ -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)
|
||||
]
|
||||
}
|
||||
|
||||
20
row.cs
20
row.cs
@@ -98,9 +98,8 @@ 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<card>()
|
||||
?? throw new Exception("invalid drag data");
|
||||
var g = this.GetParentOfType<game>()
|
||||
@@ -128,6 +127,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.Obj is row;
|
||||
}
|
||||
public override void _DropData(Vector2 atPosition, Variant data)
|
||||
{
|
||||
var r = data.As<row>()
|
||||
?? 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)
|
||||
{
|
||||
|
||||
6
row.tscn
6
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
|
||||
|
||||
53
row_edit_popup.cs
Normal file
53
row_edit_popup.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
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>("%ColorPickerButton").Color = r.RowColor;
|
||||
GetNode<TextEdit>("%RowTextEdit").Text = r.RowText;
|
||||
this.GetParentOfType<game>().MenuOpenDisableInteraction();
|
||||
Show();
|
||||
}
|
||||
public void OkClicked()
|
||||
{
|
||||
EditingRow.RowColor = GetNode<ColorPickerButton>("%ColorPickerButton").Color;
|
||||
EditingRow.RowText = GetNode<TextEdit>("%RowTextEdit").Text;
|
||||
Reset();
|
||||
}
|
||||
public void CancelClicked()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
public void Reset()
|
||||
{
|
||||
Hide();
|
||||
GetNode<ColorPickerButton>("%ColorPickerButton").Color = DefaultColor;
|
||||
GetNode<TextEdit>("%RowTextEdit").Text = "";
|
||||
EditingRow = null;
|
||||
this.GetParentOfType<game>().MenuClosedEnableInteraction();
|
||||
}
|
||||
public void DeleteRow()
|
||||
{
|
||||
EditingRow.QueueFree();
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
75
row_edit_popup.tscn
Normal file
75
row_edit_popup.tscn
Normal file
@@ -0,0 +1,75 @@
|
||||
[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")
|
||||
|
||||
[node name="RowEditMarginContainer" type="MarginContainer" parent="."]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_right = 5
|
||||
theme_override_constants/margin_bottom = 5
|
||||
|
||||
[node name="RowEditOuterVbox" type="VSplitContainer" parent="RowEditMarginContainer"]
|
||||
layout_mode = 2
|
||||
dragger_visibility = 1
|
||||
|
||||
[node name="RowEditInnerVbox" type="VSplitContainer" parent="RowEditMarginContainer/RowEditOuterVbox"]
|
||||
layout_mode = 2
|
||||
dragger_visibility = 1
|
||||
|
||||
[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
|
||||
size_flags_horizontal = 0
|
||||
size_flags_vertical = 0
|
||||
edit_alpha = false
|
||||
|
||||
[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="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/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/RowEditOuterVbox/RowEditButtonContainer"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(100, 0)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 8
|
||||
text = "OK"
|
||||
|
||||
[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"]
|
||||
@@ -19,6 +19,10 @@ public partial class settings_popup : PanelContainer
|
||||
public string Channel => GetNode<LineEdit>("%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<game>().MenuOpenDisableInteraction();
|
||||
Show();
|
||||
}
|
||||
public void ClosePopup()
|
||||
{
|
||||
Hide();
|
||||
this.GetParentOfType<game>().MenuClosedEnableInteraction();
|
||||
}
|
||||
public void _on_cancel_button_pressed()
|
||||
{
|
||||
@@ -57,6 +63,13 @@ public partial class settings_popup : PanelContainer
|
||||
}
|
||||
public void _on_ok_button_pressed()
|
||||
{
|
||||
var settings = GetNode<Settings>("/root/Settings");
|
||||
settings.AllowModerators = GetNode<CheckBox>("%CheckBoxModerator").ButtonPressed;
|
||||
settings.Trigger = GetNode<LineEdit>("%CommandEdit").Text;
|
||||
settings.SetUserLists(GetNode<TextEdit>("%WhiteListEdit").Text.Split('\n',
|
||||
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries),
|
||||
GetNode<TextEdit>("%BlackListEdit").Text.Split('\n',
|
||||
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries));
|
||||
GetNode<ConfigStretchContainer>("%ConfigStretchContainer").Apply();
|
||||
ClosePopup();
|
||||
}
|
||||
@@ -96,16 +109,11 @@ public partial class settings_popup : PanelContainer
|
||||
}
|
||||
private void SuccessfulConnection()
|
||||
{
|
||||
GD.Print(nameof(SuccessfulConnection));
|
||||
var tcw = GetNode<TwitchChatWatcher>("/root/TwitchChatWatcher");
|
||||
if (tcw.State != System.Net.WebSockets.WebSocketState.Open)
|
||||
throw new Exception("Websocket closed");
|
||||
var settings = GetNode<Settings>("/root/Settings");
|
||||
settings.AllowModerators = GetNode<CheckBox>("%CheckBoxModerator").ButtonPressed;
|
||||
settings.Command = GetNode<LineEdit>("%CommandEdit").Text;
|
||||
settings.SetUserLists(GetNode<TextEdit>("%WhiteListEdit").Text.Split('\n',
|
||||
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries),
|
||||
GetNode<TextEdit>("%BlackListEdit").Text.Split('\n',
|
||||
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries));
|
||||
GetNode<BaseButton>("%JoinChannelButton").Disabled = false;
|
||||
UnlockPopup();
|
||||
}
|
||||
private void SocketConnected()
|
||||
@@ -116,4 +124,16 @@ public partial class settings_popup : PanelContainer
|
||||
{
|
||||
GetNode<BaseButton>("%ConnectButton").Disabled = false;
|
||||
}
|
||||
private void ImportFileSelected(string filename)
|
||||
{
|
||||
EmitSignal(SignalName.ImportSelected, filename);
|
||||
}
|
||||
private void ExportFileSelected(string filename)
|
||||
{
|
||||
ExportSettings es = new()
|
||||
{
|
||||
ScaleImages = GetNode<BaseButton>("%ExportCompressPicturesButton").ButtonPressed,
|
||||
};
|
||||
EmitSignal(SignalName.ExportSelected, filename, Variant.From(es));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -108,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"]
|
||||
@@ -155,6 +160,67 @@ 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
|
||||
button_pressed = true
|
||||
text = "Scale Images"
|
||||
|
||||
[node name="ButtonContainer" type="HBoxContainer" parent="SettingsDivider"]
|
||||
layout_mode = 2
|
||||
alignment = 2
|
||||
@@ -176,5 +242,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"]
|
||||
|
||||
Reference in New Issue
Block a user