Files
MRCC/launcher/PCL-CE/Plain Craft Launcher 2/Pages/PageTools/PageToolsTest.xaml.cs
T
xyou f70b061d1a
CI / Go Backend (push) Canceled after 0s
feat: 项目初始化 + 3D方块世界原型 + AI助搭系统
初始化 monorepo: Go后端(7微服务) + Unity客户端(9模块) + 启动器

HTML5原型: Three.js 3D体素世界, Perlin噪声地形, 原版材质, 22种方块

Minecraft创造模式背包: 双栏布局, 拖拽移动物品, 方向性元件引脚

AI助搭策划文档 + 客户端/服务端骨架 + Docker Compose + CI
2026-08-08 14:07:56 +08:00

762 lines
28 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using PCL.Core.App;
using PCL.Core.App.Tools;
using PCL.Core.IO;
using PCL.Core.IO.Net;
using PCL.Core.UI;
using PCL.Core.Utils.OS;
using PCL.Core.Utils.Secret;
using PCL.Core.Utils.Validate;
using PCL.Network;
using PCL.Network.Loaders;
using PCL.Core.App.Localization;
using System.Globalization;
namespace PCL;
public partial class PageToolsTest
{
private Bitmap currentSkinBitmap;
private Bitmap generatedHeadBitmap;
private int headSize = 64;
private string skinPath = "";
public PageToolsTest()
{
InitializeComponent();
BtnSelectSkin.Click += BtnSelectSkin_Click;
CmbHeadSize.SelectionChanged += CmbHeadSize_SelectionChanged;
Loaded += (_, _) => MeLoaded();
#if DEBUG
BtnCrash.Visibility = Visibility.Visible;
#endif
}
private void MeLoaded()
{
BtnDownloadStart.IsEnabled = false;
TextDownloadFolder.Text = States.Tool.DownloadFolder;
TextDownloadFolder.Validate();
if (!string.IsNullOrEmpty(TextDownloadFolder.ValidateResult) || string.IsNullOrEmpty(TextDownloadFolder.Text))
TextDownloadFolder.Text = ModBase.exePath + @"PCL\MyDownload\";
TextDownloadFolder.Validate();
TextDownloadName.Validate();
TextDownloadUrl.Validate();
StartButtonRefresh();
}
private void StartButtonRefresh()
{
BtnDownloadStart.IsEnabled = string.IsNullOrEmpty(TextDownloadFolder.ValidateResult) &&
string.IsNullOrEmpty(TextDownloadUrl.ValidateResult) &&
string.IsNullOrEmpty(TextDownloadName.ValidateResult);
BtnDownloadOpen.IsEnabled = string.IsNullOrEmpty(TextDownloadFolder.ValidateResult);
BtnAchievementPreview.IsEnabled = string.IsNullOrEmpty(AchievementBlockTextBox.ValidateResult) &&
string.IsNullOrEmpty(AchievementTitleTextBox.ValidateResult) &&
string.IsNullOrEmpty(AchievementString1TextBox.ValidateResult);
BtnAchievementSave.IsEnabled = string.IsNullOrEmpty(AchievementBlockTextBox.ValidateResult) &&
string.IsNullOrEmpty(AchievementTitleTextBox.ValidateResult) &&
string.IsNullOrEmpty(AchievementString1TextBox.ValidateResult);
}
private void SaveCacheDownloadFolder(object sender, RoutedEventArgs e)
{
States.Tool.DownloadFolder = TextDownloadFolder.Text;
TextDownloadName.Validate();
}
private static void DownloadState(ModLoader.LoaderCombo<int> loader)
{
try
{
switch (loader.State)
{
case ModBase.LoadState.Finished:
{
HintService.Hint(Lang.Text("Tools.Test.CustomDownload.Finished", loader.name), HintType.Success);
Console.Beep();
break;
}
case ModBase.LoadState.Failed:
{
ModBase.Log(
loader.Error,
$"{loader.name}失败",
ModBase.LogLevel.Msgbox,
userSummary: Lang.Text("Tools.Test.Error.OperationFailed"));
Console.Beep();
break;
}
case ModBase.LoadState.Aborted:
{
HintService.Hint(Lang.Text("Tools.Test.CustomDownload.Aborted", loader.name));
break;
}
}
}
catch (Exception ex)
{
}
}
public static void StartCustomDownload(string url, string fileName, string folder = null, string userAgent = "")
{
try
{
if (string.IsNullOrWhiteSpace(folder))
{
folder = SystemDialogs.SelectSaveFile(Lang.Text("Tools.Test.CustomDownload.SelectLocation"), fileName);
if (!folder.Contains(@"\")) return;
if (folder.EndsWith(fileName)) folder = folder[..^fileName.Length];
}
folder = folder.Replace("/", @"\").TrimEnd(new[] { '\\' }) + @"\";
try
{
Directory.CreateDirectory(folder);
ModBase.CheckPermissionWithException(folder);
}
catch (Exception ex)
{
ModBase.Log(
ex,
$"访问文件夹失败({folder}",
ModBase.LogLevel.Hint,
userSummary: Lang.Text("Tools.Test.Error.OperationFailed"));
return;
}
ModBase.Log("[Download] 自定义下载文件名:" + fileName);
ModBase.Log("[Download] 自定义下载文件目标:" + folder);
var uuid = ModBase.GetUuid();
ModLoader.LoaderBase loaderdownload;
if (new HttpValidator().Validate(url).IsValid)
loaderdownload = new LoaderDownload(Lang.Text("Tools.Test.CustomDownload.LoaderName", fileName),
new List<DownloadFile> { new(new[] { url }, folder + fileName, null, true, userAgent) });
else // UNC 路径
loaderdownload = new LoaderDownloadUnc(Lang.Text("Tools.Test.CustomDownload.LoaderName", fileName),
new Tuple<string, string>(url, folder + fileName));
var loaderCombo = new ModLoader.LoaderCombo<int>(Lang.Text("Tools.Test.CustomDownload.LoaderTitle", uuid), new[] { loaderdownload })
{ OnStateChanged = a => DownloadState((ModLoader.LoaderCombo<int>)a) };
loaderCombo.Start();
ModLoader.LoaderTaskbarAdd(loaderCombo);
ModMain.frmMain.BtnExtraDownload.ShowRefresh();
ModMain.frmMain.BtnExtraDownload.Ribble();
}
catch (Exception ex)
{
ModBase.Log(
ex,
"开始自定义下载失败",
ModBase.LogLevel.Feedback,
userSummary: Lang.Text("Tools.Test.Error.OperationFailed"));
}
}
public static void Jrrp()
{
var random = new Random(GenerateDailySeed());
var luckValue = random.Next(0, 101);
var rating = GetRating(luckValue);
var title = Lang.Text("Tools.Test.Luck.MsgboxTitle", Lang.Date(DateTime.Now, "d"));
if (luckValue >= 60)
ModMain.MyMsgBox(Lang.Text("Tools.Test.Luck.MessageGood", luckValue, rating), title);
else
ModMain.MyMsgBox(Lang.Text("Tools.Test.Luck.MessageBad", luckValue, rating), title, isWarn: luckValue <= 30);
}
public static void RubbishClear()
{
ModBase.RunInUi(() =>
{
if (ModMain.frmToolsTest is not null && ModMain.frmToolsTest.BtnClear is not null)
ModMain.frmToolsTest.BtnClear.IsEnabled = false;
});
// 只有当没有运行中的Minecraft游戏且启动器不在加载状态时才能清理
// 清理的文件数量
// 所有 Minecraft 文件夹
// 寻找所有 Minecraft 文件夹
// 删除 Minecraft 的缓存
// 删除日志和崩溃报告并计数
// 删除 Natives 文件
// 删除 PCL 的缓存
ModBase.RunInNewThread(() =>
{
try
{
if (!ModWatcher.hasRunningMinecraft && ModLaunch.mcLaunchLoader.State != ModBase.LoadState.Loading)
{
if (ModNet.HasDownloadingTask())
{
HintService.Hint(Lang.Text("Tools.Test.Clean.WaitForDownload"));
return;
}
if (!ModFolder.mcFolderList.Any()) ModFolder.mcFolderListLoader.Start();
if (States.Hint.CleanJunkFile <= 2)
{
if (ModMain.MyMsgBox(
Lang.Text("Tools.Test.Clean.ConfirmMessage"),
Lang.Text("Tools.Test.Clean.ConfirmTitle"),
Lang.Text("Common.Action.Confirm"),
Lang.Text("Common.Action.Cancel")
) == 2) return;
States.Hint.CleanJunkFile += 1;
}
var num = 0;
var cleanMcFolderList = new List<DirectoryInfo>();
if (!ModFolder.mcFolderList.Any()) ModFolder.mcFolderListLoader.WaitForExit();
foreach (var mcFolder in ModFolder.mcFolderList)
{
cleanMcFolderList.Add(new DirectoryInfo(mcFolder.Location));
var dirInfo = new DirectoryInfo(mcFolder.Location + "versions");
if (dirInfo.Exists)
foreach (var item in dirInfo.EnumerateDirectories())
cleanMcFolderList.Add(item);
}
foreach (var dirInfo in cleanMcFolderList)
{
num += ModBase.DeleteDirectory(
dirInfo.FullName + (dirInfo.FullName.EndsWith(@"\") ? "" : @"\") + @"crash-reports\", true);
num += ModBase.DeleteDirectory(
dirInfo.FullName + (dirInfo.FullName.EndsWith(@"\") ? "" : @"\") + @"logs\", true);
foreach (var fileInfo in dirInfo.EnumerateFiles("*"))
if (fileInfo.Name.StartsWith("hs_err_pid") || fileInfo.Name.EndsWith(".log") ||
fileInfo.Name == "WailaErrorOutput.txt")
{
fileInfo.Delete();
num += 1;
}
foreach (var dirInfo2 in dirInfo.EnumerateDirectories())
if ((dirInfo2.Name ?? "") == (dirInfo2.Name + "-natives" ?? "") ||
dirInfo2.Name == "natives-windows-x86_64")
num += ModBase.DeleteDirectory(dirInfo2.FullName, true);
}
num += ModBase.DeleteDirectory(ModBase.pathTemp, true);
num += ModBase.DeleteDirectory(Path.Combine(SystemPaths.DriveLetter, "ProgramData", "PCL"), true);
if (num != 0)
{
ModMain.MyMsgBox(Lang.Text("Tools.Test.Clean.ClearedMessage", num),
Lang.Text("Tools.Test.Clean.Cleared"), Lang.Text("Common.Action.Confirm"), "", "", false, true, true);
Process.Start(new ProcessStartInfo(Basics.ExecutablePath));
FormMain.EndProgramForce();
}
else
{
HintService.Hint(Lang.Text("Tools.Test.Clean.NoFiles"));
}
}
else
{
HintService.Hint(Lang.Text("Tools.Test.Clean.CloseGameFirst"));
}
}
catch (Exception ex)
{
ModBase.Log(
ex,
"清理垃圾失败",
ModBase.LogLevel.Hint,
userSummary: Lang.Text("Tools.Test.Error.OperationFailed"));
}
finally
{
ModBase.RunInUiWait(() =>
{
if (ModMain.frmToolsTest is not null && ModMain.frmToolsTest.BtnClear is not null)
ModMain.frmToolsTest.BtnClear.IsEnabled = true;
});
}
}, "Rubbish Clear");
}
public static string GetRandomCave()
{
return Lang.Text("Tools.Test.CeNotice");
}
public static string GetRandomHint()
{
return Lang.Text("Tools.Test.CeNotice");
}
public static string GetRandomPresetHint()
{
return Lang.Text("Tools.Test.CeNotice");
}
private void TextDownloadUrl_TextChanged(object sender, TextChangedEventArgs e)
{
try
{
if (!string.IsNullOrEmpty(TextDownloadName.Text) || string.IsNullOrEmpty(TextDownloadUrl.Text)) return;
TextDownloadName.Text = ModBase.GetFileNameFromPath(WebUtility.UrlDecode(TextDownloadUrl.Text));
StartButtonRefresh();
}
catch
{
}
}
private void MyTextButton_Click(object sender, EventArgs e)
{
var text = SystemDialogs.SelectFolder();
if (!string.IsNullOrEmpty(text)) TextDownloadFolder.Text = text;
}
private void BtnDownloadOpen_Click(object sender, MouseButtonEventArgs e)
{
try
{
var text = TextDownloadFolder.Text;
Directory.CreateDirectory(text);
Basics.OpenPath(text);
}
catch (Exception ex)
{
ModBase.Log(ex, "打开下载文件夹失败");
}
}
private void BtnDownloadStart_Click(object sender, MouseButtonEventArgs e)
{
StartCustomDownload(TextDownloadUrl.Text, TextDownloadName.Text, TextDownloadFolder.Text);
TextDownloadUrl.Text = "";
TextDownloadUrl.Validate();
TextDownloadUrl.ForceShowAsSuccess();
TextDownloadName.Text = "";
TextDownloadName.Validate();
TextDownloadName.ForceShowAsSuccess();
StartButtonRefresh();
}
private void TextDownloadUrl_ValidateChanged(object sender, RoutedEventArgs e)
{
StartButtonRefresh();
}
private void TextDownloadFolder_ValidateChanged(object sender, EventArgs e)
{
StartButtonRefresh();
}
private void TextDownloadName_ValidateChanged(object sender, EventArgs e)
{
StartButtonRefresh();
}
private void BtnClear_Click(object sender, MouseButtonEventArgs e)
{
RubbishClear();
}
// 下载正版玩家皮肤
private void BtnSkinSave_Click(object sender, MouseButtonEventArgs e)
{
var id = TextSkinID.Text;
HintService.Hint(Lang.Text("Tools.Test.Skin.Fetching"));
ModBase.RunInNewThread(() =>
{
try
{
if (id.Length < 3)
{
HintService.Hint(Lang.Text("Tools.Test.Skin.InvalidId"));
}
else
{
var result = (string)ModProfile.McLoginMojangUuid(id, true);
result = ModSkin.McSkinGetAddress(result, "Mojang");
result = ModSkin.McSkinDownload(result);
ModBase.RunInUi(() =>
{
var path = SystemDialogs.SelectSaveFile(Lang.Text("Tools.Test.Skin.Save"), $"{id}.png", Lang.Text("Tools.Test.Skin.FileFilter"));
ModBase.CopyFile(result, path);
HintService.Hint(Lang.Text("Tools.Test.Skin.Saved", id), HintType.Success);
});
}
}
catch (Exception ex)
{
if (ex.ToString().Contains("429"))
{
HintService.Hint(Lang.Text("Tools.Test.Skin.TooFrequent"), HintType.Error);
ModBase.Log($"获取正版皮肤失败({id}):获取皮肤太过频繁,请 5 分钟后再试!");
}
else
{
ModBase.Log(ex, $"获取正版皮肤失败({id}");
}
}
});
}
// 今日人品
private void BtnLuck_Click(object sender, MouseButtonEventArgs e)
{
Jrrp();
}
public static int GenerateDailySeed()
{
var datePart = DateTime.Today.ToString("yyyyMMdd", CultureInfo.InvariantCulture);
return DJB2Hash(datePart + Identify.LauncherId);
}
private static int DJB2Hash(string str)
{
var hash = 5381L;
var prime = 33L;
foreach (var c in str)
{
long charValue = c;
hash = (hash * prime + charValue) % 0x100000000L;
}
return (int)(hash & 0x7FFFFFFFL);
}
public static string GetRating(int luckValue)
{
var key = luckValue switch
{
100 => "Tools.Test.Luck.Rating100",
>= 95 => "Tools.Test.Luck.Rating95",
>= 90 => "Tools.Test.Luck.Rating90",
>= 60 => "Tools.Test.Luck.Rating60",
>= 40 => "Tools.Test.Luck.Rating40",
>= 30 => "Tools.Test.Luck.Rating30",
>= 10 => "Tools.Test.Luck.Rating10",
_ => "Tools.Test.Luck.Rating0"
};
return Lang.Text(key);
}
private void BtnCreateShortcut_Click(object sender, MouseButtonEventArgs e)
{
var shortcutName = Lang.Text("Tools.Test.Shortcut.FileName", ".lnk");
var desktopName = Lang.Text("Tools.Test.Shortcut.Desktop");
var startName = Lang.Text("Tools.Test.Shortcut.StartMenu");
var desktop = Paths.GetSpecialPath(Environment.SpecialFolder.Desktop, shortcutName);
var start = Paths.GetSpecialPath(Environment.SpecialFolder.StartMenu, @"Programs\" + shortcutName);
var choice =
ModMain.MyMsgBox(
Lang.Text("Tools.Test.Shortcut.ConfirmMessage", desktopName, desktop, startName, start),
Lang.Text("Tools.Test.Shortcut.SelectLocation"), Lang.Text("Common.Action.Cancel"), desktopName, startName);
if (choice == 1)
return;
var shortcutPath = choice == 2 ? desktop : start;
var locationName = choice == 2 ? desktopName : startName;
Files.CreateShortcut(shortcutPath, Basics.ExecutablePath);
HintService.Hint(Lang.Text("Tools.Test.Shortcut.Created", locationName), HintType.Success);
}
// 启动计数显示
private void BtnLaunchCount_Click(object sender, MouseButtonEventArgs e)
{
ModMain.MyMsgBox(Lang.Text("Tools.Test.LaunchCount.Message", States.System.LaunchCount), Lang.Text("Tools.Test.LaunchCount.Title"));
}
private async void BtnAchievementPreview_Click(object sender, MouseButtonEventArgs e)
{
var url = GetAchievementUrl();
ModBase.Log("[Net] 获取网络结果" + url);
await LoadImageAsync(url);
}
private async Task LoadImageAsync(string imageUrl)
{
var client = NetworkService.GetClient();
try
{
var response = await client.GetAsync(imageUrl);
if (response.IsSuccessStatusCode)
using (var stream = await response.Content.ReadAsStreamAsync())
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
bitmapImage.Freeze();
Dispatcher.Invoke(() =>
{
AchievementImage.Source = bitmapImage;
AchievementImage.Visibility = Visibility.Visible;
});
}
else if (response.StatusCode == HttpStatusCode.NotFound)
Dispatcher.Invoke(() =>
{
ModBase.Log("获取成就图片失败(404");
HintService.Hint(Lang.Text("Tools.Test.Achievement.FetchFailed"), HintType.Error);
});
else
Dispatcher.Invoke(() => ModBase.Log("获取成就图片失败(" + (int)response.StatusCode + ""));
}
catch (Exception ex)
{
Dispatcher.Invoke(() => ModBase.Log(ex, "获取成就图片失败"));
}
}
private async void BtnAchievementSave_Click(object sender, MouseButtonEventArgs e)
{
var url = GetAchievementUrl();
await DownloadImageToLocalAsync(url);
}
private async Task DownloadImageToLocalAsync(string imageUrl)
{
var savePath = ModBase.pathTemp + @"Download\" + ModBase.GetHash(imageUrl) + ".png";
var client = NetworkService.GetClient();
try
{
// 异步发送 GET 请求
var response = await client.GetAsync(imageUrl);
// 如果响应状态码是成功的,则继续
if (response.IsSuccessStatusCode)
{
// 异步读取响应内容为字节流
var imageBytes = await response.Content.ReadAsByteArrayAsync();
// 将字节写入本地文件
File.WriteAllBytes(savePath, imageBytes);
var path =
SystemDialogs.SelectSaveFile(Lang.Text("Tools.Test.Achievement.Save"), AchievementTitleTextBox.Text + ".png", Lang.Text("Tools.Test.Achievement.FileFilter"));
if (string.IsNullOrEmpty(path))
{
ModBase.Log("用户取消了保存操作");
File.Delete(savePath);
return;
}
ModBase.CopyFile(savePath, path);
File.Delete(savePath);
HintService.Hint(Lang.Text("Tools.Test.Achievement.Saved"), HintType.Success);
}
// 下载成功,返回 True
else if (response.StatusCode == HttpStatusCode.NotFound)
{
// 捕获 404 错误
ModBase.Log("获取成就图片失败(404");
HintService.Hint(Lang.Text("Tools.Test.Achievement.FetchFailed"), HintType.Error);
}
else
{
// 处理其他非成功状态码
ModBase.Log("获取成就图片失败(" + (int)response.StatusCode + "");
}
}
catch (Exception ex)
{
// 捕获所有其他异常(如网络连接问题)
ModBase.Log(ex, "获取成就图片失败");
}
}
private string GetAchievementUrl()
{
var block = AchievementBlockTextBox.Text.Trim();
var title = AchievementTitleTextBox.Text.Replace(" ", "..");
var str1 = AchievementString1TextBox.Text.Replace(" ", "..");
var str2 = AchievementString2TextBox.Text.Replace(" ", "..");
var url = $"https://minecraft-api.com/api/achivements/{block}/{title}/{str1}";
if (!string.IsNullOrEmpty(str2)) url += $"/{str2}";
return url;
}
private void BtnCrash_Click(object sender, MouseButtonEventArgs e)
{
throw new Exception(Lang.Text("Tools.Test.Crash.ManualCrash"));
}
private int GetHeadSize() => CmbHeadSize.SelectedIndex switch
{
0 => 64,
1 => 96,
2 => 128,
_ => 64
};
private void BtnSelectSkin_Click(object sender, RoutedEventArgs e)
{
var filePath = SystemDialogs.SelectFile(Lang.Text("Tools.Test.Avatar.FileFilter"),
Lang.Text("Tools.Test.Avatar.SelectSkinFile"));
if (!string.IsNullOrEmpty(filePath)) LoadAndGenerateHead(filePath);
}
private void LoadAndGenerateHead(string skinPath)
{
try
{
using (var stream = new FileStream(skinPath, FileMode.Open, FileAccess.Read))
{
currentSkinBitmap = new Bitmap(stream);
}
this.skinPath = skinPath;
if (currentSkinBitmap.Width != currentSkinBitmap.Height)
{
HintService.Hint(Lang.Text("Tools.Test.Avatar.InvalidSize"), HintType.Error);
SkinPreviewBorder.Visibility = Visibility.Collapsed;
return;
}
generatedHeadBitmap = GenerateHeadFromSkin(currentSkinBitmap);
ImgFace.Source = BitmapToBitmapImage(generatedHeadBitmap);
ImgHair.Source = null;
SkinPreviewBorder.Visibility = Visibility.Visible;
HintService.Hint(Lang.Text("Tools.Test.Avatar.Generated"), HintType.Success);
}
catch (Exception ex)
{
ModBase.Log(ex, "生成头像失败");
HintService.Hint(Lang.Text("Tools.Test.Avatar.GenerateFailed", ex.Message), HintType.Error);
SkinPreviewBorder.Visibility = Visibility.Collapsed;
}
}
private Bitmap GenerateHeadFromSkin(Bitmap skinBitmap)
{
var scale = skinBitmap.Width / 64;
headSize = GetHeadSize();
var headBitmap = new Bitmap(headSize, headSize);
using (var g = Graphics.FromImage(headBitmap))
{
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.PixelOffsetMode = PixelOffsetMode.Half;
DrawFaceLayer(g, skinBitmap, scale);
if (skinBitmap.Width >= 64) DrawHairLayer(headBitmap, skinBitmap, scale);
}
return headBitmap;
}
private void DrawFaceLayer(Graphics g, Bitmap skinBitmap, int scale)
{
var faceRect = new Rectangle(8 * scale, 8 * scale, 8 * scale, 8 * scale);
var faceSize = headSize - headSize / 8;
var faceScaled = new Bitmap(faceSize, faceSize);
using (var gFace = Graphics.FromImage(faceScaled))
{
gFace.InterpolationMode = InterpolationMode.NearestNeighbor;
gFace.PixelOffsetMode = PixelOffsetMode.Half;
gFace.DrawImage(skinBitmap, new Rectangle(0, 0, faceSize, faceSize), faceRect, GraphicsUnit.Pixel);
}
var offset = headSize / 16;
g.DrawImage(faceScaled, offset, offset, faceSize, faceSize);
}
private void DrawHairLayer(Bitmap headBitmap, Bitmap skinBitmap, int scale)
{
var hairRect = new Rectangle(40 * scale, 8 * scale, 8 * scale, 8 * scale);
var hairScaled = new Bitmap(headSize, headSize);
using (var gHair = Graphics.FromImage(hairScaled))
{
gHair.InterpolationMode = InterpolationMode.NearestNeighbor;
gHair.PixelOffsetMode = PixelOffsetMode.Half;
gHair.DrawImage(skinBitmap, new Rectangle(0, 0, headSize, headSize), hairRect, GraphicsUnit.Pixel);
}
for (int x = 0, loopTo = headSize - 1; x <= loopTo; x++)
for (int y = 0, loopTo1 = headSize - 1; y <= loopTo1; y++)
{
var pixel = hairScaled.GetPixel(x, y);
if (pixel.A > 0) headBitmap.SetPixel(x, y, pixel);
}
}
private void BtnSaveHead_Click(object sender, MouseButtonEventArgs e)
{
if (generatedHeadBitmap is null)
{
HintService.Hint(Lang.Text("Tools.Test.Avatar.SelectFirst"), HintType.Error);
return;
}
var savePath = SystemDialogs.SelectSaveFile(Lang.Text("Tools.Test.Avatar.Save"), "Head.png");
if (string.IsNullOrEmpty(savePath))
return;
generatedHeadBitmap.Save(savePath, ImageFormat.Png);
HintService.Hint(Lang.Text("Tools.Test.Avatar.Saved"), HintType.Success);
}
private void CmbHeadSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (currentSkinBitmap is not null && skinPath is not null) LoadAndGenerateHead(skinPath);
}
private BitmapImage BitmapToBitmapImage(Bitmap bitmap)
{
using (var memoryStream = new MemoryStream())
{
bitmap.Save(memoryStream, ImageFormat.Png);
memoryStream.Position = 0L;
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = memoryStream;
bitmapImage.EndInit();
bitmapImage.Freeze();
return bitmapImage;
}
}
private void TextDownloadFolder_OnValidatedTextChanged(object sender, RoutedEventArgs e)
{
SaveCacheDownloadFolder(sender, e);
TextDownloadName_ValidateChanged(sender, e);
}
}