XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEWarframe

【WinUI】基于Warframe游戏本体的公开服务器以及安装器

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Collections.ObjectModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Graphics.Imaging;

namespace XFEWarframe.Desktop.Editing;

internal static class RivenVerification
{
    internal static async Task VerifyAsync(FrameworkElement page, ObservableCollection<RivenStatRow> rows, Func<Task> calculate, Func<string> name, bool dialogs)
    {
        var positive = rows[0];
        positive.SelectedTag = positive.Tags.Single(x => x.Key == "WeaponFireDamageMod");
        var negative = rows[1];
        negative.SelectedTag = negative.Tags.Single(x => x.Key == "WeaponCritChanceMod");
        negative.Negative = true;
        await calculate();
        if (positive.Result.Contains('|') || !positive.Result.Contains('%') || !negative.Result.StartsWith('-') || name().Contains("Mod"))
            throw new InvalidOperationException("Riven title or formatted stat values are incorrect.");
        if (positive.Tags.Any(x => x.DisplayText.Contains('|') || !x.DisplayText.Any(char.IsDigit)))
            throw new InvalidOperationException("Riven alternatives contain placeholders or omit calculated values.");
        var original = positive.Result;
        positive.Value = 11000;
        await UntilAsync(() => positive.Result.Length > 0 && positive.Result != original && positive.Result.Contains('%'), "Riven preview did not refresh after changing quality.");
        var expected = positive.Tags.Single(x => x.Key == positive.SelectedTag.Key).DisplayValue!.Value;
        positive.ModeIndex = 1;
        if (positive.Value != expected) throw new InvalidOperationException("Actual-value mode retained the quality number.");
        await UntilAsync(() => positive.Result.Contains('%'), "Actual-value preview did not refresh.");
        if (!dialogs) return;
        var launcher = (FormDialogButton)page.FindName("RivenEditorButton");
        var showing = launcher.OpenAsync();
        try
        {
            await UntilAsync(() => launcher.ActiveDialog?.IsLoaded == true, "Riven dialog did not load.");
            var dialog = launcher.ActiveDialog!;
            dialog.UpdateLayout();
            var texts = DialogVerification.Children<TextBlock>(dialog).ToArray();
            var fire = texts.Single(x => x.Text == positive.Result && RivenStatText.GetTone(x) == "DT_FIRE_COLOR");
            var curse = texts.Single(x => x.Text == negative.Result && RivenStatText.GetTone(x) == "negative");
            if (((SolidColorBrush)fire.Foreground).Color == ((SolidColorBrush)curse.Foreground).Color)
                throw new InvalidOperationException("Element and negative stat colors were not applied.");
            var picker = DialogVerification.Children<AutoSuggestBox>(dialog).First(x => ReferenceEquals(Suggestions.GetCandidates(x), positive.Tags));
            picker.Focus(FocusState.Programmatic);
            await UntilAsync(() => picker.IsSuggestionListOpen, "Riven suggestion list did not open.");
            await UntilAsync(() => VisualTreeHelper.GetOpenPopupsForXamlRoot(dialog.XamlRoot).Any(x =>
                DialogVerification.Children<TextBlock>(x.Child).Any(t => t.Text == positive.Tags[0].DisplayText && t.IsLoaded)),
                "Riven suggestion list did not render its numeric alternatives.");
            var popup = VisualTreeHelper.GetOpenPopupsForXamlRoot(dialog.XamlRoot).First(x =>
                DialogVerification.Children<TextBlock>(x.Child).Any(t => t.Text == positive.Tags[0].DisplayText));
            var report = Environment.GetCommandLineArgs().First(x => x.StartsWith("--verify-ui=", StringComparison.Ordinal))["--verify-ui=".Length..];
            await Task.Delay(250); // Capture after the native popup's opening animation.
            await CaptureAsync(popup.Child, Path.ChangeExtension(report, ".riven.png"));
            if (!DialogVerification.Children<TextBlock>(popup.Child).Any(x => RivenStatText.GetTone(x) == "DT_FIRE_COLOR"))
                throw new InvalidOperationException("Riven suggestion template did not show colored numeric alternatives.");
            positive.ModeIndex = 0; positive.Value = 10000;
            await UntilAsync(() => positive.Result.Contains('%'), "Riven quality mode did not refresh.");
            positive.ModeIndex = 1;
            await UntilAsync(() => positive.Result.Contains('%'), "Riven actual-value mode did not refresh.");
            var alternate = positive.Tags.Single(x => x.Key == "WeaponCritChanceMod");
            var alternateValue = alternate.DisplayValue;
            await SuggestionVerification.TypeAsync(picker, alternate.Label);
            await SuggestionVerification.SubmitAsync(picker);
            await UntilAsync(() => positive.Result.Contains('%'), "Riven selected stat did not refresh.");
            if (!ReferenceEquals(positive.SelectedTag, alternate) || positive.Value != alternateValue || picker.Text != alternate.Label)
                throw new InvalidOperationException("Riven numeric suggestion selection did not preserve its label and calculated value.");
        }
        finally { launcher.ActiveDialog?.Hide(); await showing; }
    }
    private static async Task UntilAsync(Func<bool> condition, string error)
    {
        for (var i = 0; i < 200 && !condition(); i++) await Task.Delay(20);
        if (!condition()) throw new InvalidOperationException(error);
    }
    private static async Task CaptureAsync(UIElement element, string path)
    {
        var bitmap = new RenderTargetBitmap();
        await bitmap.RenderAsync(element);
        var pixels = (await bitmap.GetPixelsAsync()).ToArray();
        using var file = File.Create(path);
        using var stream = file.AsRandomAccessStream();
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
        encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, 96, 96, pixels);
        await encoder.FlushAsync();
    }
}