mirror of
https://codeberg.org/Ikatono/TierMaker.git
synced 2025-10-28 20:45:35 -05:00
basically function but needs a lot of refinement
This commit is contained in:
31
CardEditImageBox.cs
Normal file
31
CardEditImageBox.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using Godot;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public partial class CardEditImageBox : 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)
|
||||||
|
{
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
CardImagePicker.cs
Normal file
16
CardImagePicker.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using Godot;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public partial class CardImagePicker : FileDialog
|
||||||
|
{
|
||||||
|
// Called when the node enters the scene tree for the first time.
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
// FileSelected += GetNode<card_edit_popup>("/game/CardEditPopup").FileSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
public override void _Process(double delta)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
49
Command.cs
49
Command.cs
@@ -105,42 +105,19 @@ public static class CommandTypeHelper
|
|||||||
// return (CommandType)ct;
|
// return (CommandType)ct;
|
||||||
// return null;
|
// return null;
|
||||||
var c = commandType.ToLower();
|
var c = commandType.ToLower();
|
||||||
if (c == "movecard")
|
return c switch
|
||||||
{
|
{
|
||||||
return CommandType.MoveCard;
|
"movecard" => CommandType.MoveCard,
|
||||||
}
|
"moverow" => CommandType.MoveRow,
|
||||||
else if (c == "moverow")
|
"deletecard" or "deletecards" => CommandType.DeleteCard,
|
||||||
{
|
"deleterow" => CommandType.DeleteRow,
|
||||||
return CommandType.MoveRow;
|
"createcard" or "addcard" => CommandType.CreateCard,
|
||||||
}
|
"createrow" or "addrow" => CommandType.CreateRow,
|
||||||
else if (c == "deletecard")
|
"renamecard" => CommandType.RenameCard,
|
||||||
{
|
"renamerow" => CommandType.RenameRow,
|
||||||
return CommandType.DeleteCard;
|
"recolorrow" or "changerowcolor" => CommandType.RecolorRow,
|
||||||
}
|
"changecardimage" or "changecardpicture" => CommandType.ChangeCardImage,
|
||||||
else if (c == "createcard")
|
_ => null,
|
||||||
{
|
};
|
||||||
return CommandType.CreateCard;
|
|
||||||
}
|
|
||||||
else if (c == "createrow")
|
|
||||||
{
|
|
||||||
return CommandType.CreateRow;
|
|
||||||
}
|
|
||||||
else if (c == "renamecard")
|
|
||||||
{
|
|
||||||
return CommandType.RenameCard;
|
|
||||||
}
|
|
||||||
else if (c == "renamerow")
|
|
||||||
{
|
|
||||||
return CommandType.RenameRow;
|
|
||||||
}
|
|
||||||
else if (c == "recolorrow")
|
|
||||||
{
|
|
||||||
return CommandType.RecolorRow;
|
|
||||||
}
|
|
||||||
else if (c == "changecardimage")
|
|
||||||
{
|
|
||||||
return CommandType.ChangeCardImage;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,20 @@
|
|||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
public partial class CommandHandler : Node
|
public partial class CommandHandler : Node
|
||||||
{
|
{
|
||||||
private Settings Settings { get; set; }
|
private Settings Settings { get; set; }
|
||||||
private game Game { get; set; }
|
private game Game { get; set; }
|
||||||
private readonly List<Task> TaskQueue = new();
|
private readonly ConcurrentQueue<Action> ActionQueue = new();
|
||||||
private System.Net.Http.HttpClient _Client = null;
|
private System.Net.Http.HttpClient _Client = null;
|
||||||
private System.Net.Http.HttpClient Client
|
private System.Net.Http.HttpClient Client
|
||||||
{ get
|
{ get
|
||||||
@@ -21,34 +23,42 @@ public partial class CommandHandler : Node
|
|||||||
return _Client;
|
return _Client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private defer_manager _Deferer = null;
|
||||||
|
private defer_manager Deferer
|
||||||
|
{ get
|
||||||
|
{
|
||||||
|
_Deferer ??= GetNode<defer_manager>("/root/DeferManager");
|
||||||
|
return _Deferer;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Called when the node enters the scene tree for the first time.
|
// Called when the node enters the scene tree for the first time.
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
Settings = GetNode<Settings>("/root/Settings");
|
Settings = GetNode<Settings>("/root/Settings");
|
||||||
Game = GetNode<game>("/root/Game");
|
Game = GetNode<game>("/root/Game");
|
||||||
|
GetNode<TwitchChatWatcher>("/root/TwitchChatWatcher").IncomingCommand
|
||||||
|
+= IncomingCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
{
|
{
|
||||||
//delete/cleanup one finished task per frame
|
while (ActionQueue.TryDequeue(out Action t))
|
||||||
//currently just logs errors
|
|
||||||
var t = TaskQueue.FirstOrDefault(t => t.IsCompleted, null);
|
|
||||||
if (t is not null)
|
|
||||||
{
|
{
|
||||||
if (t.Exception is not null)
|
t?.Invoke();
|
||||||
GD.PrintErr(t.Exception);
|
|
||||||
TaskQueue.Remove(t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void IncomingCommand(Command command)
|
private void IncomingCommand(Command command)
|
||||||
{
|
{
|
||||||
|
GD.Print("Received command");
|
||||||
if (!Settings.IsUserAuthorized(command.User, command.IsStreamer,
|
if (!Settings.IsUserAuthorized(command.User, command.IsStreamer,
|
||||||
command.IsModerator))
|
command.IsModerator))
|
||||||
return;
|
return;
|
||||||
|
GD.Print($"User {command.User} is authorized");
|
||||||
var baseArgs = command.GetArgs();
|
var baseArgs = command.GetArgs();
|
||||||
var type = CommandTypeHelper.ParseCommand(baseArgs.Pop());
|
var type = CommandTypeHelper.ParseCommand(baseArgs.Pop());
|
||||||
|
GD.Print($"Command type: {type}");
|
||||||
var args = baseArgs.DuplicateAtState();
|
var args = baseArgs.DuplicateAtState();
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@@ -65,7 +75,9 @@ public partial class CommandHandler : Node
|
|||||||
DeleteRow(args);
|
DeleteRow(args);
|
||||||
break;
|
break;
|
||||||
case CommandType.CreateCard:
|
case CommandType.CreateCard:
|
||||||
TaskQueue.Add(Task.Run(() => CreateCard(args)));
|
Task.Run(async () => await CreateCard(args))
|
||||||
|
.ContinueWith(t => GD.PrintErr(t.Exception.StackTrace),
|
||||||
|
TaskContinuationOptions.OnlyOnFaulted);
|
||||||
break;
|
break;
|
||||||
case CommandType.CreateRow:
|
case CommandType.CreateRow:
|
||||||
CreateRow(args);
|
CreateRow(args);
|
||||||
@@ -80,10 +92,12 @@ public partial class CommandHandler : Node
|
|||||||
RecolorRow(args);
|
RecolorRow(args);
|
||||||
break;
|
break;
|
||||||
case CommandType.ChangeCardImage:
|
case CommandType.ChangeCardImage:
|
||||||
TaskQueue.Add(Task.Run(() => ChangeCardImage(args)));
|
Task.Run(async () => await ChangeCardImage(args))
|
||||||
|
.ContinueWith(t => GD.PushError(t.Exception.InnerException.StackTrace),
|
||||||
|
TaskContinuationOptions.OnlyOnFaulted);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception();
|
throw new Exception("invalid command type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,10 +134,14 @@ public partial class CommandHandler : Node
|
|||||||
}
|
}
|
||||||
private async Task CreateCard(CommandArguments args)
|
private async Task CreateCard(CommandArguments args)
|
||||||
{
|
{
|
||||||
var title = args.Pop();
|
|
||||||
var url = args.Pop();
|
var url = args.Pop();
|
||||||
Image img = await ImageFromUrl(url);
|
var title = args.Remaining();
|
||||||
Game.CreateCard(title, img);
|
ImageWithMetadata img;
|
||||||
|
if (!string.IsNullOrWhiteSpace(url) && url != "_")
|
||||||
|
img = await ImageFromUrl(url);
|
||||||
|
else
|
||||||
|
img = null;
|
||||||
|
await Deferer.DeferAsync(() => Game.CreateCard(title, img));
|
||||||
}
|
}
|
||||||
private void CreateRow(CommandArguments args)
|
private void CreateRow(CommandArguments args)
|
||||||
{
|
{
|
||||||
@@ -152,7 +170,8 @@ public partial class CommandHandler : Node
|
|||||||
var rowId = args.Pop();
|
var rowId = args.Pop();
|
||||||
var colorStr = args.Pop();
|
var colorStr = args.Pop();
|
||||||
var color = Color.FromString(colorStr, new Color(0, 0, 0, 0));
|
var color = Color.FromString(colorStr, new Color(0, 0, 0, 0));
|
||||||
if (color == 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}");
|
throw new Exception($"invalid color {colorStr}");
|
||||||
Game.RecolorRow(rowId, color);
|
Game.RecolorRow(rowId, color);
|
||||||
}
|
}
|
||||||
@@ -160,18 +179,38 @@ public partial class CommandHandler : Node
|
|||||||
{
|
{
|
||||||
var cardId = args.Pop();
|
var cardId = args.Pop();
|
||||||
var img = await ImageFromUrl(args.Pop());
|
var img = await ImageFromUrl(args.Pop());
|
||||||
Game.ChangeCardImage(cardId, img);
|
await Deferer.DeferAsync(() => Game.ChangeCardImage(cardId, img));
|
||||||
|
// Game.ChangeCardImage(cardId, img);
|
||||||
}
|
}
|
||||||
private async Task<Image> ImageFromUrl(string url)
|
private async Task<ImageWithMetadata> ImageFromUrl(string url)
|
||||||
{
|
{
|
||||||
|
StretchMode mode = StretchMode.Unspecified;
|
||||||
|
if (url.Contains('|'))
|
||||||
|
{
|
||||||
|
var spl = url.Split('|', 2);
|
||||||
|
url = spl[0];
|
||||||
|
mode = spl[1].ToLower() switch
|
||||||
|
{
|
||||||
|
"unspecified" => StretchMode.Unspecified,
|
||||||
|
"fit" => StretchMode.Fit,
|
||||||
|
"stretch" => StretchMode.Stretch,
|
||||||
|
"crop" => StretchMode.Crop,
|
||||||
|
_ => throw new Exception($"Unrecognized {nameof(StretchMode)}"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
GD.Print($"Stretch mode: {mode}");
|
||||||
var uri = new Uri(url);
|
var uri = new Uri(url);
|
||||||
|
GD.Print("Starting image download");
|
||||||
var resp = await Client.GetAsync(uri);
|
var resp = await Client.GetAsync(uri);
|
||||||
if (!resp.IsSuccessStatusCode)
|
if (!resp.IsSuccessStatusCode)
|
||||||
return null;
|
throw new Exception("Failed to download image");
|
||||||
|
GD.Print("Downloaded image successfully");
|
||||||
Image img = new();
|
Image img = new();
|
||||||
var arr = await resp.Content.ReadAsByteArrayAsync();
|
var arr = await resp.Content.ReadAsByteArrayAsync();
|
||||||
|
var ext = Path.GetExtension(uri.AbsolutePath).TrimStart('.').ToLower();
|
||||||
|
GD.Print($"Image extension: {ext}");
|
||||||
//TODO detect images by header rather than extension
|
//TODO detect images by header rather than extension
|
||||||
switch (Path.GetExtension(uri.AbsolutePath).ToLower())
|
switch (ext)
|
||||||
{
|
{
|
||||||
case "png":
|
case "png":
|
||||||
img.LoadPngFromBuffer(arr);
|
img.LoadPngFromBuffer(arr);
|
||||||
@@ -189,7 +228,8 @@ public partial class CommandHandler : Node
|
|||||||
default:
|
default:
|
||||||
throw new Exception("unrecognized filetype");
|
throw new Exception("unrecognized filetype");
|
||||||
}
|
}
|
||||||
return img;
|
GD.Print($"Loaded picture {img}");
|
||||||
|
return new ImageWithMetadata(img, mode);
|
||||||
}
|
}
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
// using System.Collections.Generic;
|
|
||||||
|
|
||||||
// public static class CommandParser
|
|
||||||
// {
|
|
||||||
// public static List<string> SplitString(string s)
|
|
||||||
// {
|
|
||||||
// List<string> l = new();
|
|
||||||
// bool quoted = false;
|
|
||||||
// bool escaped = false;
|
|
||||||
// bool trimming = true;
|
|
||||||
// string current = "";
|
|
||||||
// foreach (char c in s)
|
|
||||||
// {
|
|
||||||
// switch (c)
|
|
||||||
// {
|
|
||||||
// case '\\':
|
|
||||||
// if (escaped)
|
|
||||||
// current += '\\';
|
|
||||||
// escaped = !escaped;
|
|
||||||
// break;
|
|
||||||
// case '"':
|
|
||||||
// if (escaped)
|
|
||||||
// {
|
|
||||||
// current += '"';
|
|
||||||
// escaped = false;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// if (quoted)
|
|
||||||
// {
|
|
||||||
// quoted = false;
|
|
||||||
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// case
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
54
ConfigStretchContainer.cs
Normal file
54
ConfigStretchContainer.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
using Godot;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public partial class ConfigStretchContainer : VBoxContainer
|
||||||
|
{
|
||||||
|
private Settings _Settings;
|
||||||
|
private Settings Settings
|
||||||
|
{ get
|
||||||
|
{
|
||||||
|
_Settings ??= GetNode<Settings>("/root/Settings");
|
||||||
|
return _Settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 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 LoadButtonState()
|
||||||
|
{
|
||||||
|
switch (Settings.StretchMode)
|
||||||
|
{
|
||||||
|
case StretchMode.Fit:
|
||||||
|
GetNode<BaseButton>("%ConfigStretchFitButton").ButtonPressed = true;
|
||||||
|
break;
|
||||||
|
case StretchMode.Crop:
|
||||||
|
GetNode<BaseButton>("%ConfigStretchCropButton").ButtonPressed = true;
|
||||||
|
break;
|
||||||
|
case StretchMode.Stretch:
|
||||||
|
GetNode<BaseButton>("%ConfigStretchStretchButton").ButtonPressed = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception($"Unrecognized {nameof(StretchMode)} {(int)Settings.StretchMode}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public StretchMode GetStretchMode()
|
||||||
|
{
|
||||||
|
if (GetNode<BaseButton>("%ConfigStretchFitButton").ButtonPressed)
|
||||||
|
return StretchMode.Fit;
|
||||||
|
else if (GetNode<BaseButton>("%ConfigStretchCropButton").ButtonPressed)
|
||||||
|
return StretchMode.Crop;
|
||||||
|
else if (GetNode<BaseButton>("%ConfigStretchStretchButton").ButtonPressed)
|
||||||
|
return StretchMode.Stretch;
|
||||||
|
throw new Exception($"No {nameof(StretchMode)} buttons pressed");
|
||||||
|
}
|
||||||
|
public void OkClicked()
|
||||||
|
{
|
||||||
|
Settings.StretchMode = GetStretchMode();
|
||||||
|
}
|
||||||
|
}
|
||||||
39
ImageWithMetadata.cs
Normal file
39
ImageWithMetadata.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Data.Common;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
public record class ImageWithMetadata
|
||||||
|
{
|
||||||
|
public Image Image;
|
||||||
|
public StretchMode StretchMode;
|
||||||
|
public ImageWithMetadata(Image image)
|
||||||
|
{
|
||||||
|
Image = image;
|
||||||
|
StretchMode = StretchMode.Unspecified;
|
||||||
|
}
|
||||||
|
public ImageWithMetadata(Image image, StretchMode stretchMode)
|
||||||
|
: this(image)
|
||||||
|
{
|
||||||
|
StretchMode = stretchMode;
|
||||||
|
}
|
||||||
|
// public static implicit operator Image(ImageWithMetadata iwm)
|
||||||
|
// => iwm.Image;
|
||||||
|
// public static implicit operator ImageWithMetadata(Image image)
|
||||||
|
// => new(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum StretchMode
|
||||||
|
{
|
||||||
|
Unspecified,
|
||||||
|
/// <summary>
|
||||||
|
/// Fit to either the width or height of the card
|
||||||
|
/// </summary>
|
||||||
|
Fit,
|
||||||
|
/// <summary>
|
||||||
|
/// Stretch the image to fill the card
|
||||||
|
/// </summary>
|
||||||
|
Stretch,
|
||||||
|
/// <summary>
|
||||||
|
/// Crop image to fit card (maintain center)
|
||||||
|
/// </summary>
|
||||||
|
Crop,
|
||||||
|
}
|
||||||
@@ -3,8 +3,16 @@ using System;
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
public partial class PictureDropHandler : Control
|
public partial class PictureDropHandler : Node
|
||||||
{
|
{
|
||||||
|
private Settings _Settings;
|
||||||
|
private Settings Settings
|
||||||
|
{ get
|
||||||
|
{
|
||||||
|
_Settings ??= GetNode<Settings>("/root/Settings");
|
||||||
|
return _Settings;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Called when the node enters the scene tree for the first time.
|
// Called when the node enters the scene tree for the first time.
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
@@ -28,6 +36,7 @@ public partial class PictureDropHandler : Control
|
|||||||
continue;
|
continue;
|
||||||
var c = card.MakeCard(GetTree());
|
var c = card.MakeCard(GetTree());
|
||||||
c.SetImage(tex);
|
c.SetImage(tex);
|
||||||
|
c.SetStretchMode(Settings.StretchMode);
|
||||||
g.AddUnassignedCard(c);
|
g.AddUnassignedCard(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
Settings.cs
12
Settings.cs
@@ -1,13 +1,20 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
public partial class Settings : Node
|
public partial class Settings : Node
|
||||||
{
|
{
|
||||||
|
[Export]
|
||||||
public bool AllowStreamer { get; set; }
|
public bool AllowStreamer { get; set; }
|
||||||
|
[Export]
|
||||||
public bool AllowModerators { get; set; }
|
public bool AllowModerators { get; set; }
|
||||||
|
[Export]
|
||||||
|
public string Command { get; set; }
|
||||||
public List<string> UserWhitelist { get; } = new();
|
public List<string> UserWhitelist { get; } = new();
|
||||||
public List<string> UserBlacklist { get; } = new();
|
public List<string> UserBlacklist { get; } = new();
|
||||||
public Vector2 CardSize { get; private set; }
|
public Vector2 CardSize { get; private set; }
|
||||||
|
[Export]
|
||||||
|
public StretchMode StretchMode { get; set; } = StretchMode.Fit;
|
||||||
|
|
||||||
[Signal]
|
[Signal]
|
||||||
public delegate void ChangeCardSizeEventHandler(Vector2 size);
|
public delegate void ChangeCardSizeEventHandler(Vector2 size);
|
||||||
@@ -19,6 +26,7 @@ public partial class Settings : Node
|
|||||||
}
|
}
|
||||||
public bool IsUserAuthorized(string user, bool isStreamer = false, bool isModerator = false)
|
public bool IsUserAuthorized(string user, bool isStreamer = false, bool isModerator = false)
|
||||||
{
|
{
|
||||||
|
user = user.ToLower();
|
||||||
if (UserBlacklist.Contains(user))
|
if (UserBlacklist.Contains(user))
|
||||||
return false;
|
return false;
|
||||||
if (UserWhitelist.Contains(user))
|
if (UserWhitelist.Contains(user))
|
||||||
@@ -32,8 +40,8 @@ public partial class Settings : Node
|
|||||||
public void SetUserLists(IEnumerable<string> white, IEnumerable<string> black)
|
public void SetUserLists(IEnumerable<string> white, IEnumerable<string> black)
|
||||||
{
|
{
|
||||||
UserWhitelist.Clear();
|
UserWhitelist.Clear();
|
||||||
UserWhitelist.AddRange(white);
|
UserWhitelist.AddRange(white.Select(s => s.ToLower()));
|
||||||
UserBlacklist.Clear();
|
UserBlacklist.Clear();
|
||||||
UserBlacklist.AddRange(black);
|
UserBlacklist.AddRange(black.Select(s => s.ToLower()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,22 +15,35 @@ public partial class TwitchChatWatcher : Node
|
|||||||
private readonly CancellationTokenSource TokenSource = new();
|
private readonly CancellationTokenSource TokenSource = new();
|
||||||
public CancellationToken Token => TokenSource.Token;
|
public CancellationToken Token => TokenSource.Token;
|
||||||
private CommandHandler CommandHandler { get; set; }
|
private CommandHandler CommandHandler { get; set; }
|
||||||
|
public WebSocketState State => Socket.State;
|
||||||
|
[Export]
|
||||||
|
public bool PrintAllIncoming { get; set; }
|
||||||
|
private Settings Settings;
|
||||||
|
|
||||||
[Signal]
|
[Signal]
|
||||||
public delegate void IncomingCommandEventHandler(Command command);
|
public delegate void IncomingCommandEventHandler(Command command);
|
||||||
// Called when the node enters the scene tree for the first time.
|
// Called when the node enters the scene tree for the first time.
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
CommandHandler = GetNode<CommandHandler>("/root/CommandHandler");
|
Settings = GetNode<Settings>("/root/Settings")
|
||||||
|
?? throw new Exception($"{nameof(Settings)} node not found");
|
||||||
|
CommandHandler = GetNode<CommandHandler>("/root/CommandHandler")
|
||||||
|
?? throw new Exception($"{nameof(Command)} not found");
|
||||||
}
|
}
|
||||||
|
private readonly ConcurrentQueue<string> PrintQueue = new();
|
||||||
|
private readonly ConcurrentQueue<string> ErrorQueue = new();
|
||||||
|
|
||||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
{
|
{
|
||||||
|
if (PrintQueue.TryDequeue(out string s))
|
||||||
|
GD.Print(s);
|
||||||
|
if (ErrorQueue.TryDequeue(out string e))
|
||||||
|
GD.PrintErr(e);
|
||||||
}
|
}
|
||||||
public async Task ConnectAsync()
|
public async Task ConnectAsync()
|
||||||
{
|
{
|
||||||
|
GD.Print("Connecting");
|
||||||
if (Socket.State == WebSocketState.Open)
|
if (Socket.State == WebSocketState.Open)
|
||||||
return;
|
return;
|
||||||
await Socket.ConnectAsync(new Uri("wss://irc-ws.chat.twitch.tv:443"), Token);
|
await Socket.ConnectAsync(new Uri("wss://irc-ws.chat.twitch.tv:443"), Token);
|
||||||
@@ -40,15 +53,22 @@ public partial class TwitchChatWatcher : Node
|
|||||||
}
|
}
|
||||||
public async Task Authenticate(string user = null, string pass = null)
|
public async Task Authenticate(string user = null, string pass = null)
|
||||||
{
|
{
|
||||||
|
GD.Print("Authenticating");
|
||||||
user ??= $"justinfan{Random.Shared.NextInt64(10000):D4}";
|
user ??= $"justinfan{Random.Shared.NextInt64(10000):D4}";
|
||||||
pass ??= "pass";
|
pass ??= "pass";
|
||||||
await SendMessageAsync(TwitchChatMessageType.PASS, parameters: new string[] { pass });
|
await SendMessageAsync(TwitchChatMessageType.PASS, parameters: new string[] { pass });
|
||||||
await SendMessageAsync(TwitchChatMessageType.NICK, parameters: new string[] { user });
|
await SendMessageAsync(TwitchChatMessageType.NICK, parameters: new string[] { user });
|
||||||
}
|
}
|
||||||
|
public async Task RequestTags()
|
||||||
|
{
|
||||||
|
await SendMessageAsync("CAP REQ :twitch.tv/tags");
|
||||||
|
}
|
||||||
public async Task JoinChannel(string channel)
|
public async Task JoinChannel(string channel)
|
||||||
{
|
{
|
||||||
|
GD.Print("Joining channel");
|
||||||
channel = channel.TrimStart('#');
|
channel = channel.TrimStart('#');
|
||||||
await SendMessageAsync(TwitchChatMessageType.JOIN, parameters: new string[] {"#" + channel});
|
await SendMessageAsync(TwitchChatMessageType.JOIN,
|
||||||
|
parameters: new string[] {"#" + channel});
|
||||||
}
|
}
|
||||||
public async Task SendMessageAsync(string message)
|
public async Task SendMessageAsync(string message)
|
||||||
{
|
{
|
||||||
@@ -58,7 +78,7 @@ public partial class TwitchChatWatcher : Node
|
|||||||
public async Task SendMessageAsync(TwitchChatMessageType command, IEnumerable<string> parameters = null,
|
public async Task SendMessageAsync(TwitchChatMessageType command, IEnumerable<string> parameters = null,
|
||||||
IDictionary<string, string> tags = null, string prefix = null)
|
IDictionary<string, string> tags = null, string prefix = null)
|
||||||
{
|
{
|
||||||
string EscapeTagValue(string s)
|
static string EscapeTagValue(string s)
|
||||||
{
|
{
|
||||||
if (s is null)
|
if (s is null)
|
||||||
return "";
|
return "";
|
||||||
@@ -89,41 +109,103 @@ public partial class TwitchChatWatcher : Node
|
|||||||
}
|
}
|
||||||
await SendMessageAsync(message);
|
await SendMessageAsync(message);
|
||||||
}
|
}
|
||||||
|
private static ulong PacketCount;
|
||||||
private async Task GetPacketsTask()
|
private async Task GetPacketsTask()
|
||||||
{
|
{
|
||||||
var buffer = ArraySegment<byte>.Empty;
|
try
|
||||||
|
{
|
||||||
|
var arr = new byte[16 * 1024];
|
||||||
var stringData = "";
|
var stringData = "";
|
||||||
while (!Token.IsCancellationRequested)
|
while (!Token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
var res = await Socket.ReceiveAsync(buffer, Token);
|
var res = await Socket.ReceiveAsync(arr, Token);
|
||||||
if (Token.IsCancellationRequested)
|
if (Token.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
stringData += Encoding.UTF8.GetString(buffer);
|
if (Socket.State != WebSocketState.Open)
|
||||||
|
{
|
||||||
|
ErrorQueue.Enqueue("Socket closed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (res.Count == 0)
|
||||||
|
{
|
||||||
|
ErrorQueue.Enqueue("Empty packet received");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
PacketCount++;
|
||||||
|
PrintQueue.Enqueue($"Packet count: {PacketCount}");
|
||||||
|
stringData += Encoding.UTF8.GetString(arr, 0, res.Count);
|
||||||
|
//PrintQueue.Enqueue(stringData);
|
||||||
var lines = stringData.Split("\r\n", StringSplitOptions.TrimEntries);
|
var lines = stringData.Split("\r\n", StringSplitOptions.TrimEntries);
|
||||||
|
if (!lines.Any())
|
||||||
|
continue;
|
||||||
stringData = lines.Last();
|
stringData = lines.Last();
|
||||||
|
PrintQueue.Enqueue($"Line count: {lines.SkipLast(1).Count()}");
|
||||||
foreach (var line in lines.SkipLast(1))
|
foreach (var line in lines.SkipLast(1))
|
||||||
MessageStrings.Enqueue(line);
|
MessageStrings.Enqueue(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ErrorQueue.Enqueue(e.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (!Token.IsCancellationRequested)
|
||||||
|
ErrorQueue.Enqueue($"{nameof(GetPacketsTask)} exited without cancellation");
|
||||||
|
else
|
||||||
|
PrintQueue.Enqueue($"{nameof(GetPacketsTask)} cancelled and exited");
|
||||||
|
}
|
||||||
|
}
|
||||||
private readonly ConcurrentQueue<string> MessageStrings = new();
|
private readonly ConcurrentQueue<string> MessageStrings = new();
|
||||||
private void HandleMessages()
|
private async Task HandleMessages()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (!Token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
while (MessageStrings.TryDequeue(out string message))
|
while (MessageStrings.TryDequeue(out string message))
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(message))
|
||||||
|
continue;
|
||||||
|
PrintQueue.Enqueue(message);
|
||||||
|
// if (PrintAllIncoming)
|
||||||
|
// PrintQueue.Enqueue(message);
|
||||||
var tcm = TwitchChatMessage.Parse(message);
|
var tcm = TwitchChatMessage.Parse(message);
|
||||||
if (tcm.MessageType == TwitchChatMessageType.PING)
|
if (tcm.MessageType == TwitchChatMessageType.PING)
|
||||||
_ = SendPong(tcm);
|
_ = Task.Run(() => SendPong(tcm), Token);
|
||||||
else if (tcm is Privmsg p)
|
else if (tcm is Privmsg p)
|
||||||
{
|
{
|
||||||
EmitSignal(SignalName.IncomingCommand, new Command(p.DisplayName,
|
var com = Settings.Command;
|
||||||
false, p.Moderator, p.ChatMessage));
|
if (!p.ChatMessage.StartsWith(com))
|
||||||
|
continue;
|
||||||
|
var chat = p.ChatMessage;
|
||||||
|
chat = chat[com.Length..].TrimStart();
|
||||||
|
CallDeferred("emit_signal", SignalName.IncomingCommand,
|
||||||
|
new Command(p.DisplayName,
|
||||||
|
false, p.Moderator, chat));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await Task.Delay(50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ErrorQueue.Enqueue(e.ToString() + System.Environment.NewLine
|
||||||
|
+ e.StackTrace);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (!Token.IsCancellationRequested)
|
||||||
|
ErrorQueue.Enqueue($"{nameof(HandleMessages)} exited without cancellation");
|
||||||
|
else
|
||||||
|
ErrorQueue.Enqueue($"{nameof(HandleMessages)} cancelled and exited");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private async Task SendPong(TwitchChatMessage ping)
|
private async Task SendPong(TwitchChatMessage ping)
|
||||||
{
|
{
|
||||||
var pong = TwitchChatMessage.MakePong(ping);
|
var pong = TwitchChatMessage.MakePong(ping);
|
||||||
await SendMessageAsync(TwitchChatMessageType.PONG, ping.Parameters,
|
await SendMessageAsync(TwitchChatMessageType.PONG, ping.Parameters,
|
||||||
ping.MessageTags, ping.Prefix);
|
ping.MessageTags, ping.Prefix);
|
||||||
|
PrintQueue.Enqueue("Sent Pong");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
98
card.cs
98
card.cs
@@ -1,7 +1,6 @@
|
|||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
|
||||||
|
|
||||||
public partial class card : Control
|
public partial class card : Panel
|
||||||
{
|
{
|
||||||
private Settings Settings => GetNode<Settings>("/root/Settings");
|
private Settings Settings => GetNode<Settings>("/root/Settings");
|
||||||
[Export]
|
[Export]
|
||||||
@@ -18,7 +17,7 @@ public partial class card : Control
|
|||||||
}
|
}
|
||||||
private void PropogateCardName()
|
private void PropogateCardName()
|
||||||
{
|
{
|
||||||
GetNode<Label>("CardNameLabel").Text = _CardName;
|
GetNode<Label>("%CardNameLabel").Text = _CardName;
|
||||||
}
|
}
|
||||||
[Export]
|
[Export]
|
||||||
private string _CardId;
|
private string _CardId;
|
||||||
@@ -51,6 +50,55 @@ public partial class card : Control
|
|||||||
_Texture = null;
|
_Texture = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private StretchMode? _StretchMode = null;
|
||||||
|
public void SetStretchMode(StretchMode stretchMode)
|
||||||
|
{
|
||||||
|
_StretchMode = stretchMode;
|
||||||
|
if (IsNodeReady())
|
||||||
|
PropogateStretchMode();
|
||||||
|
}
|
||||||
|
public StretchMode GetStretchMode()
|
||||||
|
{
|
||||||
|
var n = GetNode<TextureRect>("%CardImage");
|
||||||
|
return (n.StretchMode, n.ExpandMode) switch
|
||||||
|
{
|
||||||
|
(TextureRect.StretchModeEnum.Scale,
|
||||||
|
TextureRect.ExpandModeEnum.IgnoreSize)
|
||||||
|
=> StretchMode.Stretch,
|
||||||
|
(TextureRect.StretchModeEnum.KeepAspectCovered,
|
||||||
|
TextureRect.ExpandModeEnum.IgnoreSize)
|
||||||
|
=> StretchMode.Crop,
|
||||||
|
(TextureRect.StretchModeEnum.KeepAspectCentered,
|
||||||
|
TextureRect.ExpandModeEnum.IgnoreSize)
|
||||||
|
=> StretchMode.Fit,
|
||||||
|
_ => StretchMode.Unspecified,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
private void PropogateStretchMode()
|
||||||
|
{
|
||||||
|
var ci = GetNode<TextureRect>("%CardImage");
|
||||||
|
switch (_StretchMode)
|
||||||
|
{
|
||||||
|
case null:
|
||||||
|
break;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
_StretchMode = null;
|
||||||
|
}
|
||||||
|
|
||||||
public Texture2D GetTexture()
|
public Texture2D GetTexture()
|
||||||
=> GetNode<TextureRect>("%CardImage").Texture;
|
=> GetNode<TextureRect>("%CardImage").Texture;
|
||||||
public Vector2 Center
|
public Vector2 Center
|
||||||
@@ -61,20 +109,21 @@ public partial class card : Control
|
|||||||
PropogateCardName();
|
PropogateCardName();
|
||||||
PropogateCardId();
|
PropogateCardId();
|
||||||
PropogateTexture();
|
PropogateTexture();
|
||||||
|
PropogateStretchMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
public override Variant _GetDragData(Vector2 atPosition)
|
public override Variant _GetDragData(Vector2 atPosition)
|
||||||
{
|
{
|
||||||
GD.Print($"starting to drag {CardId}");
|
GD.Print($"starting to drag {CardId}");
|
||||||
var prev = card_preview.MakePreview(this);
|
var prev = card_preview.MakePreview(this);
|
||||||
var prev_root = new Control();
|
var prev_root = new Control();
|
||||||
//prev.Position = atPosition;
|
|
||||||
prev.Position = prev.Size / -2;
|
|
||||||
prev_root.AddChild(prev);
|
prev_root.AddChild(prev);
|
||||||
|
prev.Position = prev.Size / -2;
|
||||||
SetDragPreview(prev_root);
|
SetDragPreview(prev_root);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -90,34 +139,17 @@ public partial class card : Control
|
|||||||
var node = GetNode<TextureRect>("%CardImage");
|
var node = GetNode<TextureRect>("%CardImage");
|
||||||
node.Texture = texture;
|
node.Texture = texture;
|
||||||
}
|
}
|
||||||
// private void HandleInput(InputEvent @event)
|
public override void _GuiInput(InputEvent @event)
|
||||||
// {
|
{
|
||||||
// if (@event is InputEventMouseButton iemb)
|
if (@event.IsActionPressed("LocationMenu"))
|
||||||
// {
|
{
|
||||||
// if (iemb.ButtonIndex == MouseButton.Left)
|
CardMenu();
|
||||||
// {
|
}
|
||||||
// if (iemb.Pressed)
|
}
|
||||||
// {
|
private void CardMenu()
|
||||||
// InputSingleton.Instance.ClickedOn = this;
|
{
|
||||||
// StartDrag();
|
this.GetParentOfType<game>().EditCardInMenu(this);
|
||||||
// }
|
}
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// InputSingleton.Instance.ClickedOn = null;
|
|
||||||
// StopDrag();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// private void StartDrag()
|
|
||||||
// {
|
|
||||||
|
|
||||||
// }
|
|
||||||
// private void StopDrag()
|
|
||||||
// {
|
|
||||||
|
|
||||||
// }
|
|
||||||
public static card MakeCard(SceneTree tree)
|
public static card MakeCard(SceneTree tree)
|
||||||
{
|
{
|
||||||
var scene = GD.Load<PackedScene>("res://card.tscn");
|
var scene = GD.Load<PackedScene>("res://card.tscn");
|
||||||
|
|||||||
28
card.tscn
28
card.tscn
@@ -13,18 +13,9 @@ outline_color = Color(0, 0, 0, 1)
|
|||||||
outline_size = 2
|
outline_size = 2
|
||||||
outline_color = Color(0, 0, 0, 1)
|
outline_color = Color(0, 0, 0, 1)
|
||||||
|
|
||||||
[node name="Card" type="Control" groups=["CardGroup"]]
|
[node name="Card" type="Panel" groups=["CardGroup"]]
|
||||||
custom_minimum_size = Vector2(200, 200)
|
|
||||||
layout_mode = 3
|
|
||||||
anchors_preset = 0
|
|
||||||
offset_right = 200.0
|
|
||||||
offset_bottom = 200.0
|
|
||||||
mouse_filter = 1
|
|
||||||
script = ExtResource("1_dysu7")
|
|
||||||
|
|
||||||
[node name="CardBackground" type="Panel" parent="."]
|
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 1
|
clip_contents = true
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
@@ -32,8 +23,9 @@ grow_horizontal = 2
|
|||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
mouse_filter = 1
|
mouse_filter = 1
|
||||||
theme_override_styles/panel = SubResource("StyleBoxFlat_ndhi0")
|
theme_override_styles/panel = SubResource("StyleBoxFlat_ndhi0")
|
||||||
|
script = ExtResource("1_dysu7")
|
||||||
|
|
||||||
[node name="CardImage" type="TextureRect" parent="CardBackground"]
|
[node name="CardImage" type="TextureRect" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
@@ -41,22 +33,23 @@ anchor_right = 1.0
|
|||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
expand_mode = 1
|
expand_mode = 1
|
||||||
stretch_mode = 5
|
stretch_mode = 5
|
||||||
|
|
||||||
[node name="CardNameLabel" type="Label" parent="."]
|
[node name="CardNameLabel" type="Label" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
z_index = 1
|
layout_mode = 1
|
||||||
layout_mode = 0
|
anchors_preset = 10
|
||||||
offset_right = 40.0
|
anchor_right = 1.0
|
||||||
offset_bottom = 23.0
|
offset_bottom = 23.0
|
||||||
mouse_filter = 1
|
grow_horizontal = 2
|
||||||
text = "Name"
|
text = "Name"
|
||||||
label_settings = SubResource("LabelSettings_ui6ue")
|
label_settings = SubResource("LabelSettings_ui6ue")
|
||||||
|
autowrap_mode = 3
|
||||||
|
|
||||||
[node name="CardIdLabel" type="Label" parent="."]
|
[node name="CardIdLabel" type="Label" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
z_index = 1
|
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 2
|
anchors_preset = 2
|
||||||
anchor_top = 1.0
|
anchor_top = 1.0
|
||||||
@@ -64,6 +57,5 @@ anchor_bottom = 1.0
|
|||||||
offset_top = -23.0
|
offset_top = -23.0
|
||||||
offset_right = 40.0
|
offset_right = 40.0
|
||||||
grow_vertical = 0
|
grow_vertical = 0
|
||||||
mouse_filter = 1
|
|
||||||
text = "ID"
|
text = "ID"
|
||||||
label_settings = SubResource("LabelSettings_gncft")
|
label_settings = SubResource("LabelSettings_gncft")
|
||||||
|
|||||||
130
card_edit_popup.cs
Normal file
130
card_edit_popup.cs
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
using Godot;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public partial class card_edit_popup : ConfirmationDialog
|
||||||
|
{
|
||||||
|
private LineEdit _TitleEdit;
|
||||||
|
public LineEdit TitleEdit
|
||||||
|
{ get
|
||||||
|
{
|
||||||
|
_TitleEdit ??= GetNode<LineEdit>("%TitleEdit");
|
||||||
|
return _TitleEdit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private TextureRect _ImageBox;
|
||||||
|
public TextureRect ImageBox
|
||||||
|
{ get
|
||||||
|
{
|
||||||
|
_ImageBox ??= GetNode<TextureRect>("%CardEditImageBox");
|
||||||
|
return _ImageBox;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
card EditingCard;
|
||||||
|
[Export]
|
||||||
|
private string Text
|
||||||
|
{
|
||||||
|
get => TitleEdit.Text;
|
||||||
|
set => TitleEdit.Text = value;
|
||||||
|
}
|
||||||
|
[Export]
|
||||||
|
private Texture2D Texture
|
||||||
|
{
|
||||||
|
get => ImageBox.Texture;
|
||||||
|
set => ImageBox.Texture = value;
|
||||||
|
}
|
||||||
|
// Called when the node enters the scene tree for the first time.
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
GetNode<BaseButton>("%StretchModeFitButton").ButtonGroup.Pressed
|
||||||
|
+= StetchModeChanged;
|
||||||
|
TitleEdit.TextSubmitted +=
|
||||||
|
(s) => GetOkButton().EmitSignal(Button.SignalName.Pressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
public override void _Process(double delta)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public void ActivateForCard(card c)
|
||||||
|
{
|
||||||
|
EditingCard = c;
|
||||||
|
Text = c.CardName;
|
||||||
|
Texture = c.GetTexture();
|
||||||
|
SetStretchModeButton(c.GetStretchMode());
|
||||||
|
Show();
|
||||||
|
}
|
||||||
|
public void OnVisibilityChange()
|
||||||
|
{
|
||||||
|
if (Visible)
|
||||||
|
{
|
||||||
|
TitleEdit.GrabFocus();
|
||||||
|
TitleEdit.SelectAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void SetStretchModeButton(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 = ImageBox;
|
||||||
|
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 void OkClicked()
|
||||||
|
{
|
||||||
|
EditingCard.CardName = Text;
|
||||||
|
EditingCard.SetTexture(Texture);
|
||||||
|
EditingCard.SetStretchMode(GetStretchMode());
|
||||||
|
// Hide();
|
||||||
|
}
|
||||||
|
public void CancelClicked()
|
||||||
|
{
|
||||||
|
// Hide();
|
||||||
|
}
|
||||||
|
public void FileSelected(string path)
|
||||||
|
{
|
||||||
|
Image image = new();
|
||||||
|
image.Load(path);
|
||||||
|
var texture = ImageTexture.CreateFromImage(image);
|
||||||
|
Texture = texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
97
card_edit_popup.tscn
Normal file
97
card_edit_popup.tscn
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
[gd_scene load_steps=6 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="PackedScene" uid="uid://bhlqt64wrhx83" path="res://card_image_picker.tscn" id="3_4k21m"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_nx8uj"]
|
||||||
|
|
||||||
|
[sub_resource type="ButtonGroup" id="ButtonGroup_t74v5"]
|
||||||
|
|
||||||
|
[node name="CardEditPopup" type="ConfirmationDialog"]
|
||||||
|
title = "Edit Card"
|
||||||
|
position = Vector2i(0, 36)
|
||||||
|
size = Vector2i(350, 320)
|
||||||
|
visible = true
|
||||||
|
unresizable = true
|
||||||
|
always_on_top = true
|
||||||
|
script = ExtResource("1_xxurr")
|
||||||
|
|
||||||
|
[node name="CardEditContainer" type="VBoxContainer" parent="."]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = 8.0
|
||||||
|
offset_top = 8.0
|
||||||
|
offset_right = 342.0
|
||||||
|
offset_bottom = 271.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="TitleContainer" type="HBoxContainer" parent="CardEditContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="TitleLabel" type="Label" parent="CardEditContainer/TitleContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Text"
|
||||||
|
|
||||||
|
[node name="TitleEdit" type="LineEdit" parent="CardEditContainer/TitleContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="CardDetailsContainer" type="HSplitContainer" parent="CardEditContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
split_offset = 6
|
||||||
|
dragger_visibility = 1
|
||||||
|
|
||||||
|
[node name="CardImageSelectContainer" type="PanelContainer" parent="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_nx8uj")
|
||||||
|
|
||||||
|
[node name="CardEditImageBox" type="TextureRect" parent="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("2_flth7")
|
||||||
|
|
||||||
|
[node name="ImageStretchButtonsContainer" type="VBoxContainer" parent="CardEditContainer/CardDetailsContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
alignment = 1
|
||||||
|
|
||||||
|
[node name="StretchModeLabel" type="Label" parent="CardEditContainer/CardDetailsContainer/ImageStretchButtonsContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = " Stretch Mode"
|
||||||
|
|
||||||
|
[node name="StretchModeFitButton" type="CheckBox" parent="CardEditContainer/CardDetailsContainer/ImageStretchButtonsContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
button_pressed = true
|
||||||
|
button_group = SubResource("ButtonGroup_t74v5")
|
||||||
|
text = "Fit"
|
||||||
|
|
||||||
|
[node name="StretchModeStretchButton" type="CheckBox" parent="CardEditContainer/CardDetailsContainer/ImageStretchButtonsContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
button_group = SubResource("ButtonGroup_t74v5")
|
||||||
|
text = "Stretch"
|
||||||
|
|
||||||
|
[node name="StretchModeCropButton" type="CheckBox" parent="CardEditContainer/CardDetailsContainer/ImageStretchButtonsContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
button_group = SubResource("ButtonGroup_t74v5")
|
||||||
|
text = "Crop"
|
||||||
|
|
||||||
|
[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="file_selected" from="CardImagePicker" to="." method="FileSelected"]
|
||||||
15
card_image_picker.tscn
Normal file
15
card_image_picker.tscn
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://bhlqt64wrhx83"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://CardImagePicker.cs" id="1_j0c8l"]
|
||||||
|
|
||||||
|
[node name="CardImagePicker" type="FileDialog"]
|
||||||
|
title = "Choose Picture"
|
||||||
|
size = Vector2i(312, 154)
|
||||||
|
ok_button_text = "Open"
|
||||||
|
dialog_hide_on_ok = true
|
||||||
|
mode_overrides_title = false
|
||||||
|
file_mode = 0
|
||||||
|
access = 2
|
||||||
|
filters = PackedStringArray("*.png, *.jpg, *.jpeg, *.webp, *.svg; Supported Images")
|
||||||
|
use_native_dialog = true
|
||||||
|
script = ExtResource("1_j0c8l")
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
public partial class card_preview : Control
|
public partial class card_preview : PanelContainer
|
||||||
{
|
{
|
||||||
[Export]
|
[Export]
|
||||||
private string _CardName;
|
private string _CardName;
|
||||||
@@ -39,7 +39,7 @@ public partial class card_preview : Control
|
|||||||
public void SetTexture(Texture2D texture)
|
public void SetTexture(Texture2D texture)
|
||||||
{
|
{
|
||||||
_Texture = texture;
|
_Texture = texture;
|
||||||
if (IsNodeReady())
|
// if (IsNodeReady())
|
||||||
PropogateTexture();
|
PropogateTexture();
|
||||||
}
|
}
|
||||||
private void PropogateTexture()
|
private void PropogateTexture()
|
||||||
@@ -55,6 +55,7 @@ public partial class card_preview : Control
|
|||||||
{
|
{
|
||||||
PropogateCardId();
|
PropogateCardId();
|
||||||
PropogateCardName();
|
PropogateCardName();
|
||||||
|
GD.Print(Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
@@ -75,13 +76,19 @@ public partial class card_preview : Control
|
|||||||
}
|
}
|
||||||
public static card_preview MakePreview(card c)
|
public static card_preview MakePreview(card c)
|
||||||
{
|
{
|
||||||
const float TRANSPARENCY = 0.25f;
|
const float TRANSPARENCY = 0.75f;
|
||||||
var scene = GD.Load<PackedScene>("res://card_preview.tscn");
|
var scene = GD.Load<PackedScene>("res://card_preview.tscn");
|
||||||
var prev = scene.Instantiate() as card_preview;
|
var prev = scene.Instantiate() as card_preview;
|
||||||
prev.CardName = c.CardName;
|
prev.CardName = c.CardName;
|
||||||
prev.CardId = c.CardId;
|
prev.CardId = c.CardId;
|
||||||
prev.SetTexture(c.GetTexture());
|
prev.SetTexture(c.GetTexture());
|
||||||
prev.Size = c.Size;
|
// prev.Size = c.Size;
|
||||||
|
var tr = prev.GetNode<TextureRect>("%CardPreviewImage");
|
||||||
|
tr.CustomMinimumSize = c.Size;
|
||||||
|
var ci = c.GetNode<TextureRect>("%CardImage");
|
||||||
|
tr.ExpandMode = ci.ExpandMode;
|
||||||
|
tr.StretchMode = ci.StretchMode;
|
||||||
|
prev.GetNode<Control>("%CardPreviewImage").CustomMinimumSize = c.Size;
|
||||||
prev.Scale = c.Scale;
|
prev.Scale = c.Scale;
|
||||||
prev.Modulate = new(1, 1, 1, TRANSPARENCY);
|
prev.Modulate = new(1, 1, 1, TRANSPARENCY);
|
||||||
return prev;
|
return prev;
|
||||||
|
|||||||
@@ -13,51 +13,36 @@ outline_color = Color(0, 0, 0, 1)
|
|||||||
outline_size = 2
|
outline_size = 2
|
||||||
outline_color = Color(0, 0, 0, 1)
|
outline_color = Color(0, 0, 0, 1)
|
||||||
|
|
||||||
[node name="CardPreview" type="Control" groups=["CardGroup"]]
|
[node name="CardPreview" type="PanelContainer"]
|
||||||
custom_minimum_size = Vector2(200, 200)
|
|
||||||
layout_mode = 3
|
|
||||||
anchors_preset = 0
|
|
||||||
offset_right = 200.0
|
|
||||||
offset_bottom = 200.0
|
|
||||||
script = ExtResource("1_o00ln")
|
|
||||||
|
|
||||||
[node name="CardPreviewBackground" type="Panel" parent="."]
|
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 1
|
clip_contents = true
|
||||||
anchors_preset = 15
|
offset_left = 20.0
|
||||||
anchor_right = 1.0
|
offset_top = 20.0
|
||||||
anchor_bottom = 1.0
|
offset_right = 20.0
|
||||||
|
offset_bottom = 20.0
|
||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
theme_override_styles/panel = SubResource("StyleBoxFlat_ndhi0")
|
theme_override_styles/panel = SubResource("StyleBoxFlat_ndhi0")
|
||||||
|
script = ExtResource("1_o00ln")
|
||||||
|
|
||||||
[node name="CardPreviewImage" type="TextureRect" parent="CardPreviewBackground"]
|
[node name="CardPreviewImage" type="TextureRect" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 1
|
layout_mode = 2
|
||||||
anchors_preset = 15
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
grow_horizontal = 2
|
|
||||||
grow_vertical = 2
|
|
||||||
expand_mode = 1
|
expand_mode = 1
|
||||||
stretch_mode = 5
|
stretch_mode = 5
|
||||||
|
|
||||||
[node name="CardPreviewNameLabel" type="Label" parent="."]
|
[node name="CardPreviewNameLabel" type="Label" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 0
|
layout_mode = 2
|
||||||
offset_right = 40.0
|
size_flags_vertical = 1
|
||||||
offset_bottom = 23.0
|
|
||||||
text = "Name"
|
text = "Name"
|
||||||
label_settings = SubResource("LabelSettings_ui6ue")
|
label_settings = SubResource("LabelSettings_ui6ue")
|
||||||
|
autowrap_mode = 3
|
||||||
|
|
||||||
[node name="CardPreviewIdLabel" type="Label" parent="."]
|
[node name="CardPreviewIdLabel" type="Label" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 1
|
layout_mode = 2
|
||||||
anchors_preset = 2
|
size_flags_vertical = 8
|
||||||
anchor_top = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
offset_top = -23.0
|
|
||||||
offset_right = 40.0
|
|
||||||
grow_vertical = 0
|
|
||||||
text = "ID"
|
text = "ID"
|
||||||
label_settings = SubResource("LabelSettings_gncft")
|
label_settings = SubResource("LabelSettings_gncft")
|
||||||
|
vertical_alignment = 2
|
||||||
|
|||||||
81
defer_manager.cs
Normal file
81
defer_manager.cs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
using Godot;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides defer-like behavior that's easier to work with in C#
|
||||||
|
/// </summary>
|
||||||
|
public partial class defer_manager : Node
|
||||||
|
{
|
||||||
|
// Called when the node enters the scene tree for the first time.
|
||||||
|
public override void _Ready()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
private readonly ConcurrentQueue<Action> ActionQueue = new();
|
||||||
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
public override void _Process(double delta)
|
||||||
|
{
|
||||||
|
while (ActionQueue.TryDequeue(out Action a))
|
||||||
|
{
|
||||||
|
a?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void DeferForget(Action action)
|
||||||
|
{
|
||||||
|
ActionQueue.Enqueue(action);
|
||||||
|
}
|
||||||
|
public async Task DeferAsync(Action action)
|
||||||
|
{
|
||||||
|
using SemaphoreSlim slim = new(0);
|
||||||
|
ActionQueue.Enqueue(() =>
|
||||||
|
{
|
||||||
|
action?.Invoke();
|
||||||
|
slim.Release();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
await slim.WaitAsync();
|
||||||
|
}
|
||||||
|
public async Task<T> DeferAsync<T>(Func<T> func)
|
||||||
|
{
|
||||||
|
if (func is null)
|
||||||
|
throw new Exception("Cannot defer null function");
|
||||||
|
using SemaphoreSlim slim = new(0);
|
||||||
|
T[] box = { default };
|
||||||
|
ActionQueue.Enqueue(() =>
|
||||||
|
{
|
||||||
|
box[0] = func.Invoke();
|
||||||
|
slim.Release();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
await slim.WaitAsync();
|
||||||
|
return box[0];
|
||||||
|
}
|
||||||
|
public void Defer(Action action)
|
||||||
|
{
|
||||||
|
using SemaphoreSlim slim = new(0);
|
||||||
|
ActionQueue.Enqueue(() =>
|
||||||
|
{
|
||||||
|
action?.Invoke();
|
||||||
|
slim.Release();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
slim.WaitAsync();
|
||||||
|
}
|
||||||
|
public T Defer<T>(Func<T> func)
|
||||||
|
{
|
||||||
|
if (func is null)
|
||||||
|
throw new Exception("Cannot defer null function");
|
||||||
|
using SemaphoreSlim slim = new(0);
|
||||||
|
T[] box = { default };
|
||||||
|
ActionQueue.Enqueue(() =>
|
||||||
|
{
|
||||||
|
box[0] = func.Invoke();
|
||||||
|
slim.Release();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
slim.WaitAsync();
|
||||||
|
return box[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
6
defer_manager.tscn
Normal file
6
defer_manager.tscn
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://c34yvmvtgju"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://defer_manager.cs" id="1_s88sy"]
|
||||||
|
|
||||||
|
[node name="DeferManager" type="Node"]
|
||||||
|
script = ExtResource("1_s88sy")
|
||||||
111
game.cs
111
game.cs
@@ -36,10 +36,9 @@ public partial class game : Control
|
|||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
var rows = this.GetAllDescendents<row>().ToArray();
|
var rows = this.GetAllDescendents<row>().ToArray();
|
||||||
for (int i = 0; i < 50; i++)
|
for (int i = 0; i < 20; i++)
|
||||||
{
|
{
|
||||||
var c = card.MakeCard(GetTree());
|
var c = card.MakeCard(GetTree());
|
||||||
GD.Print(c.CardId);
|
|
||||||
c.CardName = $"Card {c.CardId}";
|
c.CardName = $"Card {c.CardId}";
|
||||||
if (GD.RandRange(0, 1) == 1)
|
if (GD.RandRange(0, 1) == 1)
|
||||||
{
|
{
|
||||||
@@ -56,31 +55,26 @@ public partial class game : Control
|
|||||||
|
|
||||||
PropogateCardSize();
|
PropogateCardSize();
|
||||||
}
|
}
|
||||||
// public override void _UnhandledInput(InputEvent @event)
|
public override void _UnhandledInput(InputEvent @event)
|
||||||
// {
|
{
|
||||||
// if (@event is InputEventMouseButton iemb)
|
if (@event.IsActionPressed("OpenMenu"))
|
||||||
// {
|
{
|
||||||
// if (iemb.ButtonIndex == MouseButton.Right)
|
GetNode<settings_popup>("%SettingsPopup").Visible = true;
|
||||||
// {
|
GetViewport().SetInputAsHandled();
|
||||||
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
// else if (@event is InputEventKey iek)
|
|
||||||
// {
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
public void SetContainerMinima()
|
public void SetContainerMinima()
|
||||||
{
|
{
|
||||||
var node = GetNode<VBoxContainer>("%RowContainer");
|
// var node = GetNode<VBoxContainer>("%RowContainer");
|
||||||
node.CustomMinimumSize = new Vector2(0, _CardSize.Y * node.GetChildCount());
|
// node.CustomMinimumSize = new Vector2(0, _CardSize.Y * node.GetChildCount());
|
||||||
}
|
}
|
||||||
public row GetRowById(string id)
|
public row GetRowById(string id)
|
||||||
=> GetTree().GetNodesInGroup("RowGroup").OfType<row>().FirstOrDefault(r => r.RowId == id);
|
=> GetTree().GetNodesInGroup("RowGroup").OfType<row>()
|
||||||
|
.FirstOrDefault(r => r.RowId == id);
|
||||||
public void AddRow(row row, string after = null)
|
public void AddRow(row row, string after = null)
|
||||||
{
|
{
|
||||||
if (after is not null)
|
if (after is not null)
|
||||||
@@ -118,49 +112,10 @@ public partial class game : Control
|
|||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
/// <summary>
|
public void EditCardInMenu(card c)
|
||||||
///
|
{
|
||||||
/// </summary>
|
GetNode<card_edit_popup>("%CardEditPopup").ActivateForCard(c);
|
||||||
/// <param name="id"></param>
|
}
|
||||||
/// <param name="target_row">null to unassign card</param>
|
|
||||||
/// <returns>false if something goes wrong</returns>
|
|
||||||
// public bool MoveCard(string id, row target_row, float horizontal)
|
|
||||||
// {
|
|
||||||
// foreach (row r in Rows)
|
|
||||||
// {
|
|
||||||
// if (r.TryRemoveCard(id) is card c)
|
|
||||||
// {
|
|
||||||
// //add to row
|
|
||||||
// if (target_row is not null)
|
|
||||||
// {
|
|
||||||
// target_row.AddCard(c);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// //unassign
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// AddUnassignedCard(c);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if (RemoveUnassignedCard(id) is card cc)
|
|
||||||
// {
|
|
||||||
// //add to row
|
|
||||||
// if (target_row is not null)
|
|
||||||
// {
|
|
||||||
// target_row.AddCard(cc);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// //unassign
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// AddUnassignedCard(cc);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
public card ClaimCard(string id)
|
public card ClaimCard(string id)
|
||||||
{
|
{
|
||||||
foreach (row r in Rows)
|
foreach (row r in Rows)
|
||||||
@@ -221,15 +176,25 @@ public partial class game : Control
|
|||||||
var r = FindRow(rowId);
|
var r = FindRow(rowId);
|
||||||
if (r is null)
|
if (r is null)
|
||||||
throw new Exception($"row {r.RowId} not found");
|
throw new Exception($"row {r.RowId} not found");
|
||||||
}
|
if (!deleteCards)
|
||||||
public void CreateCard(string title = null, Image image = null)
|
|
||||||
{
|
{
|
||||||
var scn = GD.Load<PackedScene>("res://card.tscn");
|
var unassigned = GetNode("%UnassignedCardContainer");
|
||||||
var c = scn.Instantiate() as card;
|
foreach (var c in r.Cards.ToArray())
|
||||||
|
c.Reparent(unassigned);
|
||||||
|
}
|
||||||
|
//GetNode("%RowContainer").RemoveChild(r);
|
||||||
|
r.QueueFree();
|
||||||
|
}
|
||||||
|
public void CreateCard(string title = null, ImageWithMetadata image = null)
|
||||||
|
{
|
||||||
|
var c = card.MakeCard(GetTree());
|
||||||
if (!string.IsNullOrWhiteSpace(title))
|
if (!string.IsNullOrWhiteSpace(title))
|
||||||
c.CardName = title;
|
c.CardName = title;
|
||||||
if (image is not null)
|
if (image is not null)
|
||||||
c.SetTexture(ImageTexture.CreateFromImage(image));
|
{
|
||||||
|
c.SetTexture(ImageTexture.CreateFromImage(image.Image));
|
||||||
|
c.SetStretchMode(image.StretchMode);
|
||||||
|
}
|
||||||
AddUnassignedCard(c);
|
AddUnassignedCard(c);
|
||||||
}
|
}
|
||||||
public void CreateRow(Color? color = null, string title = null)
|
public void CreateRow(Color? color = null, string title = null)
|
||||||
@@ -240,25 +205,27 @@ public partial class game : Control
|
|||||||
r.RowText = title;
|
r.RowText = title;
|
||||||
if (color is Color color1)
|
if (color is Color color1)
|
||||||
r.RowColor = color1;
|
r.RowColor = color1;
|
||||||
|
AddRow(r);
|
||||||
}
|
}
|
||||||
public void RenameCard(string cardId, string newName)
|
public void RenameCard(string cardId, string newName)
|
||||||
{
|
{
|
||||||
|
FindCard(cardId).CardName = newName;
|
||||||
}
|
}
|
||||||
public void RenameRow(string rowId, string newTitle)
|
public void RenameRow(string rowId, string newTitle)
|
||||||
{
|
{
|
||||||
|
GetRowById(rowId).RowText = newTitle;
|
||||||
}
|
}
|
||||||
public void RecolorRow(string rowId, Color color)
|
public void RecolorRow(string rowId, Color color)
|
||||||
{
|
{
|
||||||
|
GetRowById(rowId).RowColor = color;
|
||||||
}
|
}
|
||||||
public void ChangeCardImage(string cardId, Image image)
|
public void ChangeCardImage(string cardId, ImageWithMetadata image)
|
||||||
{
|
{
|
||||||
var c = FindCard(cardId);
|
var c = FindCard(cardId);
|
||||||
if (c is null)
|
if (c is null)
|
||||||
throw new Exception($"card {c.CardId} not found");
|
throw new Exception($"card {c.CardId} not found");
|
||||||
c.SetTexture(ImageTexture.CreateFromImage(image));
|
c.SetTexture(ImageTexture.CreateFromImage(image.Image));
|
||||||
|
c.SetStretchMode(image.StretchMode);
|
||||||
}
|
}
|
||||||
#endregion //Commands
|
#endregion //Commands
|
||||||
}
|
}
|
||||||
|
|||||||
49
game.tscn
49
game.tscn
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
[ext_resource type="PackedScene" uid="uid://b7pebyti48f7b" path="res://row.tscn" id="1_numg7"]
|
[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://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="Script" path="res://PictureDropHandler.cs" id="3_owd27"]
|
||||||
[ext_resource type="Script" path="res://TwitchChatWatcher.cs" id="5_qurdj"]
|
|
||||||
[ext_resource type="Script" path="res://CommandHandler.cs" id="5_yfhlo"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://jm7tss267q8y" path="res://settings_popup.tscn" id="6_e1cou"]
|
[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"]
|
||||||
|
|
||||||
[node name="Game" type="Control"]
|
[node name="Game" type="Control"]
|
||||||
layout_mode = 3
|
layout_mode = 3
|
||||||
@@ -18,7 +18,7 @@ size_flags_vertical = 3
|
|||||||
script = ExtResource("1_vl33u")
|
script = ExtResource("1_vl33u")
|
||||||
_CardSize = Vector2(150, 150)
|
_CardSize = Vector2(150, 150)
|
||||||
|
|
||||||
[node name="GameContainer" type="VBoxContainer" parent="."]
|
[node name="GameScrollContainer" type="ScrollContainer" parent="."]
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
@@ -26,46 +26,57 @@ anchor_bottom = 1.0
|
|||||||
grow_horizontal = 2
|
grow_horizontal = 2
|
||||||
grow_vertical = 2
|
grow_vertical = 2
|
||||||
|
|
||||||
[node name="RowContainer" type="VBoxContainer" parent="GameContainer"]
|
[node name="GameContainer" type="VBoxContainer" parent="GameScrollContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
|
||||||
|
[node name="RowContainer" type="VBoxContainer" parent="GameScrollContainer/GameContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_vertical = 3
|
size_flags_vertical = 3
|
||||||
|
|
||||||
[node name="Row_A" parent="GameContainer/RowContainer" instance=ExtResource("1_numg7")]
|
[node name="Row_A" parent="GameScrollContainer/GameContainer/RowContainer" instance=ExtResource("1_numg7")]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
_RowColor = Color(0.964706, 0.482353, 0.494118, 1)
|
_RowColor = Color(0.964706, 0.482353, 0.494118, 1)
|
||||||
_RowText = "A"
|
_RowText = "A"
|
||||||
RowId = "1"
|
RowId = "1"
|
||||||
|
|
||||||
[node name="Row_B" parent="GameContainer/RowContainer" instance=ExtResource("1_numg7")]
|
[node name="Row_B" parent="GameScrollContainer/GameContainer/RowContainer" instance=ExtResource("1_numg7")]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
_RowColor = Color(0.996078, 0.878431, 0.541176, 1)
|
_RowColor = Color(0.996078, 0.878431, 0.541176, 1)
|
||||||
_RowText = "B"
|
_RowText = "B"
|
||||||
RowId = "2"
|
RowId = "2"
|
||||||
|
|
||||||
[node name="Row_C" parent="GameContainer/RowContainer" instance=ExtResource("1_numg7")]
|
[node name="Row_C" parent="GameScrollContainer/GameContainer/RowContainer" instance=ExtResource("1_numg7")]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
_RowColor = Color(0.988235, 1, 0.494118, 1)
|
_RowColor = Color(0.988235, 1, 0.494118, 1)
|
||||||
_RowText = "C"
|
_RowText = "C"
|
||||||
RowId = "3"
|
RowId = "3"
|
||||||
|
|
||||||
[node name="Row_D" parent="GameContainer/RowContainer" instance=ExtResource("1_numg7")]
|
[node name="Row_D" parent="GameScrollContainer/GameContainer/RowContainer" instance=ExtResource("1_numg7")]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
_RowColor = Color(0.639216, 0.937255, 0.34902, 1)
|
_RowColor = Color(0.639216, 0.937255, 0.34902, 1)
|
||||||
_RowText = "D"
|
_RowText = "D"
|
||||||
RowId = "4"
|
RowId = "4"
|
||||||
|
|
||||||
[node name="Row_F" parent="GameContainer/RowContainer" instance=ExtResource("1_numg7")]
|
[node name="Row_F" parent="GameScrollContainer/GameContainer/RowContainer" instance=ExtResource("1_numg7")]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
_RowColor = Color(0.298039, 0.87451, 0.952941, 1)
|
_RowColor = Color(0.298039, 0.87451, 0.952941, 1)
|
||||||
_RowText = "F"
|
_RowText = "F"
|
||||||
RowId = "5"
|
RowId = "5"
|
||||||
|
|
||||||
[node name="PictureDropHandler" type="Control" parent="."]
|
[node name="UnassignedCardPanel" type="PanelContainer" parent="GameScrollContainer/GameContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
script = ExtResource("3_dbs2t")
|
||||||
|
|
||||||
|
[node name="UnassignedCardContainer" type="HFlowContainer" parent="GameScrollContainer/GameContainer/UnassignedCardPanel"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="PictureDropHandler" type="Node" parent="."]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
anchors_preset = 0
|
|
||||||
offset_right = 40.0
|
|
||||||
offset_bottom = 40.0
|
|
||||||
script = ExtResource("3_owd27")
|
script = ExtResource("3_owd27")
|
||||||
|
|
||||||
[node name="CardContextMenu" type="PopupMenu" parent="."]
|
[node name="CardContextMenu" type="PopupMenu" parent="."]
|
||||||
@@ -80,12 +91,10 @@ item_count = 1
|
|||||||
item_0/text = ""
|
item_0/text = ""
|
||||||
item_0/id = 0
|
item_0/id = 0
|
||||||
|
|
||||||
[node name="TwitchChatWatcher" type="Node" parent="."]
|
|
||||||
script = ExtResource("5_qurdj")
|
|
||||||
|
|
||||||
[node name="CommandHandler" type="Node" parent="."]
|
|
||||||
script = ExtResource("5_yfhlo")
|
|
||||||
|
|
||||||
[node name="SettingsPopup" parent="." instance=ExtResource("6_e1cou")]
|
[node name="SettingsPopup" parent="." instance=ExtResource("6_e1cou")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
|
||||||
[connection signal="IncomingCommand" from="TwitchChatWatcher" to="CommandHandler" method="IncomingCommand"]
|
[node name="CardEditPopup" parent="." instance=ExtResource("6_eqvov")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
visible = false
|
||||||
|
|||||||
@@ -13,10 +13,12 @@ config_version=5
|
|||||||
config/name="TierMakerControl"
|
config/name="TierMakerControl"
|
||||||
run/main_scene="res://game.tscn"
|
run/main_scene="res://game.tscn"
|
||||||
config/features=PackedStringArray("4.2", "C#", "Forward Plus")
|
config/features=PackedStringArray("4.2", "C#", "Forward Plus")
|
||||||
|
run/flush_stdout_on_print=true
|
||||||
config/icon="res://icon.svg"
|
config/icon="res://icon.svg"
|
||||||
|
|
||||||
[autoload]
|
[autoload]
|
||||||
|
|
||||||
|
DeferManager="*res://defer_manager.tscn"
|
||||||
Settings="*res://Settings.cs"
|
Settings="*res://Settings.cs"
|
||||||
CommandHandler="*res://CommandHandler.cs"
|
CommandHandler="*res://CommandHandler.cs"
|
||||||
TwitchChatWatcher="*res://TwitchChatWatcher.cs"
|
TwitchChatWatcher="*res://TwitchChatWatcher.cs"
|
||||||
@@ -32,3 +34,14 @@ OpenMenu={
|
|||||||
"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":4194332,"key_label":0,"unicode":0,"echo":false,"script":null)
|
"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":4194332,"key_label":0,"unicode":0,"echo":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
ContextMenu={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": [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(78, 14),"global_position":Vector2(82, 55),"factor":1.0,"button_index":2,"canceled":false,"pressed":true,"double_click":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
LocationMenu={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"button_mask":1,"position":Vector2(78, 20),"global_position":Vector2(82, 61),"factor":1.0,"button_index":1,"canceled":false,"pressed":true,"double_click":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":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)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|||||||
9
row.cs
9
row.cs
@@ -3,6 +3,7 @@ using System;
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
public partial class row : Control
|
public partial class row : Control
|
||||||
{
|
{
|
||||||
@@ -89,6 +90,14 @@ public partial class row : Control
|
|||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
public override void _Input(InputEvent @event)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
private void RowMenu()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
public void DropOn(Vector2 atPosition, Variant data)
|
public void DropOn(Vector2 atPosition, Variant data)
|
||||||
{
|
{
|
||||||
GD.Print($"Dropping at {atPosition}");
|
GD.Print($"Dropping at {atPosition}");
|
||||||
|
|||||||
9
row.tscn
9
row.tscn
@@ -51,7 +51,6 @@ theme_override_styles/panel = SubResource("StyleBoxFlat_22f0d")
|
|||||||
|
|
||||||
[node name="RowTitleBoxLabel" type="Label" parent="RowGrid/RowBaseContainer/RowTitleBoxBackground"]
|
[node name="RowTitleBoxLabel" type="Label" parent="RowGrid/RowBaseContainer/RowTitleBoxBackground"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
z_index = 1
|
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 8
|
anchors_preset = 8
|
||||||
anchor_left = 0.5
|
anchor_left = 0.5
|
||||||
@@ -73,16 +72,12 @@ justification_flags = 161
|
|||||||
|
|
||||||
[node name="RowTitleBoxIdLabel" type="Label" parent="RowGrid/RowBaseContainer/RowTitleBoxBackground"]
|
[node name="RowTitleBoxIdLabel" type="Label" parent="RowGrid/RowBaseContainer/RowTitleBoxBackground"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
z_index = 1
|
|
||||||
layout_mode = 1
|
layout_mode = 1
|
||||||
anchors_preset = 12
|
anchors_preset = 2
|
||||||
anchor_top = 1.0
|
anchor_top = 1.0
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
offset_left = -24.0
|
|
||||||
offset_top = -23.0
|
offset_top = -23.0
|
||||||
offset_right = 24.0
|
offset_right = 48.0
|
||||||
grow_horizontal = 2
|
|
||||||
grow_vertical = 0
|
grow_vertical = 0
|
||||||
text = "RowId"
|
text = "RowId"
|
||||||
label_settings = SubResource("LabelSettings_7hvr3")
|
label_settings = SubResource("LabelSettings_7hvr3")
|
||||||
|
|||||||
@@ -1,35 +1,75 @@
|
|||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
public partial class settings_popup : Popup
|
public partial class settings_popup : PopupPanel
|
||||||
{
|
{
|
||||||
|
[Signal]
|
||||||
|
public delegate void BeforeOkEventHandler();
|
||||||
// Called when the node enters the scene tree for the first time.
|
// Called when the node enters the scene tree for the first time.
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
|
Transient = true;
|
||||||
|
Exclusive = true;
|
||||||
}
|
}
|
||||||
|
private readonly ConcurrentQueue<Action> ActionQueue = new();
|
||||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
public override void _Process(double delta)
|
public override void _Process(double delta)
|
||||||
{
|
{
|
||||||
|
// //perform 1 action every frame
|
||||||
|
// if (ActionQueue.TryDequeue(out Action a))
|
||||||
|
// {
|
||||||
|
// GD.Print("Found action");
|
||||||
|
// a?.Invoke();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
public void _on_cancel_button_pressed()
|
public void _on_cancel_button_pressed()
|
||||||
{
|
{
|
||||||
|
GD.Print("Cancel pressed");
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
public void _on_ok_button_pressed()
|
public void _on_ok_button_pressed()
|
||||||
{
|
{
|
||||||
|
GD.Print("OK pressed");
|
||||||
|
var tcw = GetNode<TwitchChatWatcher>("/root/TwitchChatWatcher");
|
||||||
|
string chName = GetNode<LineEdit>("%ChannelNameEdit").Text;
|
||||||
|
Task.Run(tcw.ConnectAsync).ContinueWith(t => tcw.Authenticate(null, null))
|
||||||
|
.ContinueWith(t => tcw.RequestTags())
|
||||||
|
.ContinueWith(t => tcw.JoinChannel(chName))
|
||||||
|
.ContinueWith(FinishConnection);
|
||||||
|
ProcessMode = ProcessModeEnum.Disabled;
|
||||||
|
}
|
||||||
|
private void FinishConnection(Task t)
|
||||||
|
{
|
||||||
|
GD.Print(t.Status);
|
||||||
|
if (t.IsCompletedSuccessfully)
|
||||||
|
{
|
||||||
|
CallDeferred(nameof(SuccessfulConnection));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GD.PrintErr(t.Exception);
|
||||||
|
ActionQueue.Enqueue(() => ProcessMode = ProcessModeEnum.Inherit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void SuccessfulConnection()
|
||||||
|
{
|
||||||
|
GD.Print("Running completion task");
|
||||||
|
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");
|
var settings = GetNode<Settings>("/root/Settings");
|
||||||
settings.AllowModerators = GetNode<CheckBox>("%CheckBoxModerator").ButtonPressed;
|
settings.AllowModerators = GetNode<CheckBox>("%CheckBoxModerator").ButtonPressed;
|
||||||
|
settings.Command = GetNode<LineEdit>("%CommandEdit").Text;
|
||||||
settings.SetUserLists(GetNode<TextEdit>("%WhiteListEdit").Text.Split('\n',
|
settings.SetUserLists(GetNode<TextEdit>("%WhiteListEdit").Text.Split('\n',
|
||||||
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries),
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries),
|
||||||
GetNode<TextEdit>("%BlackListEdit").Text.Split('\n',
|
GetNode<TextEdit>("%BlackListEdit").Text.Split('\n',
|
||||||
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries));
|
StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries));
|
||||||
var tcw = GetNode<TwitchChatWatcher>("/root/TwitchChatWatcher");
|
ProcessMode = ProcessModeEnum.Inherit;
|
||||||
tcw.ConnectAsync().RunSynchronously();
|
|
||||||
tcw.Authenticate().RunSynchronously();
|
|
||||||
tcw.JoinChannel(GetNode<LineEdit>("%ChannelNameEdit").Text).RunSynchronously();
|
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,91 +1,141 @@
|
|||||||
[gd_scene load_steps=2 format=3 uid="uid://jm7tss267q8y"]
|
[gd_scene load_steps=5 format=3 uid="uid://jm7tss267q8y"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://settings_popup.cs" id="1_blkox"]
|
[ext_resource type="Script" path="res://settings_popup.cs" id="1_blkox"]
|
||||||
|
[ext_resource type="Script" path="res://ConfigStretchContainer.cs" id="2_fhn7i"]
|
||||||
|
|
||||||
[node name="SettingsPopup" type="Popup"]
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jcc71"]
|
||||||
|
|
||||||
|
[sub_resource type="ButtonGroup" id="ButtonGroup_4itga"]
|
||||||
|
|
||||||
|
[node name="SettingsPopup" type="PopupPanel"]
|
||||||
title = "Settings"
|
title = "Settings"
|
||||||
size = Vector2i(720, 480)
|
size = Vector2i(728, 523)
|
||||||
visible = true
|
visible = true
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_jcc71")
|
||||||
script = ExtResource("1_blkox")
|
script = ExtResource("1_blkox")
|
||||||
|
|
||||||
[node name="SettingsPopupContainer" type="TabContainer" parent="."]
|
[node name="SettingsDivider" type="VSplitContainer" parent="."]
|
||||||
|
offset_right = 728.0
|
||||||
|
offset_bottom = 523.0
|
||||||
|
|
||||||
|
[node name="SettingsPopupContainer" type="TabContainer" parent="SettingsDivider"]
|
||||||
custom_minimum_size = Vector2(720, 480)
|
custom_minimum_size = Vector2(720, 480)
|
||||||
anchors_preset = 15
|
|
||||||
anchor_right = 1.0
|
|
||||||
anchor_bottom = 1.0
|
|
||||||
grow_horizontal = 2
|
|
||||||
grow_vertical = 2
|
|
||||||
|
|
||||||
[node name="ChatContainer" type="VBoxContainer" parent="SettingsPopupContainer"]
|
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="ChannelNameContainer" type="HBoxContainer" parent="SettingsPopupContainer/ChatContainer"]
|
[node name="ChatContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="ChannelNameLabel" type="Label" parent="SettingsPopupContainer/ChatContainer/ChannelNameContainer"]
|
[node name="TopBoxContainer" type="GridContainer" parent="SettingsDivider/SettingsPopupContainer/ChatContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
columns = 2
|
||||||
|
|
||||||
|
[node name="ChannelNameLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/TopBoxContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Channel Name"
|
text = "Channel Name"
|
||||||
|
|
||||||
[node name="ChannelNameEdit" type="LineEdit" parent="SettingsPopupContainer/ChatContainer/ChannelNameContainer"]
|
[node name="ChannelNameEdit" type="LineEdit" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/TopBoxContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(500, 0)
|
custom_minimum_size = Vector2(500, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="CheckBoxModerator" type="CheckBox" parent="SettingsPopupContainer/ChatContainer"]
|
[node name="CommandLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/TopBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Command"
|
||||||
|
|
||||||
|
[node name="CommandEdit" type="LineEdit" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/TopBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(500, 0)
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="CheckBoxModerator" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ChatContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Allow moderators"
|
text = "Allow moderators"
|
||||||
|
|
||||||
[node name="UserListContainer" type="HBoxContainer" parent="SettingsPopupContainer/ChatContainer"]
|
[node name="UserListContainer" type="HBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ChatContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_vertical = 3
|
size_flags_vertical = 3
|
||||||
|
|
||||||
[node name="WhiteListContainer" type="VBoxContainer" parent="SettingsPopupContainer/ChatContainer/UserListContainer"]
|
[node name="WhiteListContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/UserListContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
[node name="WhiteListLabel" type="Label" parent="SettingsPopupContainer/ChatContainer/UserListContainer/WhiteListContainer"]
|
[node name="WhiteListLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/UserListContainer/WhiteListContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Whitelist"
|
text = "Whitelist"
|
||||||
|
|
||||||
[node name="WhiteListEdit" type="TextEdit" parent="SettingsPopupContainer/ChatContainer/UserListContainer/WhiteListContainer"]
|
[node name="WhiteListEdit" type="TextEdit" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/UserListContainer/WhiteListContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_vertical = 3
|
size_flags_vertical = 3
|
||||||
|
|
||||||
[node name="BlackListContainer" type="VBoxContainer" parent="SettingsPopupContainer/ChatContainer/UserListContainer"]
|
[node name="BlackListContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/UserListContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
[node name="BlackListLabel" type="Label" parent="SettingsPopupContainer/ChatContainer/UserListContainer/BlackListContainer"]
|
[node name="BlackListLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/UserListContainer/BlackListContainer"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Blacklist
|
text = "Blacklist
|
||||||
"
|
"
|
||||||
|
|
||||||
[node name="BlackListEdit" type="TextEdit" parent="SettingsPopupContainer/ChatContainer/UserListContainer/BlackListContainer"]
|
[node name="BlackListEdit" type="TextEdit" parent="SettingsDivider/SettingsPopupContainer/ChatContainer/UserListContainer/BlackListContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_vertical = 3
|
size_flags_vertical = 3
|
||||||
|
|
||||||
[node name="HBoxContainer" type="HBoxContainer" parent="SettingsPopupContainer/ChatContainer"]
|
[node name="ConfigContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="ConfigStretchContainer" type="VBoxContainer" parent="SettingsDivider/SettingsPopupContainer/ConfigContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
alignment = 1
|
||||||
|
script = ExtResource("2_fhn7i")
|
||||||
|
|
||||||
|
[node name="ConfigStretchLabel" type="Label" parent="SettingsDivider/SettingsPopupContainer/ConfigContainer/ConfigStretchContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
text = " Default Stretch Mode"
|
||||||
|
|
||||||
|
[node name="ConfigStretchFitButton" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ConfigContainer/ConfigStretchContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
button_pressed = true
|
||||||
|
button_group = SubResource("ButtonGroup_4itga")
|
||||||
|
text = "Fit"
|
||||||
|
|
||||||
|
[node name="ConfigStretchStretchButton" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ConfigContainer/ConfigStretchContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
button_group = SubResource("ButtonGroup_4itga")
|
||||||
|
text = "Stretch"
|
||||||
|
|
||||||
|
[node name="ConfigStretchCropButton" type="CheckBox" parent="SettingsDivider/SettingsPopupContainer/ConfigContainer/ConfigStretchContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
button_group = SubResource("ButtonGroup_4itga")
|
||||||
|
text = "Crop"
|
||||||
|
|
||||||
|
[node name="ButtonContainer" type="HBoxContainer" parent="SettingsDivider"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
alignment = 2
|
alignment = 2
|
||||||
|
|
||||||
[node name="CancelButton" type="Button" parent="SettingsPopupContainer/ChatContainer/HBoxContainer"]
|
[node name="CancelButton" type="Button" parent="SettingsDivider/ButtonContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(100, 0)
|
custom_minimum_size = Vector2(100, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 8
|
size_flags_horizontal = 8
|
||||||
text = "Cancel"
|
text = "Cancel"
|
||||||
|
|
||||||
[node name="OkButton" type="Button" parent="SettingsPopupContainer/ChatContainer/HBoxContainer"]
|
[node name="OkButton" type="Button" parent="SettingsDivider/ButtonContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(100, 0)
|
custom_minimum_size = Vector2(100, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 8
|
size_flags_horizontal = 8
|
||||||
text = "OK"
|
text = "OK"
|
||||||
|
|
||||||
[connection signal="pressed" from="SettingsPopupContainer/ChatContainer/HBoxContainer/CancelButton" to="." method="_on_cancel_button_pressed"]
|
[connection signal="BeforeOk" from="." to="SettingsDivider/SettingsPopupContainer/ConfigContainer/ConfigStretchContainer" method="OkClicked"]
|
||||||
[connection signal="pressed" from="SettingsPopupContainer/ChatContainer/HBoxContainer/OkButton" to="." method="_on_ok_button_pressed"]
|
[connection signal="pressed" from="SettingsDivider/ButtonContainer/CancelButton" to="." method="_on_cancel_button_pressed"]
|
||||||
|
[connection signal="pressed" from="SettingsDivider/ButtonContainer/OkButton" to="." method="_on_ok_button_pressed"]
|
||||||
|
|||||||
Reference in New Issue
Block a user