增加首选项对话框
This commit is contained in:
@@ -34,6 +34,7 @@ namespace SpineViewer.ViewModels.MainWindow
|
||||
_explorerListViewModel = new(this);
|
||||
_spineObjectListViewModel = new(this);
|
||||
_sfmlRendererViewModel = new(this);
|
||||
_preferenceViewModel = new(this);
|
||||
}
|
||||
|
||||
public string Title => $"SpineViewer - v{App.Version}";
|
||||
@@ -56,6 +57,9 @@ namespace SpineViewer.ViewModels.MainWindow
|
||||
public ObservableCollectionWithLock<SpineObjectModel> SpineObjects => _spineObjectModels;
|
||||
private readonly ObservableCollectionWithLock<SpineObjectModel> _spineObjectModels = [];
|
||||
|
||||
public PreferenceViewModel PreferenceViewModel => _preferenceViewModel;
|
||||
private readonly PreferenceViewModel _preferenceViewModel;
|
||||
|
||||
/// <summary>
|
||||
/// 浏览页列表 ViewModel
|
||||
/// </summary>
|
||||
|
||||
191
SpineViewer/ViewModels/MainWindow/PreferenceViewModel.cs
Normal file
191
SpineViewer/ViewModels/MainWindow/PreferenceViewModel.cs
Normal file
@@ -0,0 +1,191 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using NLog;
|
||||
using Spine.SpineWrappers;
|
||||
using SpineViewer.Models;
|
||||
using SpineViewer.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace SpineViewer.ViewModels.MainWindow
|
||||
{
|
||||
public class PreferenceViewModel : ObservableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件保存路径
|
||||
/// </summary>
|
||||
public static readonly string PreferenceFilePath = Path.Combine(Path.GetDirectoryName(Environment.ProcessPath), "preference.json");
|
||||
|
||||
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly MainWindowViewModel _vmMain;
|
||||
|
||||
public PreferenceViewModel(MainWindowViewModel vmMain)
|
||||
{
|
||||
_vmMain = vmMain;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示首选项对话框
|
||||
/// </summary>
|
||||
public RelayCommand Cmd_ShowPreferenceDialog => _cmd_ShowPreferenceDialog ??= new(ShowPreferenceDialog_Execute);
|
||||
private RelayCommand? _cmd_ShowPreferenceDialog;
|
||||
|
||||
private void ShowPreferenceDialog_Execute()
|
||||
{
|
||||
var m = Preference;
|
||||
if (!DialogService.ShowPreferenceDialog(m))
|
||||
return;
|
||||
|
||||
Preference = m;
|
||||
SavePreference(m);
|
||||
}
|
||||
|
||||
private static void SavePreference(PreferenceModel m)
|
||||
{
|
||||
try
|
||||
{
|
||||
m.Serialize(PreferenceFilePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error("Failed to save preference to {0}, {1}", PreferenceFilePath, ex.Message);
|
||||
_logger.Trace(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存首选项, 保存失败会有日志提示
|
||||
/// </summary>
|
||||
public void SavePreference() => SavePreference(Preference);
|
||||
|
||||
/// <summary>
|
||||
/// 加载首选项, 加载失败会有日志提示
|
||||
/// </summary>
|
||||
public void LoadPreference()
|
||||
{
|
||||
if (!File.Exists(PreferenceFilePath)) return;
|
||||
|
||||
try
|
||||
{
|
||||
var m = PreferenceModel.Deserialize(PreferenceFilePath);
|
||||
Preference = m;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error("Failed to load preference from {0}, {1}", PreferenceFilePath, ex.Message);
|
||||
_logger.Trace(ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取参数副本或者进行设置
|
||||
/// </summary>
|
||||
private PreferenceModel Preference
|
||||
{
|
||||
get
|
||||
{
|
||||
return new()
|
||||
{
|
||||
ForcePremul = ForcePremul,
|
||||
ForceNearest = ForceNearest,
|
||||
ForceMipmap = ForceMipmap,
|
||||
UsePma = UsePma,
|
||||
DebugTexture = DebugTexture,
|
||||
DebugBounds = DebugBounds,
|
||||
DebugBones = DebugBones,
|
||||
DebugRegions = DebugRegions,
|
||||
DebugMeshHulls = DebugMeshHulls,
|
||||
DebugMeshes = DebugMeshes,
|
||||
DebugBoundingBoxes = DebugBoundingBoxes,
|
||||
DebugPaths = DebugPaths,
|
||||
DebugPoints = DebugPoints,
|
||||
DebugClippings = DebugClippings
|
||||
};
|
||||
}
|
||||
set
|
||||
{
|
||||
ForcePremul = value.ForcePremul;
|
||||
ForceNearest = value.ForceNearest;
|
||||
ForceMipmap = value.ForceMipmap;
|
||||
UsePma = value.UsePma;
|
||||
DebugTexture = value.DebugTexture;
|
||||
DebugBounds = value.DebugBounds;
|
||||
DebugBones = value.DebugBones;
|
||||
DebugRegions = value.DebugRegions;
|
||||
DebugMeshHulls = value.DebugMeshHulls;
|
||||
DebugMeshes = value.DebugMeshes;
|
||||
DebugBoundingBoxes = value.DebugBoundingBoxes;
|
||||
DebugPaths = value.DebugPaths;
|
||||
DebugPoints = value.DebugPoints;
|
||||
DebugClippings = value.DebugClippings;
|
||||
}
|
||||
}
|
||||
|
||||
#region 纹理加载首选项
|
||||
|
||||
public bool ForcePremul
|
||||
{
|
||||
get => TextureLoader.DefaultLoader.ForcePremul;
|
||||
set => SetProperty(TextureLoader.DefaultLoader.ForcePremul, value, v => TextureLoader.DefaultLoader.ForcePremul = v);
|
||||
}
|
||||
|
||||
public bool ForceNearest
|
||||
{
|
||||
get => TextureLoader.DefaultLoader.ForceNearest;
|
||||
set => SetProperty(TextureLoader.DefaultLoader.ForceNearest, value, v => TextureLoader.DefaultLoader.ForceNearest = v);
|
||||
}
|
||||
|
||||
public bool ForceMipmap
|
||||
{
|
||||
get => TextureLoader.DefaultLoader.ForceMipmap;
|
||||
set => SetProperty(TextureLoader.DefaultLoader.ForceMipmap, value, v => TextureLoader.DefaultLoader.ForceMipmap = v);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: 是否自动记忆模型参数
|
||||
|
||||
#region 模型加载首选项
|
||||
|
||||
public bool UsePma { get => _usePma; set => SetProperty(ref _usePma, value); }
|
||||
private bool _usePma;
|
||||
|
||||
public bool DebugTexture { get => _debugTexture; set => SetProperty(ref _debugTexture, value); }
|
||||
private bool _debugTexture = true;
|
||||
|
||||
public bool DebugBounds { get => _debugBounds; set => SetProperty(ref _debugBounds, value); }
|
||||
private bool _debugBounds;
|
||||
|
||||
public bool DebugBones { get => _debugBones; set => SetProperty(ref _debugBones, value); }
|
||||
private bool _debugBones;
|
||||
|
||||
public bool DebugRegions { get => _debugRegions; set => SetProperty(ref _debugRegions, value); }
|
||||
private bool _debugRegions;
|
||||
|
||||
public bool DebugMeshHulls { get => _debugMeshHulls; set => SetProperty(ref _debugMeshHulls, value); }
|
||||
private bool _debugMeshHulls;
|
||||
|
||||
public bool DebugMeshes { get => _debugMeshes; set => SetProperty(ref _debugMeshes, value); }
|
||||
private bool _debugMeshes;
|
||||
|
||||
public bool DebugBoundingBoxes { get => _debugBoundingBoxes; set => SetProperty(ref _debugBoundingBoxes, value); }
|
||||
private bool _debugBoundingBoxes;
|
||||
|
||||
public bool DebugPaths { get => _debugPaths; set => SetProperty(ref _debugPaths, value); }
|
||||
private bool _debugPaths;
|
||||
|
||||
public bool DebugPoints { get => _debugPoints; set => SetProperty(ref _debugPoints, value); }
|
||||
private bool _debugPoints;
|
||||
|
||||
public bool DebugClippings { get => _debugClippings; set => SetProperty(ref _debugClippings, value); }
|
||||
private bool _debugClippings;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,7 @@ namespace SpineViewer.ViewModels.MainWindow
|
||||
|
||||
lock (_spineObjectModels.Lock)
|
||||
{
|
||||
// XXX: 这里必须要浅拷贝一次, 不能直接对会被修改的绑定数据 args 进行 foreach 遍历
|
||||
// NOTE: 这里必须要浅拷贝一次, 不能直接对会被修改的绑定数据 args 进行 foreach 遍历
|
||||
foreach (var sp in args.Cast<SpineObjectModel>().ToArray())
|
||||
{
|
||||
_spineObjectModels.Remove(sp);
|
||||
@@ -249,6 +249,41 @@ namespace SpineViewer.ViewModels.MainWindow
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全地在末尾添加一个模型, 发生错误会输出日志
|
||||
/// </summary>
|
||||
/// <returns>是否添加成功</returns>
|
||||
public bool AddSpineObject(string skelPath, string? atlasPath = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO: 判断是否记忆参数
|
||||
var pre = _vmMain.PreferenceViewModel;
|
||||
var sp = new SpineObjectModel(skelPath, atlasPath)
|
||||
{
|
||||
UsePma = pre.UsePma,
|
||||
DebugTexture = pre.DebugTexture,
|
||||
DebugBounds = pre.DebugBounds,
|
||||
DebugRegions = pre.DebugRegions,
|
||||
DebugMeshHulls = pre.DebugMeshHulls,
|
||||
DebugMeshes = pre.DebugMeshes,
|
||||
DebugBoundingBoxes = pre.DebugBoundingBoxes,
|
||||
DebugPaths = pre.DebugPaths,
|
||||
DebugPoints = pre.DebugPoints,
|
||||
DebugClippings = pre.DebugClippings
|
||||
};
|
||||
|
||||
lock (_spineObjectModels.Lock) _spineObjectModels.Add(sp);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Trace(ex.ToString());
|
||||
_logger.Error("Failed to load: {0}, {1}", skelPath, ex.Message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从路径列表添加对象
|
||||
/// </summary>
|
||||
@@ -289,17 +324,7 @@ namespace SpineViewer.ViewModels.MainWindow
|
||||
}
|
||||
else if (validPaths.Count > 0)
|
||||
{
|
||||
var skelPath = validPaths[0];
|
||||
try
|
||||
{
|
||||
var sp = new SpineObjectModel(skelPath);
|
||||
lock (_spineObjectModels.Lock) _spineObjectModels.Add(sp);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Trace(ex.ToString());
|
||||
_logger.Error("Failed to load: {0}, {1}", skelPath, ex.Message);
|
||||
}
|
||||
AddSpineObject(validPaths[0]);
|
||||
_logger.LogCurrentProcessMemoryUsage();
|
||||
}
|
||||
}
|
||||
@@ -326,18 +351,10 @@ namespace SpineViewer.ViewModels.MainWindow
|
||||
var skelPath = paths[i];
|
||||
reporter.ProgressText = $"[{i}/{totalCount}] {skelPath}";
|
||||
|
||||
try
|
||||
{
|
||||
var sp = new SpineObjectModel(skelPath);
|
||||
lock (_spineObjectModels.Lock) _spineObjectModels.Add(sp);
|
||||
if (AddSpineObject(skelPath))
|
||||
success++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Trace(ex.ToString());
|
||||
_logger.Error("Failed to load: {0}, {1}", skelPath, ex.Message);
|
||||
else
|
||||
error++;
|
||||
}
|
||||
|
||||
reporter.Done = i + 1;
|
||||
reporter.ProgressText = $"[{i + 1}/{totalCount}] {skelPath}";
|
||||
|
||||
Reference in New Issue
Block a user