增加参数保存功能

This commit is contained in:
ww-rm
2025-06-15 14:38:37 +08:00
parent 0dcf8c5577
commit 7bd3e3669b
5 changed files with 113 additions and 17 deletions

View File

@@ -13,6 +13,8 @@ namespace SpineViewer.Models
{
public class SpineObjectConfigModel
{
public bool IsShown { get; set; } = true;
public bool UsePma { get; set; }
public string Physics { get; set; } = ISkeleton.Physics.Update.ToString();

View File

@@ -359,6 +359,8 @@ namespace SpineViewer.Models
FlipY = _spineObject.Skeleton.ScaleY < 0,
X = _spineObject.Skeleton.X,
Y = _spineObject.Skeleton.Y,
IsShown = _isShown,
UsePma = _spineObject.UsePma,
Physics = _spineObject.Physics.ToString(),
@@ -399,6 +401,8 @@ namespace SpineViewer.Models
SetProperty(_spineObject.Skeleton.ScaleY < 0, config.FlipY, v => _spineObject.Skeleton.ScaleY *= -1, nameof(FlipY));
SetProperty(_spineObject.Skeleton.X, config.X, v => _spineObject.Skeleton.X = v, nameof(X));
SetProperty(_spineObject.Skeleton.Y, config.Y, v => _spineObject.Skeleton.Y = v, nameof(Y));
IsShown = config.IsShown;
SetProperty(_spineObject.UsePma, config.UsePma, v => _spineObject.UsePma = v, nameof(UsePma));
SetProperty(_spineObject.Physics, Enum.Parse<ISkeleton.Physics>(config.Physics ?? "Update", true), v => _spineObject.Physics = v, nameof(Physics));

View File

@@ -68,27 +68,47 @@ namespace SpineViewer.Services
/// <returns>是否确认了选择</returns>
public static bool ShowOpenFolderDialog(out string? folderName)
{
// XXX: 此处使用了 System.Windows.Forms 的文件夹浏览对话框
var folderDialog = new OpenFolderDialog() { Multiselect = false };
if (folderDialog.ShowDialog() is true)
var dialog = new OpenFolderDialog() { Multiselect = false };
if (dialog.ShowDialog() is true)
{
folderName = folderDialog.FolderName;
folderName = dialog.FolderName;
return true;
}
folderName = null;
return false;
}
/// <summary>
/// 获取用户选择的文件夹
/// </summary>
/// <param name="selectedPath"></param>
/// <returns>是否确认了选择</returns>
public static bool ShowSaveFileDialog(out string? selectedPath)
public static bool ShowOpenFileDialog(out string? fileName, string initialDirectory = "", string filter = "All|*.*")
{
var dialog = new SaveFileDialog() { };
selectedPath = null;
// TODO
var dialog = new OpenFileDialog()
{
InitialDirectory = initialDirectory,
Filter = filter
};
if (dialog.ShowDialog() is true)
{
fileName = dialog.FileName;
return true;
}
fileName = null;
return false;
}
public static bool ShowSaveFileDialog(ref string? fileName, string initialDirectory = "", string defaultExt = "", string filter = "All|*.*")
{
var dialog = new SaveFileDialog()
{
FileName = fileName,
InitialDirectory = initialDirectory,
DefaultExt = defaultExt,
Filter = filter,
};
if (dialog.ShowDialog() is true)
{
fileName = dialog.FileName;
return true;
}
fileName = null;
return false;
}
}

View File

@@ -15,7 +15,6 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace SpineViewer.ViewModels.MainWindow
@@ -348,6 +347,74 @@ namespace SpineViewer.ViewModels.MainWindow
return true;
}
public RelayCommand<IList?> Cmd_ApplySpineObjectConfigFromFile => _cmd_ApplySpineObjectConfigFromFile ??= new(ApplySpineObjectConfigFromFile_Execute, ApplySpineObjectConfigFromFile_CanExecute);
private RelayCommand<IList?>? _cmd_ApplySpineObjectConfigFromFile;
private void ApplySpineObjectConfigFromFile_Execute(IList? args)
{
if (!ApplySpineObjectConfigFromFile_CanExecute(args)) return;
if (!DialogService.ShowOpenFileDialog(out var fileName, filter: "Json Config|*.jcfg|All|*.*")) return;
try
{
var config = SpineObjectConfigModel.Deserialize(fileName);
foreach (SpineObjectModel sp in args)
{
sp.Load(config);
_logger.Info("Apply config to model: {0}", sp.Name);
}
}
catch (Exception ex)
{
_logger.Error("Failed to apply config file {0}, {1}", fileName, ex.Message);
_logger.Trace(ex.ToString());
return;
}
}
private bool ApplySpineObjectConfigFromFile_CanExecute(IList? args)
{
if (args is null) return false;
if (args.Count <= 0) return false;
return true;
}
public RelayCommand<IList?> Cmd_SaveSpineObjectConfigToFile => _cmd_SaveSpineObjectConfigToFile ??= new(SaveSpineObjectConfigToFile_Execute, SaveSpineObjectConfigToFile_CanExecute);
private RelayCommand<IList?>? _cmd_SaveSpineObjectConfigToFile;
private void SaveSpineObjectConfigToFile_Execute(IList? args)
{
if (!SaveSpineObjectConfigToFile_CanExecute(args)) return;
var sp = (SpineObjectModel)args[0];
var config = sp.Dump();
string fileName = $"{Path.ChangeExtension(Path.GetFileName(sp.SkelPath), ".jcfg")}";
if (!DialogService.ShowSaveFileDialog(
ref fileName,
initialDirectory: sp.AssetsDir,
defaultExt: ".jcfg",
filter:"Json Config|*.jcfg|All|*.*")
)
return;
try
{
sp.Dump().Serialize(fileName);
_logger.Info("{0} config save to {1}", sp.Name, fileName);
}
catch (Exception ex)
{
_logger.Error("Failed to save config file {0}, {1}", fileName, ex.Message);
_logger.Trace(ex.ToString());
return;
}
}
private bool SaveSpineObjectConfigToFile_CanExecute(IList? args)
{
if (args is null) return false;
if (args.Count != 1) return false;
return true;
}
/// <summary>
/// 从路径列表添加对象
/// </summary>

View File

@@ -288,9 +288,12 @@
InputGestureText="Ctrl+Shift+V"
Command="{Binding Cmd_ApplySpineObjectConfig}"
CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
<Separator/>
<MenuItem Header="{DynamicResource Str_ApplySpineObjectConfigFromFile}"/>
<MenuItem Header="{DynamicResource Str_SaveSpineObjectConfigToFile}"/>
<MenuItem Header="{DynamicResource Str_ApplySpineObjectConfigFromFile}"
Command="{Binding Cmd_ApplySpineObjectConfigFromFile}"
CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
<MenuItem Header="{DynamicResource Str_SaveSpineObjectConfigToFile}"
Command="{Binding Cmd_SaveSpineObjectConfigToFile}"
CommandParameter="{Binding PlacementTarget.SelectedItems, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>
<Separator/>
<MenuItem Header="{DynamicResource Str_Export}">
<MenuItem Header="{DynamicResource Str_ExportFrame}"