mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
launch game impl switch monitor
This commit is contained in:
@@ -253,4 +253,4 @@ internal static class LocalSetting
|
|||||||
{
|
{
|
||||||
Container.Values[key] = value;
|
Container.Values[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@ internal static class Localization
|
|||||||
/// <param name="culture">语言代码</param>
|
/// <param name="culture">语言代码</param>
|
||||||
public static void Initialize(string culture)
|
public static void Initialize(string culture)
|
||||||
{
|
{
|
||||||
CultureInfo cultureInfo = CultureInfo.CreateSpecificCulture(culture);
|
CultureInfo cultureInfo = CultureInfo.GetCultureInfo(culture);
|
||||||
CultureInfo.CurrentCulture = cultureInfo;
|
CultureInfo.CurrentCulture = cultureInfo;
|
||||||
CultureInfo.CurrentUICulture = cultureInfo;
|
CultureInfo.CurrentUICulture = cultureInfo;
|
||||||
ApplicationLanguages.PrimaryLanguageOverride = culture;
|
ApplicationLanguages.PrimaryLanguageOverride = culture;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ internal sealed class WindowSubclassManager<TWindow> : IDisposable
|
|||||||
private readonly bool isLegacyDragBar;
|
private readonly bool isLegacyDragBar;
|
||||||
private HWND hwndDragBar;
|
private HWND hwndDragBar;
|
||||||
|
|
||||||
// We have to explictly hold a reference to SUBCLASSPROC
|
// We have to explicitly hold a reference to SUBCLASSPROC
|
||||||
private SUBCLASSPROC? windowProc;
|
private SUBCLASSPROC? windowProc;
|
||||||
private SUBCLASSPROC? dragBarProc;
|
private SUBCLASSPROC? dragBarProc;
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,11 @@ internal sealed class SettingEntry
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public const string LaunchTargetFps = "Launch.TargetFps";
|
public const string LaunchTargetFps = "Launch.TargetFps";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 启动游戏 显示器编号
|
||||||
|
/// </summary>
|
||||||
|
public const string LaunchMonitor = "Launch.Monitor";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 语言
|
/// 语言
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Snap.Hutao.Model.Calculable;
|
|||||||
using Snap.Hutao.Model.Metadata.Abstraction;
|
using Snap.Hutao.Model.Metadata.Abstraction;
|
||||||
using Snap.Hutao.Model.Metadata.Converter;
|
using Snap.Hutao.Model.Metadata.Converter;
|
||||||
using Snap.Hutao.Model.Metadata.Item;
|
using Snap.Hutao.Model.Metadata.Item;
|
||||||
|
using Snap.Hutao.ViewModel.Complex;
|
||||||
using Snap.Hutao.ViewModel.GachaLog;
|
using Snap.Hutao.ViewModel.GachaLog;
|
||||||
|
|
||||||
namespace Snap.Hutao.Model.Metadata.Avatar;
|
namespace Snap.Hutao.Model.Metadata.Avatar;
|
||||||
@@ -19,7 +20,7 @@ internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IName
|
|||||||
/// [非元数据] 搭配数据
|
/// [非元数据] 搭配数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public ComplexAvatarCollocation? Collocation { get; set; }
|
public AvatarCollocationView? Collocation { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// [非元数据] 烹饪奖励
|
/// [非元数据] 烹饪奖励
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using Snap.Hutao.Model.Binding.Hutao;
|
|
||||||
using Snap.Hutao.Model.Calculable;
|
using Snap.Hutao.Model.Calculable;
|
||||||
using Snap.Hutao.Model.Intrinsic;
|
using Snap.Hutao.Model.Intrinsic;
|
||||||
using Snap.Hutao.Model.Metadata.Abstraction;
|
using Snap.Hutao.Model.Metadata.Abstraction;
|
||||||
using Snap.Hutao.Model.Metadata.Converter;
|
using Snap.Hutao.Model.Metadata.Converter;
|
||||||
|
using Snap.Hutao.ViewModel.Complex;
|
||||||
using Snap.Hutao.ViewModel.GachaLog;
|
using Snap.Hutao.ViewModel.GachaLog;
|
||||||
|
|
||||||
namespace Snap.Hutao.Model.Metadata.Weapon;
|
namespace Snap.Hutao.Model.Metadata.Weapon;
|
||||||
@@ -19,7 +19,7 @@ internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource
|
|||||||
/// [非元数据] 搭配数据
|
/// [非元数据] 搭配数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public ComplexWeaponCollocation? Collocation { get; set; }
|
public WeaponCollocationView? Collocation { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
|||||||
@@ -10,8 +10,11 @@ MINMAXINFO
|
|||||||
|
|
||||||
// COMCTL32
|
// COMCTL32
|
||||||
DefSubclassProc
|
DefSubclassProc
|
||||||
SetWindowSubclass
|
|
||||||
RemoveWindowSubclass
|
RemoveWindowSubclass
|
||||||
|
SetWindowSubclass
|
||||||
|
|
||||||
|
// GDI32
|
||||||
|
GetDeviceCaps
|
||||||
|
|
||||||
// KERNEL32
|
// KERNEL32
|
||||||
CreateEvent
|
CreateEvent
|
||||||
@@ -27,6 +30,7 @@ CoWaitForMultipleObjects
|
|||||||
|
|
||||||
// USER32
|
// USER32
|
||||||
FindWindowEx
|
FindWindowEx
|
||||||
|
GetDC
|
||||||
GetDpiForWindow
|
GetDpiForWindow
|
||||||
GetWindowPlacement
|
GetWindowPlacement
|
||||||
|
|
||||||
|
|||||||
136
src/Snap.Hutao/Snap.Hutao/Option/AppOptions.cs
Normal file
136
src/Snap.Hutao/Snap.Hutao/Option/AppOptions.cs
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.UI.Windowing;
|
||||||
|
using Snap.Hutao.Core.Database;
|
||||||
|
using Snap.Hutao.Model.Entity;
|
||||||
|
using Snap.Hutao.Model.Entity.Database;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Option;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应用程序选项
|
||||||
|
/// </summary>
|
||||||
|
[Injection(InjectAs.Singleton)]
|
||||||
|
internal sealed class AppOptions : IOptions<AppOptions>
|
||||||
|
{
|
||||||
|
private readonly IServiceScopeFactory serviceScopeFactory;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造一个新的应用程序选项
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceScopeFactory">服务范围工厂</param>
|
||||||
|
public AppOptions(IServiceScopeFactory serviceScopeFactory)
|
||||||
|
{
|
||||||
|
this.serviceScopeFactory = serviceScopeFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 游戏路径
|
||||||
|
/// </summary>
|
||||||
|
public string? GamePath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
return appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.GamePath)?.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.GamePath);
|
||||||
|
appDbContext.Settings.AddAndSave(new(SettingEntry.GamePath, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 游戏路径
|
||||||
|
/// </summary>
|
||||||
|
public bool IsEmptyHistoryWishVisible
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.IsEmptyHistoryWishVisible)?.Value;
|
||||||
|
return value != null && bool.Parse(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.IsEmptyHistoryWishVisible);
|
||||||
|
appDbContext.Settings.AddAndSave(new(SettingEntry.IsEmptyHistoryWishVisible, value.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 背景类型 默认 Mica
|
||||||
|
/// </summary>
|
||||||
|
public Core.Windowing.BackdropType BackdropType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.SystemBackdropType)?.Value;
|
||||||
|
return Enum.Parse<Core.Windowing.BackdropType>(value ?? nameof(Core.Windowing.BackdropType.Mica));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.SystemBackdropType);
|
||||||
|
appDbContext.Settings.AddAndSave(new(SettingEntry.SystemBackdropType, value.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前语言
|
||||||
|
/// </summary>
|
||||||
|
public CultureInfo CurrentCulture
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.Culture)?.Value;
|
||||||
|
return value != null ? CultureInfo.GetCultureInfo(value) : CultureInfo.CurrentCulture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.Culture);
|
||||||
|
appDbContext.Settings.AddAndSave(new(SettingEntry.Culture, value.Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public AppOptions Value { get => this; }
|
||||||
|
}
|
||||||
@@ -59,7 +59,6 @@ public static partial class Program
|
|||||||
.AddDatabase()
|
.AddDatabase()
|
||||||
.AddInjections()
|
.AddInjections()
|
||||||
.AddHttpClients()
|
.AddHttpClients()
|
||||||
|
|
||||||
// Discrete services
|
// Discrete services
|
||||||
.AddSingleton<IMessenger>(WeakReferenceMessenger.Default)
|
.AddSingleton<IMessenger>(WeakReferenceMessenger.Default)
|
||||||
|
|
||||||
|
|||||||
@@ -2139,6 +2139,15 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 无圣遗物或散件 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewModelComplexReliquarySetViewEmptyName {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewModelComplexReliquarySetViewEmptyName", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 养成计划添加失败 的本地化字符串。
|
/// 查找类似 养成计划添加失败 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -3687,6 +3696,24 @@ namespace Snap.Hutao.Resource.Localization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 在指定的显示器上运行 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewPageLaunchGameMonitorsDescription {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewPageLaunchGameMonitorsDescription", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 显示器 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
internal static string ViewPageLaunchGameMonitorsHeader {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ViewPageLaunchGameMonitorsHeader", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 在游戏时可以随时调整 的本地化字符串。
|
/// 查找类似 在游戏时可以随时调整 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -810,6 +810,9 @@
|
|||||||
<data name="ViewModelAvatarPropertyShowcaseNotOpen" xml:space="preserve">
|
<data name="ViewModelAvatarPropertyShowcaseNotOpen" xml:space="preserve">
|
||||||
<value>角色展柜尚未开启,请前往游戏操作后重试</value>
|
<value>角色展柜尚未开启,请前往游戏操作后重试</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewModelComplexReliquarySetViewEmptyName" xml:space="preserve">
|
||||||
|
<value>无圣遗物或散件</value>
|
||||||
|
</data>
|
||||||
<data name="ViewModelCultivationAddWarning" xml:space="preserve">
|
<data name="ViewModelCultivationAddWarning" xml:space="preserve">
|
||||||
<value>养成计划添加失败</value>
|
<value>养成计划添加失败</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -1326,6 +1329,12 @@
|
|||||||
<data name="ViewPageLaunchGameElevationHint" xml:space="preserve">
|
<data name="ViewPageLaunchGameElevationHint" xml:space="preserve">
|
||||||
<value>某些选项处于禁用状态,它们只在管理员模式下生效!</value>
|
<value>某些选项处于禁用状态,它们只在管理员模式下生效!</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewPageLaunchGameMonitorsDescription" xml:space="preserve">
|
||||||
|
<value>在指定的显示器上运行</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewPageLaunchGameMonitorsHeader" xml:space="preserve">
|
||||||
|
<value>显示器</value>
|
||||||
|
</data>
|
||||||
<data name="ViewPageLaunchGameSetFpsDescription" xml:space="preserve">
|
<data name="ViewPageLaunchGameSetFpsDescription" xml:space="preserve">
|
||||||
<value>在游戏时可以随时调整</value>
|
<value>在游戏时可以随时调整</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ internal sealed class GameService : IGameService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async ValueTask LaunchAsync(LaunchConfiguration configuration)
|
public async ValueTask LaunchAsync(LaunchOptions options)
|
||||||
{
|
{
|
||||||
if (IsGameRunning())
|
if (IsGameRunning())
|
||||||
{
|
{
|
||||||
@@ -321,13 +321,13 @@ internal sealed class GameService : IGameService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// https://docs.unity.cn/cn/current/Manual/PlayerCommandLineArguments.html
|
// https://docs.unity.cn/cn/current/Manual/PlayerCommandLineArguments.html
|
||||||
// TODO: impl monitor option.
|
|
||||||
string commandLine = new CommandLineBuilder()
|
string commandLine = new CommandLineBuilder()
|
||||||
.AppendIf("-popupwindow", configuration.IsBorderless)
|
.AppendIf("-popupwindow", options.IsBorderless)
|
||||||
.Append("-screen-fullscreen", configuration.IsFullScreen ? 1 : 0)
|
.Append("-screen-fullscreen", options.IsFullScreen ? 1 : 0)
|
||||||
.AppendIf("-window-mode", configuration.IsExclusive, "exclusive")
|
.AppendIf("-window-mode", options.IsExclusive, "exclusive")
|
||||||
.Append("-screen-width", configuration.ScreenWidth)
|
.Append("-screen-width", options.ScreenWidth)
|
||||||
.Append("-screen-height", configuration.ScreenHeight)
|
.Append("-screen-height", options.ScreenHeight)
|
||||||
|
.Append("-monitor", options.Monitor.Value)
|
||||||
.ToString();
|
.ToString();
|
||||||
|
|
||||||
Process game = new()
|
Process game = new()
|
||||||
@@ -344,9 +344,9 @@ internal sealed class GameService : IGameService
|
|||||||
|
|
||||||
using (await gameSemaphore.EnterAsync().ConfigureAwait(false))
|
using (await gameSemaphore.EnterAsync().ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
if (configuration.UnlockFPS)
|
if (options.UnlockFps)
|
||||||
{
|
{
|
||||||
IGameFpsUnlocker unlocker = new GameFpsUnlocker(game, configuration.TargetFPS);
|
IGameFpsUnlocker unlocker = new GameFpsUnlocker(game, options.TargetFps);
|
||||||
|
|
||||||
TimeSpan findModuleDelay = TimeSpan.FromMilliseconds(100);
|
TimeSpan findModuleDelay = TimeSpan.FromMilliseconds(100);
|
||||||
TimeSpan findModuleLimit = TimeSpan.FromMilliseconds(10000);
|
TimeSpan findModuleLimit = TimeSpan.FromMilliseconds(10000);
|
||||||
|
|||||||
@@ -61,9 +61,9 @@ internal interface IGameService
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 异步启动
|
/// 异步启动
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="configuration">启动配置</param>
|
/// <param name="options">启动配置</param>
|
||||||
/// <returns>任务</returns>
|
/// <returns>任务</returns>
|
||||||
ValueTask LaunchAsync(LaunchConfiguration configuration);
|
ValueTask LaunchAsync(LaunchOptions options);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 异步修改游戏账号名称
|
/// 异步修改游戏账号名称
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
|
||||||
// Licensed under the MIT license.
|
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.Game;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 启动游戏配置
|
|
||||||
/// </summary>
|
|
||||||
[HighQuality]
|
|
||||||
internal readonly struct LaunchConfiguration
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 是否为独占全屏
|
|
||||||
/// </summary>
|
|
||||||
public readonly bool IsExclusive;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否全屏,全屏时无边框设置将被覆盖
|
|
||||||
/// </summary>
|
|
||||||
public readonly bool IsFullScreen;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否为无边框窗口
|
|
||||||
/// </summary>
|
|
||||||
public readonly bool IsBorderless;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 窗口宽度
|
|
||||||
/// </summary>
|
|
||||||
public readonly int ScreenWidth;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 窗口高度
|
|
||||||
/// </summary>
|
|
||||||
public readonly int ScreenHeight;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 是否启用解锁帧率
|
|
||||||
/// </summary>
|
|
||||||
public readonly bool UnlockFPS;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 目标帧率
|
|
||||||
/// </summary>
|
|
||||||
public readonly int TargetFPS;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构造一个新的启动配置
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="isExclusive">独占全屏</param>
|
|
||||||
/// <param name="isFullScreen">全屏</param>
|
|
||||||
/// <param name="isBorderless">无边框</param>
|
|
||||||
/// <param name="screenWidth">宽度</param>
|
|
||||||
/// <param name="screenHeight">高度</param>
|
|
||||||
/// <param name="unlockFps">解锁帧率</param>
|
|
||||||
/// <param name="targetFps">目标帧率</param>
|
|
||||||
public LaunchConfiguration(bool isExclusive, bool isFullScreen, bool isBorderless, int screenWidth, int screenHeight, bool unlockFps, int targetFps)
|
|
||||||
{
|
|
||||||
IsExclusive = isExclusive;
|
|
||||||
IsFullScreen = isFullScreen;
|
|
||||||
IsBorderless = isBorderless;
|
|
||||||
ScreenHeight = screenHeight;
|
|
||||||
ScreenWidth = screenWidth;
|
|
||||||
ScreenHeight = screenHeight;
|
|
||||||
UnlockFPS = unlockFps;
|
|
||||||
TargetFPS = targetFps;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
371
src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs
Normal file
371
src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.UI.Windowing;
|
||||||
|
using Snap.Hutao.Core.Database;
|
||||||
|
using Snap.Hutao.Model;
|
||||||
|
using Snap.Hutao.Model.Entity;
|
||||||
|
using Snap.Hutao.Model.Entity.Database;
|
||||||
|
using Snap.Hutao.Win32;
|
||||||
|
using Windows.Graphics;
|
||||||
|
using Windows.Win32.Foundation;
|
||||||
|
using Windows.Win32.Graphics.Gdi;
|
||||||
|
using static Windows.Win32.PInvoke;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Service.Game;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 启动游戏选项
|
||||||
|
/// </summary>
|
||||||
|
[Injection(InjectAs.Singleton)]
|
||||||
|
internal sealed class LaunchOptions : ObservableObject, IOptions<LaunchOptions>
|
||||||
|
{
|
||||||
|
private readonly IServiceScopeFactory serviceScopeFactory;
|
||||||
|
private readonly int primaryScreenWidth;
|
||||||
|
private readonly int primaryScreenHeight;
|
||||||
|
private readonly int primaryScreenFps;
|
||||||
|
|
||||||
|
private bool? isFullScreen;
|
||||||
|
private bool? isBorderless;
|
||||||
|
private bool? isExclusive;
|
||||||
|
private int? screenWidth;
|
||||||
|
private int? screenHeight;
|
||||||
|
private bool? unlockFps;
|
||||||
|
private int? targetFps;
|
||||||
|
private NameValue<int>? monitor;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造一个新的启动游戏选项
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serviceScopeFactory">服务范围工厂</param>
|
||||||
|
public LaunchOptions(IServiceScopeFactory serviceScopeFactory)
|
||||||
|
{
|
||||||
|
this.serviceScopeFactory = serviceScopeFactory;
|
||||||
|
RectInt32 primaryRect = DisplayArea.Primary.OuterBounds;
|
||||||
|
primaryScreenWidth = primaryRect.Width;
|
||||||
|
primaryScreenHeight = primaryRect.Height;
|
||||||
|
|
||||||
|
// This list can't use foreach
|
||||||
|
IReadOnlyList<DisplayArea> displayAreas = DisplayArea.FindAll();
|
||||||
|
for (int i = 0; i < displayAreas.Count; i++)
|
||||||
|
{
|
||||||
|
DisplayArea displayArea = displayAreas[i];
|
||||||
|
int index = i + 1;
|
||||||
|
Monitors.Add(new($"{displayArea.DisplayId.Value:X8}:{index}", index));
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeScreenFps(out primaryScreenFps);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否全屏
|
||||||
|
/// </summary>
|
||||||
|
public bool IsFullScreen
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (isFullScreen == null)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchIsFullScreen)?.Value;
|
||||||
|
isFullScreen = value != null && bool.Parse(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isFullScreen.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref isFullScreen, value))
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
IsBorderless = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchIsFullScreen);
|
||||||
|
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchIsFullScreen, value.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否无边框
|
||||||
|
/// </summary>
|
||||||
|
public bool IsBorderless
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (isBorderless == null)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchIsBorderless)?.Value;
|
||||||
|
isBorderless = value != null && bool.Parse(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isBorderless.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref isBorderless, value))
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
IsExclusive = false;
|
||||||
|
IsFullScreen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchIsBorderless);
|
||||||
|
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchIsBorderless, value.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否独占全屏
|
||||||
|
/// </summary>
|
||||||
|
public bool IsExclusive
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (isExclusive == null)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchIsExclusive)?.Value;
|
||||||
|
isExclusive = value != null && bool.Parse(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isExclusive.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref isExclusive, value))
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
IsFullScreen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchIsExclusive);
|
||||||
|
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchIsExclusive, value.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 屏幕宽度
|
||||||
|
/// </summary>
|
||||||
|
public int ScreenWidth
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (screenWidth == null)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchScreenWidth)?.Value;
|
||||||
|
screenWidth = value == null ? primaryScreenWidth : int.Parse(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return screenWidth.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref screenWidth, value))
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchScreenWidth);
|
||||||
|
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchScreenWidth, value.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 屏幕高度
|
||||||
|
/// </summary>
|
||||||
|
public int ScreenHeight
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (screenHeight == null)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchScreenHeight)?.Value;
|
||||||
|
screenHeight = value == null ? primaryScreenHeight : int.Parse(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return screenHeight.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref screenHeight, value))
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchScreenHeight);
|
||||||
|
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchScreenHeight, value.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否全屏
|
||||||
|
/// </summary>
|
||||||
|
public bool UnlockFps
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (unlockFps == null)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchUnlockFps)?.Value;
|
||||||
|
unlockFps = value != null && bool.Parse(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unlockFps.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref unlockFps, value))
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchUnlockFps);
|
||||||
|
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchUnlockFps, value.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 目标帧率
|
||||||
|
/// </summary>
|
||||||
|
public int TargetFps
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (targetFps == null)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchTargetFps)?.Value;
|
||||||
|
targetFps = value == null ? primaryScreenFps : int.Parse(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetFps.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref targetFps, value))
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchTargetFps);
|
||||||
|
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchTargetFps, value.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 所有监视器
|
||||||
|
/// </summary>
|
||||||
|
public List<NameValue<int>> Monitors { get; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 目标帧率
|
||||||
|
/// </summary>
|
||||||
|
public NameValue<int> Monitor
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (monitor == null)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == SettingEntry.LaunchMonitor)?.Value;
|
||||||
|
|
||||||
|
int index = value == null ? 1 : int.Parse(value);
|
||||||
|
monitor = Monitors[index - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return monitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref monitor, value))
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceScopeFactory.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.Settings.ExecuteDeleteWhere(e => e.Key == SettingEntry.LaunchMonitor);
|
||||||
|
appDbContext.Settings.AddAndSave(new(SettingEntry.LaunchMonitor, value.Value.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public LaunchOptions Value { get => this; }
|
||||||
|
|
||||||
|
private static void InitializeScreenFps(out int fps)
|
||||||
|
{
|
||||||
|
HDC hDC = GetDC(HWND.Null);
|
||||||
|
fps = GetDeviceCaps(hDC, GET_DEVICE_CAPS_INDEX.VREFRESH);
|
||||||
|
if (ReleaseDC(HWND.Null, hDC) == 0)
|
||||||
|
{
|
||||||
|
// not released
|
||||||
|
throw new Win32Exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ using Snap.Hutao.Model.Metadata.Avatar;
|
|||||||
using Snap.Hutao.Model.Metadata.Weapon;
|
using Snap.Hutao.Model.Metadata.Weapon;
|
||||||
using Snap.Hutao.Model.Primitive;
|
using Snap.Hutao.Model.Primitive;
|
||||||
using Snap.Hutao.Service.Metadata;
|
using Snap.Hutao.Service.Metadata;
|
||||||
|
using Snap.Hutao.ViewModel.Complex;
|
||||||
using Snap.Hutao.Web.Hutao.Model;
|
using Snap.Hutao.Web.Hutao.Model;
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.Hutao;
|
namespace Snap.Hutao.Service.Hutao;
|
||||||
@@ -40,25 +41,25 @@ internal sealed class HutaoCache : IHutaoCache
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public List<ComplexAvatarRank>? AvatarUsageRanks { get; set; }
|
public List<AvatarRankView>? AvatarUsageRanks { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public List<ComplexAvatarRank>? AvatarAppearanceRanks { get; set; }
|
public List<AvatarRankView>? AvatarAppearanceRanks { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public List<ComplexAvatarConstellationInfo>? AvatarConstellationInfos { get; set; }
|
public List<AvatarConstellationInfoView>? AvatarConstellationInfos { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public List<ComplexTeamRank>? TeamAppearances { get; set; }
|
public List<TeamAppearanceView>? TeamAppearances { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public Overview? Overview { get; set; }
|
public Overview? Overview { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public List<ComplexAvatarCollocation>? AvatarCollocations { get; set; }
|
public List<AvatarCollocationView>? AvatarCollocations { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public List<ComplexWeaponCollocation>? WeaponCollocations { get; set; }
|
public List<WeaponCollocationView>? WeaponCollocations { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async ValueTask<bool> InitializeForDatabaseViewModelAsync()
|
public async ValueTask<bool> InitializeForDatabaseViewModelAsync()
|
||||||
@@ -113,12 +114,12 @@ internal sealed class HutaoCache : IHutaoCache
|
|||||||
avatarCollocationsRaw = await hutaoService.GetAvatarCollocationsAsync().ConfigureAwait(false);
|
avatarCollocationsRaw = await hutaoService.GetAvatarCollocationsAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarCollocations = avatarCollocationsRaw.Select(co => new ComplexAvatarCollocation()
|
AvatarCollocations = avatarCollocationsRaw.Select(co => new AvatarCollocationView()
|
||||||
{
|
{
|
||||||
AvatarId = co.AvatarId,
|
AvatarId = co.AvatarId,
|
||||||
Avatars = co.Avatars.Select(a => new ComplexAvatar(idAvatarMap[a.Item], a.Rate)).ToList(),
|
Avatars = co.Avatars.Select(a => new AvatarView(idAvatarMap[a.Item], a.Rate)).ToList(),
|
||||||
Weapons = co.Weapons.Select(w => new ComplexWeapon(idWeaponMap[w.Item], w.Rate)).ToList(),
|
Weapons = co.Weapons.Select(w => new WeaponView(idWeaponMap[w.Item], w.Rate)).ToList(),
|
||||||
ReliquarySets = co.Reliquaries.Select(r => new ComplexReliquarySet(r, idReliquarySetMap)).ToList(),
|
ReliquarySets = co.Reliquaries.Select(r => new ReliquarySetView(r, idReliquarySetMap)).ToList(),
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
wikiAvatarViewModelTaskSource.TrySetResult(true);
|
wikiAvatarViewModelTaskSource.TrySetResult(true);
|
||||||
@@ -149,10 +150,10 @@ internal sealed class HutaoCache : IHutaoCache
|
|||||||
weaponCollocationsRaw = await hutaoService.GetWeaponCollocationsAsync().ConfigureAwait(false);
|
weaponCollocationsRaw = await hutaoService.GetWeaponCollocationsAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
WeaponCollocations = weaponCollocationsRaw.Select(co => new ComplexWeaponCollocation()
|
WeaponCollocations = weaponCollocationsRaw.Select(co => new WeaponCollocationView()
|
||||||
{
|
{
|
||||||
WeaponId = co.WeaponId,
|
WeaponId = co.WeaponId,
|
||||||
Avatars = co.Avatars.Select(a => new ComplexAvatar(idAvatarMap[a.Item], a.Rate)).ToList(),
|
Avatars = co.Avatars.Select(a => new AvatarView(idAvatarMap[a.Item], a.Rate)).ToList(),
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
wikiWeaponViewModelTaskSource.TrySetResult(true);
|
wikiWeaponViewModelTaskSource.TrySetResult(true);
|
||||||
@@ -183,10 +184,10 @@ internal sealed class HutaoCache : IHutaoCache
|
|||||||
avatarAppearanceRanksRaw = await hutaoService.GetAvatarAppearanceRanksAsync().ConfigureAwait(false);
|
avatarAppearanceRanksRaw = await hutaoService.GetAvatarAppearanceRanksAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarAppearanceRanks = avatarAppearanceRanksRaw.OrderByDescending(r => r.Floor).Select(rank => new ComplexAvatarRank
|
AvatarAppearanceRanks = avatarAppearanceRanksRaw.OrderByDescending(r => r.Floor).Select(rank => new AvatarRankView
|
||||||
{
|
{
|
||||||
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, rank.Floor),
|
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, rank.Floor),
|
||||||
Avatars = rank.Ranks.OrderByDescending(r => r.Rate).Select(rank => new ComplexAvatar(idAvatarMap[rank.Item], rank.Rate)).ToList(),
|
Avatars = rank.Ranks.OrderByDescending(r => r.Rate).Select(rank => new AvatarView(idAvatarMap[rank.Item], rank.Rate)).ToList(),
|
||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,10 +200,10 @@ internal sealed class HutaoCache : IHutaoCache
|
|||||||
avatarUsageRanksRaw = await hutaoService.GetAvatarUsageRanksAsync().ConfigureAwait(false);
|
avatarUsageRanksRaw = await hutaoService.GetAvatarUsageRanksAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarUsageRanks = avatarUsageRanksRaw.OrderByDescending(r => r.Floor).Select(rank => new ComplexAvatarRank
|
AvatarUsageRanks = avatarUsageRanksRaw.OrderByDescending(r => r.Floor).Select(rank => new AvatarRankView
|
||||||
{
|
{
|
||||||
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, rank.Floor),
|
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, rank.Floor),
|
||||||
Avatars = rank.Ranks.OrderByDescending(r => r.Rate).Select(rank => new ComplexAvatar(idAvatarMap[rank.Item], rank.Rate)).ToList(),
|
Avatars = rank.Ranks.OrderByDescending(r => r.Rate).Select(rank => new AvatarView(idAvatarMap[rank.Item], rank.Rate)).ToList(),
|
||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +218,7 @@ internal sealed class HutaoCache : IHutaoCache
|
|||||||
|
|
||||||
AvatarConstellationInfos = avatarConstellationInfosRaw.OrderBy(i => i.HoldingRate).Select(info =>
|
AvatarConstellationInfos = avatarConstellationInfosRaw.OrderBy(i => i.HoldingRate).Select(info =>
|
||||||
{
|
{
|
||||||
return new ComplexAvatarConstellationInfo(idAvatarMap[info.AvatarId], info.HoldingRate, info.Constellations.Select(x => x.Rate));
|
return new AvatarConstellationInfoView(idAvatarMap[info.AvatarId], info.HoldingRate, info.Constellations.Select(x => x.Rate));
|
||||||
}).ToList();
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +231,7 @@ internal sealed class HutaoCache : IHutaoCache
|
|||||||
teamAppearancesRaw = await hutaoService.GetTeamAppearancesAsync().ConfigureAwait(false);
|
teamAppearancesRaw = await hutaoService.GetTeamAppearancesAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TeamAppearances = teamAppearancesRaw.OrderByDescending(t => t.Floor).Select(team => new ComplexTeamRank(team, idAvatarMap)).ToList();
|
TeamAppearances = teamAppearancesRaw.OrderByDescending(t => t.Floor).Select(team => new TeamAppearanceView(team, idAvatarMap)).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OverviewAsync()
|
private async Task OverviewAsync()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using Snap.Hutao.Model.Binding.Hutao;
|
using Snap.Hutao.Model.Binding.Hutao;
|
||||||
|
using Snap.Hutao.ViewModel.Complex;
|
||||||
using Snap.Hutao.Web.Hutao.Model;
|
using Snap.Hutao.Web.Hutao.Model;
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.Hutao;
|
namespace Snap.Hutao.Service.Hutao;
|
||||||
@@ -15,22 +16,22 @@ internal interface IHutaoCache
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色使用率
|
/// 角色使用率
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<ComplexAvatarRank>? AvatarUsageRanks { get; set; }
|
List<AvatarRankView>? AvatarUsageRanks { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色上场率
|
/// 角色上场率
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<ComplexAvatarRank>? AvatarAppearanceRanks { get; set; }
|
List<AvatarRankView>? AvatarAppearanceRanks { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色命座信息
|
/// 角色命座信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<ComplexAvatarConstellationInfo>? AvatarConstellationInfos { get; set; }
|
List<AvatarConstellationInfoView>? AvatarConstellationInfos { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 队伍出场
|
/// 队伍出场
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<ComplexTeamRank>? TeamAppearances { get; set; }
|
List<TeamAppearanceView>? TeamAppearances { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 总览数据
|
/// 总览数据
|
||||||
@@ -40,12 +41,12 @@ internal interface IHutaoCache
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色搭配
|
/// 角色搭配
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<ComplexAvatarCollocation>? AvatarCollocations { get; set; }
|
List<AvatarCollocationView>? AvatarCollocations { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 武器搭配
|
/// 武器搭配
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<ComplexWeaponCollocation>? WeaponCollocations { get; set; }
|
List<WeaponCollocationView>? WeaponCollocations { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 为数据库视图模型初始化
|
/// 为数据库视图模型初始化
|
||||||
|
|||||||
@@ -110,7 +110,6 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi
|
|||||||
case "id": return "ID"; // Indonesian
|
case "id": return "ID"; // Indonesian
|
||||||
case "it": return "IT"; // Italian
|
case "it": return "IT"; // Italian
|
||||||
case "ja": return "JP"; // Japanese
|
case "ja": return "JP"; // Japanese
|
||||||
case "kr": return "JP"; // Japanese
|
|
||||||
case "ko": return "KR"; // Korean
|
case "ko": return "KR"; // Korean
|
||||||
case "pt": return "PT"; // Portuguese
|
case "pt": return "PT"; // Portuguese
|
||||||
case "ru": return "RU"; // Russian
|
case "ru": return "RU"; // Russian
|
||||||
|
|||||||
@@ -432,7 +432,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Control\Extension\" />
|
<Folder Include="Control\Extension\" />
|
||||||
<Folder Include="Model\Binding\Gacha\" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Update="Resource\Localization\SH.Designer.cs">
|
<Compile Update="Resource\Localization\SH.Designer.cs">
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
xmlns:shci="using:Snap.Hutao.Control.Image"
|
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||||
xmlns:shcp="using:Snap.Hutao.Control.Panel"
|
xmlns:shcp="using:Snap.Hutao.Control.Panel"
|
||||||
xmlns:shmbg="using:Snap.Hutao.Model.Binding.Gacha"
|
|
||||||
xmlns:shvc="using:Snap.Hutao.View.Control"
|
xmlns:shvc="using:Snap.Hutao.View.Control"
|
||||||
d:DataContext="{d:DesignInstance shmbg:Snap.Hutao.ViewModel.GachaLog.TypedWishSummary}"
|
xmlns:shvg="using:Snap.Hutao.ViewModel.GachaLog"
|
||||||
|
d:DataContext="{d:DesignInstance shvg:TypedWishSummary}"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<SolidColorBrush x:Key="PurpleBrush" Color="#FFA156E0"/>
|
<SolidColorBrush x:Key="PurpleBrush" Color="#FFA156E0"/>
|
||||||
<SolidColorBrush x:Key="OrangeBrush" Color="#FFBC6932"/>
|
<SolidColorBrush x:Key="OrangeBrush" Color="#FFBC6932"/>
|
||||||
|
|
||||||
<DataTemplate x:Key="OrangeListTemplate" x:DataType="shmbg:SummaryItem">
|
<DataTemplate x:Key="OrangeListTemplate" d:DataType="shvg:SummaryItem">
|
||||||
<Grid Margin="0,4,4,0" Background="Transparent">
|
<Grid Margin="0,4,4,0" Background="Transparent">
|
||||||
<ToolTipService.ToolTip>
|
<ToolTipService.ToolTip>
|
||||||
<TextBlock Text="{Binding TimeFormatted}"/>
|
<TextBlock Text="{Binding TimeFormatted}"/>
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
FalseValue="{ThemeResource SystemFillColorCriticalBackgroundBrush}"
|
FalseValue="{ThemeResource SystemFillColorCriticalBackgroundBrush}"
|
||||||
TrueValue="{ThemeResource CardBackgroundFillColorDefaultBrush}"/>
|
TrueValue="{ThemeResource CardBackgroundFillColorDefaultBrush}"/>
|
||||||
|
|
||||||
<DataTemplate x:Key="OrangeGridTemplate" x:DataType="shmbg:SummaryItem">
|
<DataTemplate x:Key="OrangeGridTemplate" d:DataType="shvg:SummaryItem">
|
||||||
<Grid Width="40" Margin="0,4,4,0">
|
<Grid Width="40" Margin="0,4,4,0">
|
||||||
<Border
|
<Border
|
||||||
Background="{Binding IsUp, Converter={StaticResource BoolToBrushConverter}}"
|
Background="{Binding IsUp, Converter={StaticResource BoolToBrushConverter}}"
|
||||||
|
|||||||
@@ -9,11 +9,10 @@
|
|||||||
xmlns:shc="using:Snap.Hutao.Control"
|
xmlns:shc="using:Snap.Hutao.Control"
|
||||||
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
||||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||||
xmlns:shmbh="using:Snap.Hutao.Model.Binding.Hutao"
|
xmlns:shvcom="using:Snap.Hutao.ViewModel.Complex"
|
||||||
xmlns:shv="using:Snap.Hutao.ViewModel"
|
xmlns:shvcon="using:Snap.Hutao.View.Control"
|
||||||
xmlns:shvc="using:Snap.Hutao.View.Control"
|
|
||||||
xmlns:wsc="using:WinUICommunity.SettingsUI.Controls"
|
xmlns:wsc="using:WinUICommunity.SettingsUI.Controls"
|
||||||
d:DataContext="{d:DesignInstance shv:HutaoDatabaseViewModel}"
|
d:DataContext="{d:DesignInstance shvcom:HutaoDatabaseViewModel}"
|
||||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
@@ -22,7 +21,7 @@
|
|||||||
</mxi:Interaction.Behaviors>
|
</mxi:Interaction.Behaviors>
|
||||||
|
|
||||||
<Page.Resources>
|
<Page.Resources>
|
||||||
<DataTemplate x:Key="TeamItemTemplate" x:DataType="shmbh:Team">
|
<DataTemplate x:Key="TeamItemTemplate" d:DataType="shvcom:Team">
|
||||||
<Border Margin="12,0,12,12" Style="{StaticResource BorderCardStyle}">
|
<Border Margin="12,0,12,12" Style="{StaticResource BorderCardStyle}">
|
||||||
<Grid Margin="6">
|
<Grid Margin="6">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@@ -37,7 +36,7 @@
|
|||||||
</ItemsControl.ItemsPanel>
|
</ItemsControl.ItemsPanel>
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<shvc:ItemIcon
|
<shvcon:ItemIcon
|
||||||
Width="48"
|
Width="48"
|
||||||
Height="48"
|
Height="48"
|
||||||
Icon="{Binding Icon}"
|
Icon="{Binding Icon}"
|
||||||
@@ -115,9 +114,9 @@
|
|||||||
SelectionMode="None">
|
SelectionMode="None">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<shvc:BottomTextControl Text="{Binding Rate}">
|
<shvcon:BottomTextControl Text="{Binding Rate}">
|
||||||
<shvc:ItemIcon Icon="{Binding Icon}" Quality="{Binding Quality}"/>
|
<shvcon:ItemIcon Icon="{Binding Icon}" Quality="{Binding Quality}"/>
|
||||||
</shvc:BottomTextControl>
|
</shvcon:BottomTextControl>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</GridView>
|
</GridView>
|
||||||
@@ -143,9 +142,9 @@
|
|||||||
SelectionMode="None">
|
SelectionMode="None">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<shvc:BottomTextControl Text="{Binding Rate}">
|
<shvcon:BottomTextControl Text="{Binding Rate}">
|
||||||
<shvc:ItemIcon Icon="{Binding Icon}" Quality="{Binding Quality}"/>
|
<shvcon:ItemIcon Icon="{Binding Icon}" Quality="{Binding Quality}"/>
|
||||||
</shvc:BottomTextControl>
|
</shvcon:BottomTextControl>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
</GridView>
|
</GridView>
|
||||||
@@ -275,7 +274,7 @@
|
|||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<shvc:ItemIcon
|
<shvcon:ItemIcon
|
||||||
Width="48"
|
Width="48"
|
||||||
Height="48"
|
Height="48"
|
||||||
Icon="{Binding Icon}"
|
Icon="{Binding Icon}"
|
||||||
@@ -315,6 +314,6 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</PivotItem>
|
</PivotItem>
|
||||||
</Pivot>
|
</Pivot>
|
||||||
<shvc:LoadingView IsLoading="{Binding Overview, Converter={StaticResource EmptyObjectToBoolRevertConverter}}"/>
|
<shvcon:LoadingView IsLoading="{Binding Overview, Converter={StaticResource EmptyObjectToBoolRevertConverter}}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</shc:ScopedPage>
|
</shc:ScopedPage>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using Snap.Hutao.Control;
|
using Snap.Hutao.Control;
|
||||||
using Snap.Hutao.ViewModel;
|
using Snap.Hutao.ViewModel.Complex;
|
||||||
|
|
||||||
namespace Snap.Hutao.View.Page;
|
namespace Snap.Hutao.View.Page;
|
||||||
|
|
||||||
|
|||||||
@@ -184,7 +184,7 @@
|
|||||||
<wsc:Setting.ActionContent>
|
<wsc:Setting.ActionContent>
|
||||||
<ToggleSwitch
|
<ToggleSwitch
|
||||||
Width="120"
|
Width="120"
|
||||||
IsOn="{Binding IsExclusive, Mode=TwoWay}"
|
IsOn="{Binding Options.IsExclusive, Mode=TwoWay}"
|
||||||
Style="{StaticResource ToggleSwitchSettingStyle}"/>
|
Style="{StaticResource ToggleSwitchSettingStyle}"/>
|
||||||
</wsc:Setting.ActionContent>
|
</wsc:Setting.ActionContent>
|
||||||
</wsc:Setting>
|
</wsc:Setting>
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
<wsc:Setting.ActionContent>
|
<wsc:Setting.ActionContent>
|
||||||
<ToggleSwitch
|
<ToggleSwitch
|
||||||
Width="120"
|
Width="120"
|
||||||
IsOn="{Binding IsFullScreen, Mode=TwoWay}"
|
IsOn="{Binding Options.IsFullScreen, Mode=TwoWay}"
|
||||||
Style="{StaticResource ToggleSwitchSettingStyle}"/>
|
Style="{StaticResource ToggleSwitchSettingStyle}"/>
|
||||||
</wsc:Setting.ActionContent>
|
</wsc:Setting.ActionContent>
|
||||||
</wsc:Setting>
|
</wsc:Setting>
|
||||||
@@ -206,7 +206,7 @@
|
|||||||
<wsc:Setting.ActionContent>
|
<wsc:Setting.ActionContent>
|
||||||
<ToggleSwitch
|
<ToggleSwitch
|
||||||
Width="120"
|
Width="120"
|
||||||
IsOn="{Binding IsBorderless, Mode=TwoWay}"
|
IsOn="{Binding Options.IsBorderless, Mode=TwoWay}"
|
||||||
Style="{StaticResource ToggleSwitchSettingStyle}"/>
|
Style="{StaticResource ToggleSwitchSettingStyle}"/>
|
||||||
</wsc:Setting.ActionContent>
|
</wsc:Setting.ActionContent>
|
||||||
</wsc:Setting>
|
</wsc:Setting>
|
||||||
@@ -217,7 +217,7 @@
|
|||||||
Header="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceScreenWidthHeader}"
|
Header="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceScreenWidthHeader}"
|
||||||
Icon="">
|
Icon="">
|
||||||
<wsc:Setting.ActionContent>
|
<wsc:Setting.ActionContent>
|
||||||
<NumberBox Width="156" Value="{Binding ScreenWidth, Mode=TwoWay}"/>
|
<NumberBox Width="156" Value="{Binding Options.ScreenWidth, Mode=TwoWay}"/>
|
||||||
</wsc:Setting.ActionContent>
|
</wsc:Setting.ActionContent>
|
||||||
</wsc:Setting>
|
</wsc:Setting>
|
||||||
<wsc:Setting
|
<wsc:Setting
|
||||||
@@ -225,7 +225,19 @@
|
|||||||
Header="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceScreenHeightHeader}"
|
Header="{shcm:ResourceString Name=ViewPageLaunchGameAppearanceScreenHeightHeader}"
|
||||||
Icon="">
|
Icon="">
|
||||||
<wsc:Setting.ActionContent>
|
<wsc:Setting.ActionContent>
|
||||||
<NumberBox Width="156" Value="{Binding ScreenHeight, Mode=TwoWay}"/>
|
<NumberBox Width="156" Value="{Binding Options.ScreenHeight, Mode=TwoWay}"/>
|
||||||
|
</wsc:Setting.ActionContent>
|
||||||
|
</wsc:Setting>
|
||||||
|
|
||||||
|
<wsc:Setting
|
||||||
|
Description="{shcm:ResourceString Name=ViewPageLaunchGameMonitorsDescription}"
|
||||||
|
Header="{shcm:ResourceString Name=ViewPageLaunchGameMonitorsHeader}"
|
||||||
|
Icon="">
|
||||||
|
<wsc:Setting.ActionContent>
|
||||||
|
<ComboBox
|
||||||
|
DisplayMemberPath="Name"
|
||||||
|
ItemsSource="{Binding Options.Monitors}"
|
||||||
|
SelectedItem="{Binding Options.Monitor, Mode=TwoWay}"/>
|
||||||
</wsc:Setting.ActionContent>
|
</wsc:Setting.ActionContent>
|
||||||
</wsc:Setting>
|
</wsc:Setting>
|
||||||
</wsc:SettingsGroup>
|
</wsc:SettingsGroup>
|
||||||
@@ -243,7 +255,7 @@
|
|||||||
<wsc:Setting.ActionContent>
|
<wsc:Setting.ActionContent>
|
||||||
<ToggleSwitch
|
<ToggleSwitch
|
||||||
Width="120"
|
Width="120"
|
||||||
IsOn="{Binding UnlockFps, Mode=TwoWay}"
|
IsOn="{Binding Options.UnlockFps, Mode=TwoWay}"
|
||||||
OffContent="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsOff}"
|
OffContent="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsOff}"
|
||||||
OnContent="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsOn}"
|
OnContent="{shcm:ResourceString Name=ViewPageLaunchGameUnlockFpsOn}"
|
||||||
Style="{StaticResource ToggleSwitchSettingStyle}"/>
|
Style="{StaticResource ToggleSwitchSettingStyle}"/>
|
||||||
@@ -253,7 +265,7 @@
|
|||||||
<wsc:Setting.Description>
|
<wsc:Setting.Description>
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<TextBlock Text="{shcm:ResourceString Name=ViewPageLaunchGameSetFpsDescription}"/>
|
<TextBlock Text="{shcm:ResourceString Name=ViewPageLaunchGameSetFpsDescription}"/>
|
||||||
<TextBlock Text="{Binding TargetFps}"/>
|
<TextBlock Text="{Binding Options.TargetFps}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</wsc:Setting.Description>
|
</wsc:Setting.Description>
|
||||||
<wsc:Setting.ActionContent>
|
<wsc:Setting.ActionContent>
|
||||||
@@ -261,7 +273,7 @@
|
|||||||
Width="400"
|
Width="400"
|
||||||
Maximum="360"
|
Maximum="360"
|
||||||
Minimum="60"
|
Minimum="60"
|
||||||
Value="{Binding TargetFps, Mode=TwoWay}"/>
|
Value="{Binding Options.TargetFps, Mode=TwoWay}"/>
|
||||||
</wsc:Setting.ActionContent>
|
</wsc:Setting.ActionContent>
|
||||||
</wsc:Setting>
|
</wsc:Setting>
|
||||||
</wsc:SettingsGroup>
|
</wsc:SettingsGroup>
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
using Snap.Hutao.Model.Primitive;
|
using Snap.Hutao.Model.Primitive;
|
||||||
|
|
||||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
namespace Snap.Hutao.ViewModel.Complex;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色搭配
|
/// 角色搭配
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal sealed class ComplexAvatarCollocation
|
internal sealed class AvatarCollocationView
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色Id
|
/// 角色Id
|
||||||
@@ -19,15 +19,15 @@ internal sealed class ComplexAvatarCollocation
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色
|
/// 角色
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ComplexAvatar> Avatars { get; set; } = default!;
|
public List<AvatarView> Avatars { get; set; } = default!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 武器
|
/// 武器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ComplexWeapon> Weapons { get; set; } = default!;
|
public List<WeaponView> Weapons { get; set; } = default!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 圣遗物套装
|
/// 圣遗物套装
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ComplexReliquarySet> ReliquarySets { get; set; } = default!;
|
public List<ReliquarySetView> ReliquarySets { get; set; } = default!;
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using Snap.Hutao.Model.Metadata.Avatar;
|
using Snap.Hutao.Model.Metadata.Avatar;
|
||||||
|
using Snap.Hutao.ViewModel.Complex;
|
||||||
|
|
||||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
namespace Snap.Hutao.Model.Binding.Hutao;
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ namespace Snap.Hutao.Model.Binding.Hutao;
|
|||||||
/// 角色命座信息
|
/// 角色命座信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal sealed class ComplexAvatarConstellationInfo : ComplexAvatar
|
internal sealed class AvatarConstellationInfoView : AvatarView
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造一个新的角色命座信息
|
/// 构造一个新的角色命座信息
|
||||||
@@ -17,7 +18,7 @@ internal sealed class ComplexAvatarConstellationInfo : ComplexAvatar
|
|||||||
/// <param name="avatar">角色</param>
|
/// <param name="avatar">角色</param>
|
||||||
/// <param name="rate">持有率</param>
|
/// <param name="rate">持有率</param>
|
||||||
/// <param name="rates">命座比率</param>
|
/// <param name="rates">命座比率</param>
|
||||||
public ComplexAvatarConstellationInfo(Avatar avatar, double rate, IEnumerable<double> rates)
|
public AvatarConstellationInfoView(Avatar avatar, double rate, IEnumerable<double> rates)
|
||||||
: base(avatar, rate)
|
: base(avatar, rate)
|
||||||
{
|
{
|
||||||
Rates = rates.Select(r => $"{r:P3}").ToList();
|
Rates = rates.Select(r => $"{r:P3}").ToList();
|
||||||
@@ -26,5 +27,5 @@ internal sealed class ComplexAvatarConstellationInfo : ComplexAvatar
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 命座比率
|
/// 命座比率
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> Rates { get; set; }
|
public List<string> Rates { get; }
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
namespace Snap.Hutao.ViewModel.Complex;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色榜
|
/// 角色榜
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal sealed class ComplexAvatarRank
|
internal sealed class AvatarRankView
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 层数
|
/// 层数
|
||||||
@@ -17,5 +17,5 @@ internal sealed class ComplexAvatarRank
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 排行信息
|
/// 排行信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ComplexAvatar> Avatars { get; set; } = default!;
|
public List<AvatarView> Avatars { get; set; } = default!;
|
||||||
}
|
}
|
||||||
@@ -1,24 +1,25 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Snap.Hutao.Model.Binding;
|
||||||
using Snap.Hutao.Model.Intrinsic;
|
using Snap.Hutao.Model.Intrinsic;
|
||||||
using Snap.Hutao.Model.Metadata.Avatar;
|
using Snap.Hutao.Model.Metadata.Avatar;
|
||||||
using Snap.Hutao.Model.Metadata.Converter;
|
using Snap.Hutao.Model.Metadata.Converter;
|
||||||
|
|
||||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
namespace Snap.Hutao.ViewModel.Complex;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色
|
/// 角色
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal class ComplexAvatar : INameIconSide
|
internal class AvatarView : INameIconSide
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造一个胡桃数据库角色
|
/// 构造一个胡桃数据库角色
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="avatar">元数据角色</param>
|
/// <param name="avatar">元数据角色</param>
|
||||||
/// <param name="rate">率</param>
|
/// <param name="rate">率</param>
|
||||||
public ComplexAvatar(Avatar avatar, double rate)
|
public AvatarView(Avatar avatar, double rate)
|
||||||
{
|
{
|
||||||
Name = avatar.Name;
|
Name = avatar.Name;
|
||||||
Icon = AvatarIconConverter.IconNameToUri(avatar.Icon);
|
Icon = AvatarIconConverter.IconNameToUri(avatar.Icon);
|
||||||
@@ -30,25 +31,25 @@ internal class ComplexAvatar : INameIconSide
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 名称
|
/// 名称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; } = default!;
|
public string Name { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 图标
|
/// 图标
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Uri Icon { get; set; } = default!;
|
public Uri Icon { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 侧面图标
|
/// 侧面图标
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Uri SideIcon { get; set; } = default!;
|
public Uri SideIcon { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 星级
|
/// 星级
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ItemQuality Quality { get; set; }
|
public ItemQuality Quality { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 比率
|
/// 比率
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Rate { get; set; } = default!;
|
public string Rate { get; }
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.Input;
|
|
||||||
using Snap.Hutao.Model.Binding.Hutao;
|
using Snap.Hutao.Model.Binding.Hutao;
|
||||||
using Snap.Hutao.Service.Hutao;
|
using Snap.Hutao.Service.Hutao;
|
||||||
using Snap.Hutao.Web.Hutao.Model;
|
using Snap.Hutao.Web.Hutao.Model;
|
||||||
|
|
||||||
namespace Snap.Hutao.ViewModel;
|
namespace Snap.Hutao.ViewModel.Complex;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 胡桃数据库视图模型
|
/// 胡桃数据库视图模型
|
||||||
@@ -17,10 +16,10 @@ internal sealed class HutaoDatabaseViewModel : Abstraction.ViewModel
|
|||||||
{
|
{
|
||||||
private readonly IHutaoCache hutaoCache;
|
private readonly IHutaoCache hutaoCache;
|
||||||
|
|
||||||
private List<ComplexAvatarRank>? avatarUsageRanks;
|
private List<AvatarRankView>? avatarUsageRanks;
|
||||||
private List<ComplexAvatarRank>? avatarAppearanceRanks;
|
private List<AvatarRankView>? avatarAppearanceRanks;
|
||||||
private List<ComplexAvatarConstellationInfo>? avatarConstellationInfos;
|
private List<AvatarConstellationInfoView>? avatarConstellationInfos;
|
||||||
private List<ComplexTeamRank>? teamAppearances;
|
private List<TeamAppearanceView>? teamAppearances;
|
||||||
private Overview? overview;
|
private Overview? overview;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -30,41 +29,35 @@ internal sealed class HutaoDatabaseViewModel : Abstraction.ViewModel
|
|||||||
public HutaoDatabaseViewModel(IHutaoCache hutaoCache)
|
public HutaoDatabaseViewModel(IHutaoCache hutaoCache)
|
||||||
{
|
{
|
||||||
this.hutaoCache = hutaoCache;
|
this.hutaoCache = hutaoCache;
|
||||||
|
|
||||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色使用率
|
/// 角色使用率
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ComplexAvatarRank>? AvatarUsageRanks { get => avatarUsageRanks; set => SetProperty(ref avatarUsageRanks, value); }
|
public List<AvatarRankView>? AvatarUsageRanks { get => avatarUsageRanks; set => SetProperty(ref avatarUsageRanks, value); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色上场率
|
/// 角色上场率
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ComplexAvatarRank>? AvatarAppearanceRanks { get => avatarAppearanceRanks; set => SetProperty(ref avatarAppearanceRanks, value); }
|
public List<AvatarRankView>? AvatarAppearanceRanks { get => avatarAppearanceRanks; set => SetProperty(ref avatarAppearanceRanks, value); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色命座信息
|
/// 角色命座信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ComplexAvatarConstellationInfo>? AvatarConstellationInfos { get => avatarConstellationInfos; set => SetProperty(ref avatarConstellationInfos, value); }
|
public List<AvatarConstellationInfoView>? AvatarConstellationInfos { get => avatarConstellationInfos; set => SetProperty(ref avatarConstellationInfos, value); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 队伍出场
|
/// 队伍出场
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ComplexTeamRank>? TeamAppearances { get => teamAppearances; set => SetProperty(ref teamAppearances, value); }
|
public List<TeamAppearanceView>? TeamAppearances { get => teamAppearances; set => SetProperty(ref teamAppearances, value); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 总览数据
|
/// 总览数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Overview? Overview { get => overview; set => SetProperty(ref overview, value); }
|
public Overview? Overview { get => overview; set => SetProperty(ref overview, value); }
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// 打开界面命令
|
protected override async Task OpenUIAsync()
|
||||||
/// </summary>
|
|
||||||
public ICommand OpenUICommand { get; }
|
|
||||||
|
|
||||||
private async Task OpenUIAsync()
|
|
||||||
{
|
{
|
||||||
if (await hutaoCache.InitializeForDatabaseViewModelAsync().ConfigureAwait(true))
|
if (await hutaoCache.InitializeForDatabaseViewModelAsync().ConfigureAwait(true))
|
||||||
{
|
{
|
||||||
@@ -6,30 +6,30 @@ using Snap.Hutao.Model.Primitive;
|
|||||||
using Snap.Hutao.Web.Hutao.Model;
|
using Snap.Hutao.Web.Hutao.Model;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
namespace Snap.Hutao.ViewModel.Complex;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 圣遗物套装
|
/// 圣遗物套装
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal sealed class ComplexReliquarySet
|
internal sealed class ReliquarySetView
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造一个新的胡桃数据库圣遗物套装
|
/// 构造一个新的胡桃数据库圣遗物套装
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reliquarySetRate">圣遗物套装率</param>
|
/// <param name="reliquarySetRate">圣遗物套装率</param>
|
||||||
/// <param name="idReliquarySetMap">圣遗物套装映射</param>
|
/// <param name="idReliquarySetMap">圣遗物套装映射</param>
|
||||||
public ComplexReliquarySet(ItemRate<ReliquarySets, double> reliquarySetRate, Dictionary<EquipAffixId, Metadata.Reliquary.ReliquarySet> idReliquarySetMap)
|
public ReliquarySetView(ItemRate<ReliquarySets, double> reliquarySetRate, Dictionary<EquipAffixId, Model.Metadata.Reliquary.ReliquarySet> idReliquarySetMap)
|
||||||
{
|
{
|
||||||
ReliquarySets sets = reliquarySetRate.Item;
|
ReliquarySets sets = reliquarySetRate.Item;
|
||||||
|
|
||||||
if (sets.Count >= 1)
|
if (sets.Count >= 1)
|
||||||
{
|
{
|
||||||
StringBuilder nameBuilder = new();
|
StringBuilder nameBuilder = new();
|
||||||
List<Uri> icons = new();
|
List<Uri> icons = new(2);
|
||||||
|
|
||||||
foreach (ReliquarySet set in sets)
|
foreach (ReliquarySet set in sets)
|
||||||
{
|
{
|
||||||
Metadata.Reliquary.ReliquarySet metaSet = idReliquarySetMap[set.EquipAffixId / 10];
|
Model.Metadata.Reliquary.ReliquarySet metaSet = idReliquarySetMap[set.EquipAffixId / 10];
|
||||||
|
|
||||||
if (nameBuilder.Length != 0)
|
if (nameBuilder.Length != 0)
|
||||||
{
|
{
|
||||||
@@ -45,7 +45,7 @@ internal sealed class ComplexReliquarySet
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Name = "无圣遗物或散件";
|
Name = SH.ViewModelComplexReliquarySetViewEmptyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rate = $"{reliquarySetRate.Rate:P3}";
|
Rate = $"{reliquarySetRate.Rate:P3}";
|
||||||
@@ -5,13 +5,13 @@ using Snap.Hutao.Model.Metadata.Avatar;
|
|||||||
using Snap.Hutao.Model.Primitive;
|
using Snap.Hutao.Model.Primitive;
|
||||||
using Snap.Hutao.Web.Hutao.Model;
|
using Snap.Hutao.Web.Hutao.Model;
|
||||||
|
|
||||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
namespace Snap.Hutao.ViewModel.Complex;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 队伍
|
/// 队伍
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal sealed class Team : List<ComplexAvatar>
|
internal sealed class Team : List<AvatarView>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造一个新的队伍
|
/// 构造一个新的队伍
|
||||||
@@ -5,20 +5,20 @@ using Snap.Hutao.Model.Metadata.Avatar;
|
|||||||
using Snap.Hutao.Model.Primitive;
|
using Snap.Hutao.Model.Primitive;
|
||||||
using Snap.Hutao.Web.Hutao.Model;
|
using Snap.Hutao.Web.Hutao.Model;
|
||||||
|
|
||||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
namespace Snap.Hutao.ViewModel.Complex;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 队伍排行
|
/// 队伍排行
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal sealed class ComplexTeamRank
|
internal sealed class TeamAppearanceView
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造一个新的队伍排行
|
/// 构造一个新的队伍排行
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="teamRank">队伍排行</param>
|
/// <param name="teamRank">队伍排行</param>
|
||||||
/// <param name="idAvatarMap">映射</param>
|
/// <param name="idAvatarMap">映射</param>
|
||||||
public ComplexTeamRank(TeamAppearance teamRank, Dictionary<AvatarId, Avatar> idAvatarMap)
|
public TeamAppearanceView(TeamAppearance teamRank, Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||||
{
|
{
|
||||||
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, teamRank.Floor);
|
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, teamRank.Floor);
|
||||||
Up = teamRank.Up.Select(teamRate => new Team(teamRate, idAvatarMap)).ToList();
|
Up = teamRank.Up.Select(teamRate => new Team(teamRate, idAvatarMap)).ToList();
|
||||||
@@ -3,18 +3,18 @@
|
|||||||
|
|
||||||
using Snap.Hutao.Model.Primitive;
|
using Snap.Hutao.Model.Primitive;
|
||||||
|
|
||||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
namespace Snap.Hutao.ViewModel.Complex;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 武器搭配
|
/// 武器搭配
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal sealed class ComplexWeaponCollocation
|
internal sealed class WeaponCollocationView
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色
|
/// 角色
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ComplexAvatar> Avatars { get; set; } = default!;
|
public List<AvatarView> Avatars { get; set; } = default!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 武器Id
|
/// 武器Id
|
||||||
@@ -1,24 +1,25 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Snap.Hutao.Model.Binding;
|
||||||
using Snap.Hutao.Model.Intrinsic;
|
using Snap.Hutao.Model.Intrinsic;
|
||||||
using Snap.Hutao.Model.Metadata.Converter;
|
using Snap.Hutao.Model.Metadata.Converter;
|
||||||
using Snap.Hutao.Model.Metadata.Weapon;
|
using Snap.Hutao.Model.Metadata.Weapon;
|
||||||
|
|
||||||
namespace Snap.Hutao.Model.Binding.Hutao;
|
namespace Snap.Hutao.ViewModel.Complex;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 胡桃数据库武器
|
/// 胡桃数据库武器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal sealed class ComplexWeapon : INameIcon
|
internal sealed class WeaponView : INameIcon
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造一个胡桃数据库武器
|
/// 构造一个胡桃数据库武器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="weapon">元数据武器</param>
|
/// <param name="weapon">元数据武器</param>
|
||||||
/// <param name="rate">率</param>
|
/// <param name="rate">率</param>
|
||||||
public ComplexWeapon(Weapon weapon, double rate)
|
public WeaponView(Weapon weapon, double rate)
|
||||||
{
|
{
|
||||||
Name = weapon.Name;
|
Name = weapon.Name;
|
||||||
Icon = EquipIconConverter.IconNameToUri(weapon.Icon);
|
Icon = EquipIconConverter.IconNameToUri(weapon.Icon);
|
||||||
@@ -2,12 +2,9 @@
|
|||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.UI.Windowing;
|
|
||||||
using Snap.Hutao.Control.Extension;
|
using Snap.Hutao.Control.Extension;
|
||||||
using Snap.Hutao.Core.Database;
|
|
||||||
using Snap.Hutao.Core.ExceptionService;
|
using Snap.Hutao.Core.ExceptionService;
|
||||||
using Snap.Hutao.Core.LifeCycle;
|
using Snap.Hutao.Core.LifeCycle;
|
||||||
using Snap.Hutao.Model.Binding.LaunchGame;
|
using Snap.Hutao.Model.Binding.LaunchGame;
|
||||||
@@ -21,7 +18,6 @@ using Snap.Hutao.View.Dialog;
|
|||||||
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Windows.Graphics;
|
|
||||||
|
|
||||||
namespace Snap.Hutao.ViewModel;
|
namespace Snap.Hutao.ViewModel;
|
||||||
|
|
||||||
@@ -47,13 +43,6 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
|||||||
private LaunchScheme? selectedScheme;
|
private LaunchScheme? selectedScheme;
|
||||||
private ObservableCollection<GameAccount>? gameAccounts;
|
private ObservableCollection<GameAccount>? gameAccounts;
|
||||||
private GameAccount? selectedGameAccount;
|
private GameAccount? selectedGameAccount;
|
||||||
private bool isExclusive;
|
|
||||||
private bool isFullScreen;
|
|
||||||
private bool isBorderless;
|
|
||||||
private int screenWidth;
|
|
||||||
private int screenHeight;
|
|
||||||
private bool unlockFps;
|
|
||||||
private int targetFps;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造一个新的启动游戏视图模型
|
/// 构造一个新的启动游戏视图模型
|
||||||
@@ -64,9 +53,9 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
|||||||
gameService = serviceProvider.GetRequiredService<IGameService>();
|
gameService = serviceProvider.GetRequiredService<IGameService>();
|
||||||
appDbContext = serviceProvider.GetRequiredService<AppDbContext>();
|
appDbContext = serviceProvider.GetRequiredService<AppDbContext>();
|
||||||
memoryCache = serviceProvider.GetRequiredService<IMemoryCache>();
|
memoryCache = serviceProvider.GetRequiredService<IMemoryCache>();
|
||||||
|
Options = serviceProvider.GetRequiredService<LaunchOptions>();
|
||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
|
|
||||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
|
||||||
LaunchCommand = new AsyncRelayCommand(LaunchAsync);
|
LaunchCommand = new AsyncRelayCommand(LaunchAsync);
|
||||||
DetectGameAccountCommand = new AsyncRelayCommand(DetectGameAccountAsync);
|
DetectGameAccountCommand = new AsyncRelayCommand(DetectGameAccountAsync);
|
||||||
ModifyGameAccountCommand = new AsyncRelayCommand<GameAccount>(ModifyGameAccountAsync);
|
ModifyGameAccountCommand = new AsyncRelayCommand<GameAccount>(ModifyGameAccountAsync);
|
||||||
@@ -95,76 +84,9 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
|||||||
public GameAccount? SelectedGameAccount { get => selectedGameAccount; set => SetProperty(ref selectedGameAccount, value); }
|
public GameAccount? SelectedGameAccount { get => selectedGameAccount; set => SetProperty(ref selectedGameAccount, value); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否为独占全屏
|
/// 启动选项
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsExclusive
|
public LaunchOptions Options { get; }
|
||||||
{
|
|
||||||
get => isExclusive; set
|
|
||||||
{
|
|
||||||
if (SetProperty(ref isExclusive, value))
|
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
IsFullScreen = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 全屏
|
|
||||||
/// </summary>
|
|
||||||
public bool IsFullScreen
|
|
||||||
{
|
|
||||||
get => isFullScreen; set
|
|
||||||
{
|
|
||||||
if (SetProperty(ref isFullScreen, value))
|
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
IsBorderless = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 无边框
|
|
||||||
/// </summary>
|
|
||||||
public bool IsBorderless
|
|
||||||
{
|
|
||||||
get => isBorderless; set
|
|
||||||
{
|
|
||||||
if (SetProperty(ref isBorderless, value))
|
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
IsExclusive = false;
|
|
||||||
IsFullScreen = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 宽度
|
|
||||||
/// </summary>
|
|
||||||
public int ScreenWidth { get => screenWidth; set => SetProperty(ref screenWidth, value); }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 高度
|
|
||||||
/// </summary>
|
|
||||||
public int ScreenHeight { get => screenHeight; set => SetProperty(ref screenHeight, value); }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解锁帧率
|
|
||||||
/// </summary>
|
|
||||||
public bool UnlockFps { get => unlockFps; set => SetProperty(ref unlockFps, value); }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 目标帧率
|
|
||||||
/// </summary>
|
|
||||||
public int TargetFps { get => targetFps; set => SetProperty(ref targetFps, value); }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否提权
|
/// 是否提权
|
||||||
@@ -172,11 +94,6 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
|||||||
[SuppressMessage("", "CA1822")]
|
[SuppressMessage("", "CA1822")]
|
||||||
public bool IsElevated { get => Activation.GetElevated(); }
|
public bool IsElevated { get => Activation.GetElevated(); }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 打开界面命令
|
|
||||||
/// </summary>
|
|
||||||
public ICommand OpenUICommand { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 启动游戏命令
|
/// 启动游戏命令
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -202,7 +119,8 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ICommand AttachGameAccountCommand { get; }
|
public ICommand AttachGameAccountCommand { get; }
|
||||||
|
|
||||||
private async Task OpenUIAsync()
|
/// <inheritdoc/>
|
||||||
|
protected override async Task OpenUIAsync()
|
||||||
{
|
{
|
||||||
if (File.Exists(gameService.GetGamePathSkipLocator()))
|
if (File.Exists(gameService.GetGamePathSkipLocator()))
|
||||||
{
|
{
|
||||||
@@ -228,9 +146,6 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
|||||||
SelectedGameAccount = GameAccounts.FirstOrDefault(g => g.AttachUid == uid);
|
SelectedGameAccount = GameAccounts.FirstOrDefault(g => g.AttachUid == uid);
|
||||||
memoryCache.Remove(DesiredUid);
|
memoryCache.Remove(DesiredUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync from Settings
|
|
||||||
RetiveSetting();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
@@ -246,44 +161,6 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RetiveSetting()
|
|
||||||
{
|
|
||||||
DbSet<SettingEntry> settings = appDbContext.Settings;
|
|
||||||
|
|
||||||
isFullScreen = settings.SingleOrAdd(SettingEntry.LaunchIsFullScreen, Core.StringLiterals.True).GetBoolean();
|
|
||||||
OnPropertyChanged(nameof(IsFullScreen));
|
|
||||||
|
|
||||||
isBorderless = settings.SingleOrAdd(SettingEntry.LaunchIsBorderless, Core.StringLiterals.False).GetBoolean();
|
|
||||||
OnPropertyChanged(nameof(IsBorderless));
|
|
||||||
|
|
||||||
RectInt32 primaryRect = DisplayArea.Primary.OuterBounds;
|
|
||||||
|
|
||||||
screenWidth = settings.SingleOrAdd(SettingEntry.LaunchScreenWidth, $"{primaryRect.Width}").GetInt32();
|
|
||||||
OnPropertyChanged(nameof(ScreenWidth));
|
|
||||||
|
|
||||||
screenHeight = settings.SingleOrAdd(SettingEntry.LaunchScreenHeight, $"{primaryRect.Height}").GetInt32();
|
|
||||||
OnPropertyChanged(nameof(ScreenHeight));
|
|
||||||
|
|
||||||
unlockFps = settings.SingleOrAdd(SettingEntry.LaunchUnlockFps, Core.StringLiterals.False).GetBoolean();
|
|
||||||
OnPropertyChanged(nameof(UnlockFps));
|
|
||||||
|
|
||||||
targetFps = settings.SingleOrAdd(SettingEntry.LaunchTargetFps, "60").GetInt32();
|
|
||||||
OnPropertyChanged(nameof(TargetFps));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SaveSetting()
|
|
||||||
{
|
|
||||||
DbSet<SettingEntry> settings = appDbContext.Settings;
|
|
||||||
settings.SingleOrAdd(SettingEntry.LaunchIsExclusive, Core.StringLiterals.False).SetBoolean(IsExclusive);
|
|
||||||
settings.SingleOrAdd(SettingEntry.LaunchIsFullScreen, Core.StringLiterals.False).SetBoolean(IsFullScreen);
|
|
||||||
settings.SingleOrAdd(SettingEntry.LaunchIsBorderless, Core.StringLiterals.False).SetBoolean(IsBorderless);
|
|
||||||
settings.SingleOrAdd(SettingEntry.LaunchScreenWidth, "1920").SetInt32(ScreenWidth);
|
|
||||||
settings.SingleOrAdd(SettingEntry.LaunchScreenHeight, "1080").SetInt32(ScreenHeight);
|
|
||||||
settings.SingleOrAdd(SettingEntry.LaunchUnlockFps, Core.StringLiterals.False).SetBoolean(UnlockFps);
|
|
||||||
settings.SingleOrAdd(SettingEntry.LaunchTargetFps, "60").SetInt32(TargetFps);
|
|
||||||
appDbContext.SaveChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task LaunchAsync()
|
private async Task LaunchAsync()
|
||||||
{
|
{
|
||||||
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||||
@@ -322,10 +199,7 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveSetting();
|
await gameService.LaunchAsync(Options).ConfigureAwait(false);
|
||||||
|
|
||||||
LaunchConfiguration configuration = new(IsExclusive, IsFullScreen, IsBorderless, ScreenWidth, ScreenHeight, IsElevated && UnlockFps, TargetFps);
|
|
||||||
await gameService.LaunchAsync(configuration).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -46,10 +46,10 @@ internal sealed class SettingViewModel : Abstraction.ViewModel
|
|||||||
|
|
||||||
private readonly List<NameValue<string>> cultures = new()
|
private readonly List<NameValue<string>> cultures = new()
|
||||||
{
|
{
|
||||||
ToNameValue(CultureInfo.CreateSpecificCulture("zh-CN")),
|
ToNameValue(CultureInfo.GetCultureInfo("zh-Hans")),
|
||||||
ToNameValue(CultureInfo.CreateSpecificCulture("zh-TW")),
|
ToNameValue(CultureInfo.GetCultureInfo("zh-Hant")),
|
||||||
ToNameValue(CultureInfo.CreateSpecificCulture("en-US")),
|
ToNameValue(CultureInfo.GetCultureInfo("en")),
|
||||||
ToNameValue(CultureInfo.CreateSpecificCulture("ko-KR")),
|
ToNameValue(CultureInfo.GetCultureInfo("ko")),
|
||||||
};
|
};
|
||||||
|
|
||||||
private bool isEmptyHistoryWishVisible;
|
private bool isEmptyHistoryWishVisible;
|
||||||
@@ -102,7 +102,7 @@ internal sealed class SettingViewModel : Abstraction.ViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Webview2 版本
|
/// WebView2 版本
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SuppressMessage("", "CA1822")]
|
[SuppressMessage("", "CA1822")]
|
||||||
public string WebView2Version
|
public string WebView2Version
|
||||||
@@ -226,6 +226,12 @@ internal sealed class SettingViewModel : Abstraction.ViewModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ICommand ResetStaticResourceCommand { get; }
|
public ICommand ResetStaticResourceCommand { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override Task OpenUIAsync()
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
private static NameValue<string> ToNameValue(CultureInfo info)
|
private static NameValue<string> ToNameValue(CultureInfo info)
|
||||||
{
|
{
|
||||||
return new(info.NativeName, info.Name);
|
return new(info.NativeName, info.Name);
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ internal sealed class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecip
|
|||||||
userService = serviceProvider.GetRequiredService<IUserService>();
|
userService = serviceProvider.GetRequiredService<IUserService>();
|
||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
|
|
||||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
|
||||||
RefreshCommand = new AsyncRelayCommand(RefreshAsync);
|
RefreshCommand = new AsyncRelayCommand(RefreshAsync);
|
||||||
UploadSpiralAbyssRecordCommand = new AsyncRelayCommand(UploadSpiralAbyssRecordAsync);
|
UploadSpiralAbyssRecordCommand = new AsyncRelayCommand(UploadSpiralAbyssRecordAsync);
|
||||||
|
|
||||||
@@ -86,11 +85,6 @@ internal sealed class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecip
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public SpiralAbyssView? SpiralAbyssView { get => spiralAbyssView; set => SetProperty(ref spiralAbyssView, value); }
|
public SpiralAbyssView? SpiralAbyssView { get => spiralAbyssView; set => SetProperty(ref spiralAbyssView, value); }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 打开界面命令
|
|
||||||
/// </summary>
|
|
||||||
public ICommand OpenUICommand { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 刷新界面命令
|
/// 刷新界面命令
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -114,7 +108,8 @@ internal sealed class SpiralAbyssRecordViewModel : Abstraction.ViewModel, IRecip
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OpenUIAsync()
|
/// <inheritdoc/>
|
||||||
|
protected override async Task OpenUIAsync()
|
||||||
{
|
{
|
||||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -53,6 +53,12 @@ internal sealed class TestViewModel : Abstraction.ViewModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ICommand RestartAppCommand { get; }
|
public ICommand RestartAppCommand { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override Task OpenUIAsync()
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task ShowCommunityGameRecordDialogAsync()
|
private async Task ShowCommunityGameRecordDialogAsync()
|
||||||
{
|
{
|
||||||
// ContentDialog must be created by main thread.
|
// ContentDialog must be created by main thread.
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ using Snap.Hutao.Service.Hutao;
|
|||||||
using Snap.Hutao.Service.Metadata;
|
using Snap.Hutao.Service.Metadata;
|
||||||
using Snap.Hutao.Service.User;
|
using Snap.Hutao.Service.User;
|
||||||
using Snap.Hutao.View.Dialog;
|
using Snap.Hutao.View.Dialog;
|
||||||
|
using Snap.Hutao.ViewModel.Complex;
|
||||||
using Snap.Hutao.Web.Response;
|
using Snap.Hutao.Web.Response;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
@@ -59,7 +60,6 @@ internal sealed class WikiAvatarViewModel : Abstraction.ViewModel
|
|||||||
hutaoCache = serviceProvider.GetRequiredService<IHutaoCache>();
|
hutaoCache = serviceProvider.GetRequiredService<IHutaoCache>();
|
||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
|
|
||||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
|
||||||
CultivateCommand = new AsyncRelayCommand<Avatar>(CultivateAsync);
|
CultivateCommand = new AsyncRelayCommand<Avatar>(CultivateAsync);
|
||||||
FilterCommand = new RelayCommand<string>(ApplyFilter);
|
FilterCommand = new RelayCommand<string>(ApplyFilter);
|
||||||
}
|
}
|
||||||
@@ -93,11 +93,6 @@ internal sealed class WikiAvatarViewModel : Abstraction.ViewModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 打开页面命令
|
|
||||||
/// </summary>
|
|
||||||
public ICommand OpenUICommand { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 养成命令
|
/// 养成命令
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -108,7 +103,8 @@ internal sealed class WikiAvatarViewModel : Abstraction.ViewModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ICommand FilterCommand { get; }
|
public ICommand FilterCommand { get; }
|
||||||
|
|
||||||
private async Task OpenUIAsync()
|
/// <inheritdoc/>
|
||||||
|
protected override async Task OpenUIAsync()
|
||||||
{
|
{
|
||||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
@@ -134,7 +130,7 @@ internal sealed class WikiAvatarViewModel : Abstraction.ViewModel
|
|||||||
{
|
{
|
||||||
if (await hutaoCache.InitializeForWikiAvatarViewModelAsync().ConfigureAwait(false))
|
if (await hutaoCache.InitializeForWikiAvatarViewModelAsync().ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
Dictionary<AvatarId, ComplexAvatarCollocation> idCollocations = hutaoCache.AvatarCollocations!.ToDictionary(a => a.AvatarId);
|
Dictionary<AvatarId, AvatarCollocationView> idCollocations = hutaoCache.AvatarCollocations!.ToDictionary(a => a.AvatarId);
|
||||||
|
|
||||||
foreach (Avatar avatar in avatars)
|
foreach (Avatar avatar in avatars)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,31 +1,15 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.Input;
|
|
||||||
using CommunityToolkit.WinUI.UI;
|
using CommunityToolkit.WinUI.UI;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Primitives;
|
|
||||||
using Snap.Hutao.Model.Binding.BaseValue;
|
using Snap.Hutao.Model.Binding.BaseValue;
|
||||||
using Snap.Hutao.Model.Binding.Hutao;
|
|
||||||
using Snap.Hutao.Model.Entity.Primitive;
|
|
||||||
using Snap.Hutao.Model.Intrinsic;
|
using Snap.Hutao.Model.Intrinsic;
|
||||||
using Snap.Hutao.Model.Intrinsic.Immutable;
|
|
||||||
using Snap.Hutao.Model.Metadata.Item;
|
using Snap.Hutao.Model.Metadata.Item;
|
||||||
using Snap.Hutao.Model.Metadata.Monster;
|
using Snap.Hutao.Model.Metadata.Monster;
|
||||||
using Snap.Hutao.Model.Metadata.Weapon;
|
|
||||||
using Snap.Hutao.Model.Primitive;
|
using Snap.Hutao.Model.Primitive;
|
||||||
using Snap.Hutao.Service.Abstraction;
|
|
||||||
using Snap.Hutao.Service.Cultivation;
|
|
||||||
using Snap.Hutao.Service.Hutao;
|
|
||||||
using Snap.Hutao.Service.Metadata;
|
using Snap.Hutao.Service.Metadata;
|
||||||
using Snap.Hutao.Service.User;
|
|
||||||
using Snap.Hutao.View.Dialog;
|
|
||||||
using Snap.Hutao.Web.Response;
|
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using CalcAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta;
|
|
||||||
using CalcClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient;
|
|
||||||
using CalcConsumption = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.Consumption;
|
|
||||||
|
|
||||||
namespace Snap.Hutao.ViewModel;
|
namespace Snap.Hutao.ViewModel;
|
||||||
|
|
||||||
@@ -35,16 +19,13 @@ namespace Snap.Hutao.ViewModel;
|
|||||||
[Injection(InjectAs.Scoped)]
|
[Injection(InjectAs.Scoped)]
|
||||||
internal class WikiMonsterViewModel : Abstraction.ViewModel
|
internal class WikiMonsterViewModel : Abstraction.ViewModel
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider serviceProvider;
|
|
||||||
private readonly IMetadataService metadataService;
|
private readonly IMetadataService metadataService;
|
||||||
private readonly IHutaoCache hutaoCache;
|
|
||||||
|
|
||||||
private AdvancedCollectionView? monsters;
|
private AdvancedCollectionView? monsters;
|
||||||
private Monster? selected;
|
private Monster? selected;
|
||||||
private string? filterText;
|
private string? filterText;
|
||||||
private BaseValueInfo? baseValueInfo;
|
private BaseValueInfo? baseValueInfo;
|
||||||
private Dictionary<int, Dictionary<GrowCurveType, float>>? levelMonsterCurveMap;
|
private Dictionary<int, Dictionary<GrowCurveType, float>>? levelMonsterCurveMap;
|
||||||
private Dictionary<MaterialId, Material>? idMaterialMap;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造一个新的怪物资料视图模型
|
/// 构造一个新的怪物资料视图模型
|
||||||
@@ -53,10 +34,6 @@ internal class WikiMonsterViewModel : Abstraction.ViewModel
|
|||||||
public WikiMonsterViewModel(IServiceProvider serviceProvider)
|
public WikiMonsterViewModel(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
metadataService = serviceProvider.GetRequiredService<IMetadataService>();
|
metadataService = serviceProvider.GetRequiredService<IMetadataService>();
|
||||||
hutaoCache = serviceProvider.GetRequiredService<IHutaoCache>();
|
|
||||||
this.serviceProvider = serviceProvider;
|
|
||||||
|
|
||||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -88,12 +65,8 @@ internal class WikiMonsterViewModel : Abstraction.ViewModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// 打开界面命令
|
protected override async Task OpenUIAsync()
|
||||||
/// </summary>
|
|
||||||
public ICommand OpenUICommand { get; }
|
|
||||||
|
|
||||||
private async Task OpenUIAsync()
|
|
||||||
{
|
{
|
||||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using CommunityToolkit.WinUI.UI;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using Snap.Hutao.Model.Binding.BaseValue;
|
using Snap.Hutao.Model.Binding.BaseValue;
|
||||||
using Snap.Hutao.Model.Binding.Hutao;
|
|
||||||
using Snap.Hutao.Model.Entity.Primitive;
|
using Snap.Hutao.Model.Entity.Primitive;
|
||||||
using Snap.Hutao.Model.Intrinsic;
|
using Snap.Hutao.Model.Intrinsic;
|
||||||
using Snap.Hutao.Model.Intrinsic.Immutable;
|
using Snap.Hutao.Model.Intrinsic.Immutable;
|
||||||
@@ -19,6 +18,7 @@ using Snap.Hutao.Service.Hutao;
|
|||||||
using Snap.Hutao.Service.Metadata;
|
using Snap.Hutao.Service.Metadata;
|
||||||
using Snap.Hutao.Service.User;
|
using Snap.Hutao.Service.User;
|
||||||
using Snap.Hutao.View.Dialog;
|
using Snap.Hutao.View.Dialog;
|
||||||
|
using Snap.Hutao.ViewModel.Complex;
|
||||||
using Snap.Hutao.Web.Response;
|
using Snap.Hutao.Web.Response;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
@@ -61,7 +61,6 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
|||||||
hutaoCache = serviceProvider.GetRequiredService<IHutaoCache>();
|
hutaoCache = serviceProvider.GetRequiredService<IHutaoCache>();
|
||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
|
|
||||||
OpenUICommand = new AsyncRelayCommand(OpenUIAsync);
|
|
||||||
CultivateCommand = new AsyncRelayCommand<Weapon>(CultivateAsync);
|
CultivateCommand = new AsyncRelayCommand<Weapon>(CultivateAsync);
|
||||||
FilterCommand = new RelayCommand<string>(ApplyFilter);
|
FilterCommand = new RelayCommand<string>(ApplyFilter);
|
||||||
}
|
}
|
||||||
@@ -95,11 +94,6 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 打开界面命令
|
|
||||||
/// </summary>
|
|
||||||
public ICommand OpenUICommand { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 养成命令
|
/// 养成命令
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -110,7 +104,8 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ICommand FilterCommand { get; }
|
public ICommand FilterCommand { get; }
|
||||||
|
|
||||||
private async Task OpenUIAsync()
|
/// <inheritdoc/>
|
||||||
|
protected override async Task OpenUIAsync()
|
||||||
{
|
{
|
||||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
@@ -137,7 +132,7 @@ internal class WikiWeaponViewModel : Abstraction.ViewModel
|
|||||||
{
|
{
|
||||||
if (await hutaoCache.InitializeForWikiWeaponViewModelAsync().ConfigureAwait(false))
|
if (await hutaoCache.InitializeForWikiWeaponViewModelAsync().ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
Dictionary<WeaponId, ComplexWeaponCollocation> idCollocations = hutaoCache.WeaponCollocations!.ToDictionary(a => a.WeaponId);
|
Dictionary<WeaponId, WeaponCollocationView> idCollocations = hutaoCache.WeaponCollocations!.ToDictionary(a => a.WeaponId);
|
||||||
weapons.ForEach(w => w.Collocation = idCollocations.GetValueOrDefault(w.Id));
|
weapons.ForEach(w => w.Collocation = idCollocations.GetValueOrDefault(w.Id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Buffers.Binary;
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Windows.Graphics;
|
using Windows.Graphics;
|
||||||
|
using Windows.Win32.Graphics.Gdi;
|
||||||
using Windows.Win32.System.Diagnostics.ToolHelp;
|
using Windows.Win32.System.Diagnostics.ToolHelp;
|
||||||
using Windows.Win32.UI.WindowsAndMessaging;
|
using Windows.Win32.UI.WindowsAndMessaging;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user