Updated image library
This commit is contained in:
parent
89ab9a2ceb
commit
742d98a4c1
9 changed files with 54 additions and 43 deletions
|
@ -69,9 +69,9 @@
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.Seq" Version="7.0.1" />
|
<PackageReference Include="Serilog.Sinks.Seq" Version="7.0.1" />
|
||||||
|
|
||||||
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta17" />
|
<PackageReference Include="SixLabors.Fonts" Version="2.0.4" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.9" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.5" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14" />
|
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.4" />
|
||||||
<PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0009" />
|
<PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0009" />
|
||||||
<PackageReference Include="StackExchange.Redis" Version="2.8.0" />
|
<PackageReference Include="StackExchange.Redis" Version="2.8.0" />
|
||||||
<PackageReference Include="YamlDotNet" Version="15.1.4" />
|
<PackageReference Include="YamlDotNet" Version="15.1.4" />
|
||||||
|
|
|
@ -37,6 +37,8 @@ public class AutoPublishService : IExecNoCommand, IReadyExecutor, IEService
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo GUILDS
|
||||||
|
|
||||||
public async Task OnReadyAsync()
|
public async Task OnReadyAsync()
|
||||||
{
|
{
|
||||||
var creds = _creds.GetCreds();
|
var creds = _creds.GetCreds();
|
||||||
|
|
|
@ -111,13 +111,17 @@ public class PlantPickService : IEService, IExecNoCommand
|
||||||
{
|
{
|
||||||
var curImg = await _images.GetCurrencyImageAsync();
|
var curImg = await _images.GetCurrencyImageAsync();
|
||||||
|
|
||||||
|
if (curImg is null)
|
||||||
|
return (new MemoryStream(), null);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(pass))
|
if (string.IsNullOrWhiteSpace(pass))
|
||||||
{
|
{
|
||||||
// determine the extension
|
// determine the extension
|
||||||
using var load = _ = Image.Load(curImg, out var format);
|
using var load = Image.Load(curImg);
|
||||||
|
|
||||||
|
var format = load.Metadata.DecodedImageFormat;
|
||||||
// return the image
|
// return the image
|
||||||
return (curImg.ToStream(), format.FileExtensions.FirstOrDefault() ?? "png");
|
return (curImg.ToStream(), format?.FileExtensions.FirstOrDefault() ?? "png");
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the image stream and extension
|
// get the image stream and extension
|
||||||
|
@ -134,16 +138,17 @@ public class PlantPickService : IEService, IExecNoCommand
|
||||||
{
|
{
|
||||||
// draw lower, it looks better
|
// draw lower, it looks better
|
||||||
pass = pass.TrimTo(10, true).ToLowerInvariant();
|
pass = pass.TrimTo(10, true).ToLowerInvariant();
|
||||||
using var img = Image.Load<Rgba32>(curImg, out var format);
|
using var img = Image.Load<Rgba32>(curImg);
|
||||||
// choose font size based on the image height, so that it's visible
|
// choose font size based on the image height, so that it's visible
|
||||||
var font = _fonts.NotoSans.CreateFont(img.Height / 12.0f, FontStyle.Bold);
|
var font = _fonts.NotoSans.CreateFont(img.Height / 12.0f, FontStyle.Bold);
|
||||||
img.Mutate(x =>
|
img.Mutate(x =>
|
||||||
{
|
{
|
||||||
// measure the size of the text to be drawing
|
// measure the size of the text to be drawing
|
||||||
var size = TextMeasurer.Measure(pass, new TextOptions(font)
|
var size = TextMeasurer.MeasureSize(pass,
|
||||||
{
|
new TextOptions(font)
|
||||||
Origin = new PointF(0, 0)
|
{
|
||||||
});
|
Origin = new PointF(0, 0)
|
||||||
|
});
|
||||||
|
|
||||||
// fill the background with black, add 5 pixels on each side to make it look better
|
// fill the background with black, add 5 pixels on each side to make it look better
|
||||||
x.FillPolygon(Color.ParseHex("00000080"),
|
x.FillPolygon(Color.ParseHex("00000080"),
|
||||||
|
@ -156,6 +161,7 @@ public class PlantPickService : IEService, IExecNoCommand
|
||||||
x.DrawText(pass, font, Color.White, new(0, 0));
|
x.DrawText(pass, font, Color.White, new(0, 0));
|
||||||
});
|
});
|
||||||
// return image as a stream for easy sending
|
// return image as a stream for easy sending
|
||||||
|
var format = img.Metadata.DecodedImageFormat;
|
||||||
return (img.ToStream(format), format.FileExtensions.FirstOrDefault() ?? "png");
|
return (img.ToStream(format), format.FileExtensions.FirstOrDefault() ?? "png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +262,8 @@ public class PlantPickService : IEService, IExecNoCommand
|
||||||
|
|
||||||
pass = pass?.Trim().TrimTo(10, true).ToUpperInvariant();
|
pass = pass?.Trim().TrimTo(10, true).ToUpperInvariant();
|
||||||
// gets all plants in this channel with the same password
|
// gets all plants in this channel with the same password
|
||||||
var entries = uow.Set<PlantedCurrency>().AsQueryable()
|
var entries = uow.Set<PlantedCurrency>()
|
||||||
|
.AsQueryable()
|
||||||
.Where(x => x.ChannelId == ch.Id && pass == x.Password)
|
.Where(x => x.ChannelId == ch.Id && pass == x.Password)
|
||||||
.ToList();
|
.ToList();
|
||||||
// sum how much currency that is, and get all of the message ids (so that i can delete them)
|
// sum how much currency that is, and get all of the message ids (so that i can delete them)
|
||||||
|
@ -368,15 +375,16 @@ public class PlantPickService : IEService, IExecNoCommand
|
||||||
string pass)
|
string pass)
|
||||||
{
|
{
|
||||||
await using var uow = _db.GetDbContext();
|
await using var uow = _db.GetDbContext();
|
||||||
uow.Set<PlantedCurrency>().Add(new()
|
uow.Set<PlantedCurrency>()
|
||||||
{
|
.Add(new()
|
||||||
Amount = amount,
|
{
|
||||||
GuildId = gid,
|
Amount = amount,
|
||||||
ChannelId = cid,
|
GuildId = gid,
|
||||||
Password = pass,
|
ChannelId = cid,
|
||||||
UserId = uid,
|
Password = pass,
|
||||||
MessageId = mid
|
UserId = uid,
|
||||||
});
|
MessageId = mid
|
||||||
|
});
|
||||||
await uow.SaveChangesAsync();
|
await uow.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -172,13 +172,13 @@ public partial class Gambling
|
||||||
}
|
}
|
||||||
|
|
||||||
var slotBg = await _images.GetSlotBgAsync();
|
var slotBg = await _images.GetSlotBgAsync();
|
||||||
var bgImage = Image.Load<Rgba32>(slotBg, out _);
|
var bgImage = Image.Load<Rgba32>(slotBg);
|
||||||
var numbers = new int[3];
|
var numbers = new int[3];
|
||||||
result.Rolls.CopyTo(numbers, 0);
|
result.Rolls.CopyTo(numbers, 0);
|
||||||
|
|
||||||
Color fontColor = Config.Slots.CurrencyFontColor;
|
Color fontColor = Config.Slots.CurrencyFontColor;
|
||||||
|
|
||||||
bgImage.Mutate(x => x.DrawText(new TextOptions(_fonts.DottyFont.CreateFont(65))
|
bgImage.Mutate<Rgba32>(x => x.DrawText(new RichTextOptions(_fonts.DottyFont.CreateFont(65))
|
||||||
{
|
{
|
||||||
HorizontalAlignment = HorizontalAlignment.Center,
|
HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
@ -190,7 +190,7 @@ public partial class Gambling
|
||||||
|
|
||||||
var bottomFont = _fonts.DottyFont.CreateFont(50);
|
var bottomFont = _fonts.DottyFont.CreateFont(50);
|
||||||
|
|
||||||
bgImage.Mutate(x => x.DrawText(new TextOptions(bottomFont)
|
bgImage.Mutate(x => x.DrawText(new RichTextOptions(bottomFont)
|
||||||
{
|
{
|
||||||
HorizontalAlignment = HorizontalAlignment.Center,
|
HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
|
|
@ -90,7 +90,7 @@ public class CryptoService : IEService
|
||||||
|
|
||||||
img.Mutate(x =>
|
img.Mutate(x =>
|
||||||
{
|
{
|
||||||
x.DrawLines(color, 2, points);
|
x.DrawLine(color, 2, points);
|
||||||
});
|
});
|
||||||
|
|
||||||
return img;
|
return img;
|
||||||
|
|
|
@ -94,7 +94,7 @@ public sealed class ImagesharpStockChartDrawingService : IStockChartDrawingServi
|
||||||
=> image.Mutate(ctx =>
|
=> image.Mutate(ctx =>
|
||||||
{
|
{
|
||||||
foreach (var data in drawData)
|
foreach (var data in drawData)
|
||||||
ctx.DrawLines(data.IsGreen
|
ctx.DrawLine(data.IsGreen
|
||||||
? _greenBrush
|
? _greenBrush
|
||||||
: _redBrush,
|
: _redBrush,
|
||||||
1,
|
1,
|
||||||
|
@ -128,7 +128,7 @@ public sealed class ImagesharpStockChartDrawingService : IStockChartDrawingServi
|
||||||
{
|
{
|
||||||
// draw guides
|
// draw guides
|
||||||
foreach (var y in lines)
|
foreach (var y in lines)
|
||||||
ctx.DrawLines(_lineGuideColor, 1, new PointF(0, y), new PointF(WIDTH, y));
|
ctx.DrawLine(_lineGuideColor, 1, new PointF(0, y), new PointF(WIDTH, y));
|
||||||
|
|
||||||
// // draw min and max price on the chart
|
// // draw min and max price on the chart
|
||||||
// ctx.DrawText(min.ToString(CultureInfo.InvariantCulture),
|
// ctx.DrawText(min.ToString(CultureInfo.InvariantCulture),
|
||||||
|
@ -156,7 +156,7 @@ public sealed class ImagesharpStockChartDrawingService : IStockChartDrawingServi
|
||||||
|
|
||||||
image.Mutate(ctx =>
|
image.Mutate(ctx =>
|
||||||
{
|
{
|
||||||
ctx.DrawLines(_sparklineColor, 2, points);
|
ctx.DrawLine(_sparklineColor, 2, points);
|
||||||
});
|
});
|
||||||
|
|
||||||
return Task.FromResult<ImageData?>(new("png", image.ToStream()));
|
return Task.FromResult<ImageData?>(new("png", image.ToStream()));
|
||||||
|
@ -177,7 +177,7 @@ public sealed class ImagesharpStockChartDrawingService : IStockChartDrawingServi
|
||||||
var points = GetSparklinePointsInternal(series);
|
var points = GetSparklinePointsInternal(series);
|
||||||
image.Mutate(ctx =>
|
image.Mutate(ctx =>
|
||||||
{
|
{
|
||||||
ctx.DrawLines(Color.ParseHex("00FFFFAA"), 1, points);
|
ctx.DrawLine(Color.ParseHex("00FFFFAA"), 1, points);
|
||||||
});
|
});
|
||||||
|
|
||||||
return Task.FromResult<ImageData?>(new("png", image.ToStream()));
|
return Task.FromResult<ImageData?>(new("png", image.ToStream()));
|
||||||
|
|
|
@ -994,23 +994,23 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
|
||||||
throw new ArgumentNullException(nameof(bgBytes));
|
throw new ArgumentNullException(nameof(bgBytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
var outlinePen = new Pen(Color.Black, 1f);
|
var outlinePen = new SolidPen(Color.Black, 1f);
|
||||||
|
|
||||||
using var img = Image.Load<Rgba32>(bgBytes, out var imageFormat);
|
using var img = Image.Load<Rgba32>(bgBytes);
|
||||||
if (template.User.Name.Show)
|
if (template.User.Name.Show)
|
||||||
{
|
{
|
||||||
var fontSize = (int)(template.User.Name.FontSize * 0.9);
|
var fontSize = (int)(template.User.Name.FontSize * 0.9);
|
||||||
var username = stats.User.ToString();
|
var username = stats.User.ToString();
|
||||||
var usernameFont = _fonts.NotoSans.CreateFont(fontSize, FontStyle.Bold);
|
var usernameFont = _fonts.NotoSans.CreateFont(fontSize, FontStyle.Bold);
|
||||||
|
|
||||||
var size = TextMeasurer.Measure($"@{username}", new(usernameFont));
|
var size = TextMeasurer.MeasureSize($"@{username}", new(usernameFont));
|
||||||
var scale = 400f / size.Width;
|
var scale = 400f / size.Width;
|
||||||
if (scale < 1)
|
if (scale < 1)
|
||||||
usernameFont = _fonts.NotoSans.CreateFont(template.User.Name.FontSize * scale, FontStyle.Bold);
|
usernameFont = _fonts.NotoSans.CreateFont(template.User.Name.FontSize * scale, FontStyle.Bold);
|
||||||
|
|
||||||
img.Mutate(x =>
|
img.Mutate(x =>
|
||||||
{
|
{
|
||||||
x.DrawText(new TextOptions(usernameFont)
|
x.DrawText(new RichTextOptions(usernameFont)
|
||||||
{
|
{
|
||||||
HorizontalAlignment = HorizontalAlignment.Left,
|
HorizontalAlignment = HorizontalAlignment.Left,
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
@ -1031,7 +1031,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
|
||||||
|
|
||||||
var clubFont = _fonts.NotoSans.CreateFont(template.Club.Name.FontSize, FontStyle.Regular);
|
var clubFont = _fonts.NotoSans.CreateFont(template.Club.Name.FontSize, FontStyle.Regular);
|
||||||
|
|
||||||
img.Mutate(x => x.DrawText(new TextOptions(clubFont)
|
img.Mutate(x => x.DrawText(new RichTextOptions(clubFont)
|
||||||
{
|
{
|
||||||
HorizontalAlignment = HorizontalAlignment.Right,
|
HorizontalAlignment = HorizontalAlignment.Right,
|
||||||
VerticalAlignment = VerticalAlignment.Top,
|
VerticalAlignment = VerticalAlignment.Top,
|
||||||
|
@ -1051,7 +1051,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
|
||||||
int maxSize)
|
int maxSize)
|
||||||
{
|
{
|
||||||
var font = fontFamily.CreateFont(fontSize, style);
|
var font = fontFamily.CreateFont(fontSize, style);
|
||||||
var size = TextMeasurer.Measure(text, new(font));
|
var size = TextMeasurer.MeasureSize(text, new(font));
|
||||||
var scale = maxSize / size.Width;
|
var scale = maxSize / size.Width;
|
||||||
if (scale < 1)
|
if (scale < 1)
|
||||||
font = fontFamily.CreateFont(fontSize * scale, style);
|
font = fontFamily.CreateFont(fontSize * scale, style);
|
||||||
|
@ -1114,7 +1114,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
|
||||||
if (template.User.Xp.Global.Show)
|
if (template.User.Xp.Global.Show)
|
||||||
{
|
{
|
||||||
img.Mutate(x => x.DrawText(
|
img.Mutate(x => x.DrawText(
|
||||||
new TextOptions(_fonts.NotoSans.CreateFont(template.User.Xp.Global.FontSize, FontStyle.Bold))
|
new RichTextOptions(_fonts.NotoSans.CreateFont(template.User.Xp.Global.FontSize, FontStyle.Bold))
|
||||||
{
|
{
|
||||||
HorizontalAlignment = HorizontalAlignment.Center,
|
HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
@ -1128,7 +1128,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
|
||||||
if (template.User.Xp.Guild.Show)
|
if (template.User.Xp.Guild.Show)
|
||||||
{
|
{
|
||||||
img.Mutate(x => x.DrawText(
|
img.Mutate(x => x.DrawText(
|
||||||
new TextOptions(_fonts.NotoSans.CreateFont(template.User.Xp.Guild.FontSize, FontStyle.Bold))
|
new RichTextOptions(_fonts.NotoSans.CreateFont(template.User.Xp.Guild.FontSize, FontStyle.Bold))
|
||||||
{
|
{
|
||||||
HorizontalAlignment = HorizontalAlignment.Center,
|
HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
@ -1152,7 +1152,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
|
||||||
new(awX, awY)));
|
new(awX, awY)));
|
||||||
}
|
}
|
||||||
|
|
||||||
var rankPen = new Pen(Color.White, 1);
|
var rankPen = new SolidPen(Color.White, 1);
|
||||||
//ranking
|
//ranking
|
||||||
if (template.User.GlobalRank.Show)
|
if (template.User.GlobalRank.Show)
|
||||||
{
|
{
|
||||||
|
@ -1166,7 +1166,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
|
||||||
68);
|
68);
|
||||||
|
|
||||||
img.Mutate(x => x.DrawText(
|
img.Mutate(x => x.DrawText(
|
||||||
new TextOptions(globalRankFont)
|
new RichTextOptions(globalRankFont)
|
||||||
{
|
{
|
||||||
Origin = new(template.User.GlobalRank.Pos.X, template.User.GlobalRank.Pos.Y)
|
Origin = new(template.User.GlobalRank.Pos.X, template.User.GlobalRank.Pos.Y)
|
||||||
},
|
},
|
||||||
|
@ -1188,7 +1188,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
|
||||||
43);
|
43);
|
||||||
|
|
||||||
img.Mutate(x => x.DrawText(
|
img.Mutate(x => x.DrawText(
|
||||||
new TextOptions(guildRankFont)
|
new RichTextOptions(guildRankFont)
|
||||||
{
|
{
|
||||||
Origin = new(template.User.GuildRank.Pos.X, template.User.GuildRank.Pos.Y)
|
Origin = new(template.User.GuildRank.Pos.X, template.User.GuildRank.Pos.Y)
|
||||||
},
|
},
|
||||||
|
@ -1231,7 +1231,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
using var toDraw = Image.Load(data);
|
using var toDraw = Image.Load(data);
|
||||||
if (toDraw.Size() != new Size(template.User.Icon.Size.X, template.User.Icon.Size.Y))
|
if (toDraw.Size != new Size(template.User.Icon.Size.X, template.User.Icon.Size.Y))
|
||||||
toDraw.Mutate(x => x.Resize(template.User.Icon.Size.X, template.User.Icon.Size.Y));
|
toDraw.Mutate(x => x.Resize(template.User.Icon.Size.X, template.User.Icon.Size.Y));
|
||||||
|
|
||||||
img.Mutate(x => x.DrawImage(toDraw,
|
img.Mutate(x => x.DrawImage(toDraw,
|
||||||
|
@ -1257,6 +1257,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
|
||||||
if (outputSize.X != img.Width || outputSize.Y != img.Height)
|
if (outputSize.X != img.Width || outputSize.Y != img.Height)
|
||||||
img.Mutate(x => x.Resize(template.OutputSize.X, template.OutputSize.Y));
|
img.Mutate(x => x.Resize(template.OutputSize.X, template.OutputSize.Y));
|
||||||
|
|
||||||
|
var imageFormat = img.Metadata.DecodedImageFormat;
|
||||||
var output = ((Stream)await img.ToStreamAsync(imageFormat), imageFormat);
|
var output = ((Stream)await img.ToStreamAsync(imageFormat), imageFormat);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
@ -1393,7 +1394,7 @@ public class XpService : IEService, IReadyExecutor, IExecNoCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
using var toDraw = Image.Load(data);
|
using var toDraw = Image.Load(data);
|
||||||
if (toDraw.Size() != new Size(template.Club.Icon.Size.X, template.Club.Icon.Size.Y))
|
if (toDraw.Size != new Size(template.Club.Icon.Size.X, template.Club.Icon.Size.Y))
|
||||||
toDraw.Mutate(x => x.Resize(template.Club.Icon.Size.X, template.Club.Icon.Size.Y));
|
toDraw.Mutate(x => x.Resize(template.Club.Icon.Size.X, template.Club.Icon.Size.Y));
|
||||||
|
|
||||||
img.Mutate(x => x.DrawImage(
|
img.Mutate(x => x.DrawImage(
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace EllieBot.Common.JsonConverters;
|
||||||
public class Rgba32Converter : JsonConverter<Rgba32>
|
public class Rgba32Converter : JsonConverter<Rgba32>
|
||||||
{
|
{
|
||||||
public override Rgba32 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
public override Rgba32 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
=> Rgba32.ParseHex(reader.GetString());
|
=> Rgba32.ParseHex(reader.GetString()!);
|
||||||
|
|
||||||
public override void Write(Utf8JsonWriter writer, Rgba32 value, JsonSerializerOptions options)
|
public override void Write(Utf8JsonWriter writer, Rgba32 value, JsonSerializerOptions options)
|
||||||
=> writer.WriteStringValue(value.ToHex());
|
=> writer.WriteStringValue(value.ToHex());
|
||||||
|
|
|
@ -24,7 +24,7 @@ public static class Rgba32Extensions
|
||||||
using var frame = imgArray[i].Frames.CloneFrame(frameNumber % imgArray[i].Frames.Count);
|
using var frame = imgArray[i].Frames.CloneFrame(frameNumber % imgArray[i].Frames.Count);
|
||||||
var offset = xOffset;
|
var offset = xOffset;
|
||||||
imgFrame.Mutate(x => x.DrawImage(frame, new Point(offset, 0), new GraphicsOptions()));
|
imgFrame.Mutate(x => x.DrawImage(frame, new Point(offset, 0), new GraphicsOptions()));
|
||||||
xOffset += imgArray[i].Bounds().Width;
|
xOffset += imgArray[i].Bounds.Width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue