2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -15,4 +15,4 @@ assignees: ''
|
|||||||
如果有必要,提供报错时的有关截图。/If applicable, add screenshots to help explain your problem.
|
如果有必要,提供报错时的有关截图。/If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
## 附件(可选)/Attachments (Optional)
|
## 附件(可选)/Attachments (Optional)
|
||||||
请将会**出现问题的文件**以及**日志文件**打包成一个 ZIP 后作为附件贴在 issue 内。/Please compress the problematic files and the log files into a single ZIP archive and attach it to this issue.
|
请将会**出现问题的文件**以及**日志文件**打包成一个 ZIP 后作为附件贴在 issue 内,日志文件位于程序目录下的 `logs` 文件夹内。/Please compress the problematic files and the log files into a single ZIP archive and attach it to this issue. The log files are located in the `logs` folder under the program directory.
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## v0.16.0
|
||||||
|
|
||||||
|
- 增加最小化至托盘图标功能
|
||||||
|
- 调整部分参数项的顺序
|
||||||
|
- 增加开机自启和自启文件设置
|
||||||
|
- 切换桌面投影时自动设置预览分辨率为主屏幕分辨率
|
||||||
|
- 修复 3.4 版本下可能存在的附件残留问题
|
||||||
|
|
||||||
## v0.15.19
|
## v0.15.19
|
||||||
|
|
||||||
- 模型重载后选中最后一个重载模型
|
- 模型重载后选中最后一个重载模型
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<TargetFramework>net8.0-windows</TargetFramework>
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
<Version>0.15.18</Version>
|
<Version>0.16.0</Version>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
87
README.en.md
87
README.en.md
@@ -8,29 +8,32 @@
|
|||||||
|
|
||||||
A simple and user-friendly Spine file viewer and exporter with multi-language support (Chinese/English/Japanese).
|
A simple and user-friendly Spine file viewer and exporter with multi-language support (Chinese/English/Japanese).
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
<video src="https://github.com/user-attachments/assets/37b6b730-088a-4352-827a-c338127a16f0">
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Supports multiple versions of Spine files.
|
- Multiple versions of Spine files
|
||||||
* Batch open files via drag-and-drop or copy-paste.
|
- Batch file opening via drag-and-drop or copy-paste
|
||||||
* Batch preview functionality.
|
- Batch preview
|
||||||
* List-based multi-skeleton viewing and render order management.
|
- List-based multi-skeleton viewing and render order management
|
||||||
* Batch adjustment of skeleton parameters using multi-selection.
|
- Multi-selection in lists for batch skeleton parameter settings
|
||||||
* Multi-track animation settings.
|
- Multi-track animation settings
|
||||||
* Skin and custom slot attachment settings.
|
- Skin and custom slot attachment settings
|
||||||
* Custom slot visibility settings.
|
- Custom slot visibility
|
||||||
* Debug rendering support.
|
- Debug rendering
|
||||||
* View/model/track time scale adjustment.
|
- Playback speed adjustment for view/model/track timelines
|
||||||
* Track alpha blending parameter settings.
|
- Track alpha blending parameter settings
|
||||||
* Fullscreen preview mode.
|
- Fullscreen preview
|
||||||
* Export to single frame/image sequence/animated GIF/video formats.
|
- Export to single frame, image sequence, animated GIF, or video file
|
||||||
* Automatic resolution batch export.
|
- Automatic resolution batch export
|
||||||
* FFmpeg custom export support.
|
- Custom export with FFmpeg
|
||||||
* Program parameter saving.
|
- Program parameter saving
|
||||||
* File name extension association.
|
- File extension association
|
||||||
* Supports texture image formats other than PNG.
|
- Texture images in formats other than PNG
|
||||||
* ...
|
- Launch at startup with persistent dynamic wallpaper
|
||||||
|
- ......
|
||||||
|
|
||||||
### Supported Spine Versions
|
### Supported Spine Versions
|
||||||
|
|
||||||
@@ -78,14 +81,14 @@ In the menu, go to "File" -> "Preferences..." -> "Language," select your desired
|
|||||||
|
|
||||||
The program is organized into a left-right layout:
|
The program is organized into a left-right layout:
|
||||||
|
|
||||||
* **Left Panel:** Functionality panel.
|
- **Left Panel:** Functionality panel.
|
||||||
* **Right Panel:** Preview display.
|
- **Right Panel:** Preview display.
|
||||||
|
|
||||||
The left panel includes three sub-panels:
|
The left panel includes three sub-panels:
|
||||||
|
|
||||||
* **Browse:** Preview the content of a specified folder without importing files into the program. This panel allows generating `.webp` previews for models or importing selected models.
|
- **Browse:** Preview the content of a specified folder without importing files into the program. This panel allows generating `.webp` previews for models or importing selected models.
|
||||||
* **Model:** Lists imported models for rendering. Parameters and rendering order can be adjusted here, along with other model-related functionalities.
|
- **Model:** Lists imported models for rendering. Parameters and rendering order can be adjusted here, along with other model-related functionalities.
|
||||||
* **Display:** Adjust parameters for the right-side preview display.
|
- **Display:** Adjust parameters for the right-side preview display.
|
||||||
|
|
||||||
Hover your mouse over buttons, labels, or input fields to see help text for most UI elements.
|
Hover your mouse over buttons, labels, or input fields to see help text for most UI elements.
|
||||||
|
|
||||||
@@ -101,10 +104,10 @@ The Model panel supports right-click menus, some shortcuts, and batch adjustment
|
|||||||
|
|
||||||
For preview display adjustments:
|
For preview display adjustments:
|
||||||
|
|
||||||
* **Left-click:** Select and drag models. Hold `Ctrl` for multi-selection, synchronized with the left-side list.
|
- **Left-click:** Select and drag models. Hold `Ctrl` for multi-selection, synchronized with the left-side list.
|
||||||
* **Right-click:** Drag the entire display.
|
- **Right-click:** Drag the entire display.
|
||||||
* **Scroll wheel:** Zoom in/out. Hold `Ctrl` to scale selected models.
|
- **Scroll wheel:** Zoom in/out. Hold `Ctrl` to scale selected models.
|
||||||
* **Render selected-only mode:** In this mode, the preview only shows selected models, and selection status can only be changed via the left-side list.
|
- **Render selected-only mode:** In this mode, the preview only shows selected models, and selection status can only be changed via the left-side list.
|
||||||
|
|
||||||
The buttons below the preview display allow time adjustments, serving as a simple playback control.
|
The buttons below the preview display allow time adjustments, serving as a simple playback control.
|
||||||
|
|
||||||
@@ -116,9 +119,17 @@ Use the right-click menu in the Model panel to export selected items.
|
|||||||
|
|
||||||
Key export parameters include:
|
Key export parameters include:
|
||||||
|
|
||||||
* **Output folder:** Optional. When not specified, output is saved to the respective model folder; otherwise, all output is saved to the provided folder.
|
- **Output folder:** Optional. When not specified, output is saved to the respective model folder; otherwise, all output is saved to the provided folder.
|
||||||
* **Export single:** By default, each model is exported independently. Selecting "Export single" renders all selected models in a single frame, producing a unified output.
|
- **Export single:** By default, each model is exported independently. Selecting "Export single" renders all selected models in a single frame, producing a unified output.
|
||||||
* **Auto resolution:** Ignores the preview resolution and viewport parameters, exporting output at the actual size of the content. For animations/videos, the output matches the size required for full visibility.
|
- **Auto resolution:** Ignores the preview resolution and viewport parameters, exporting output at the actual size of the content. For animations/videos, the output matches the size required for full visibility.
|
||||||
|
|
||||||
|
### Dynamic Wallpaper
|
||||||
|
|
||||||
|
Dynamic wallpaper is implemented through desktop projection, allowing the content of the current preview to be projected onto the desktop in real time.
|
||||||
|
|
||||||
|
You can enable or disable desktop projection from the program preferences or the right-click menu of the tray icon. After adjusting the model and display parameters, you can save the current configuration as a workspace file for convenient restoration later.
|
||||||
|
|
||||||
|
If you want the wallpaper to stay active after startup, you can enable auto-start in the preferences and specify which workspace file should be loaded when the program launches.
|
||||||
|
|
||||||
### More Information
|
### More Information
|
||||||
|
|
||||||
@@ -126,12 +137,12 @@ For detailed usage and documentation, see the [Wiki](https://github.com/ww-rm/Sp
|
|||||||
|
|
||||||
## Acknowledgements
|
## Acknowledgements
|
||||||
|
|
||||||
* [spine-runtimes](https://github.com/EsotericSoftware/spine-runtimes)
|
- [spine-runtimes](https://github.com/EsotericSoftware/spine-runtimes)
|
||||||
* [SFML.Net](https://github.com/SFML/SFML.Net)
|
- [SFML.Net](https://github.com/SFML/SFML.Net)
|
||||||
* [FFMpegCore](https://github.com/rosenbjerg/FFMpegCore)
|
- [FFMpegCore](https://github.com/rosenbjerg/FFMpegCore)
|
||||||
* [HandyControl](https://github.com/HandyOrg/HandyControl)
|
- [HandyControl](https://github.com/HandyOrg/HandyControl)
|
||||||
* [NLog](https://github.com/NLog/NLog)
|
- [NLog](https://github.com/NLog/NLog)
|
||||||
* [SkiaSharp](https://github.com/mono/SkiaSharp)
|
- [SkiaSharp](https://github.com/mono/SkiaSharp)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
15
README.md
15
README.md
@@ -6,9 +6,11 @@
|
|||||||
|
|
||||||
[中文](README.md) | [English](README.en.md)
|
[中文](README.md) | [English](README.en.md)
|
||||||
|
|
||||||
一个简单好用的 Spine 文件查看&导出程序, 支持中/英/日多语言界面.
|
Spine 文件查看&导出程序, 同时也是支持 Spine 的动态壁纸程序.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
<video src="https://github.com/user-attachments/assets/37b6b730-088a-4352-827a-c338127a16f0">
|
||||||
|
|
||||||
## 功能
|
## 功能
|
||||||
|
|
||||||
@@ -30,6 +32,7 @@
|
|||||||
- 支持程序参数保存
|
- 支持程序参数保存
|
||||||
- 支持文件后缀关联
|
- 支持文件后缀关联
|
||||||
- 支持非 png 格式的纹理图片格式
|
- 支持非 png 格式的纹理图片格式
|
||||||
|
- 支持开机自启常驻动态壁纸
|
||||||
- ......
|
- ......
|
||||||
|
|
||||||
### Spine 版本支持
|
### Spine 版本支持
|
||||||
@@ -117,6 +120,14 @@
|
|||||||
- 导出单个. 默认是每个模型独立导出, 即对模型列表进行批量操作, 如果选择仅导出单个, 那么被导出的所有模型将在同一个画面上被渲染, 输出产物只有一份.
|
- 导出单个. 默认是每个模型独立导出, 即对模型列表进行批量操作, 如果选择仅导出单个, 那么被导出的所有模型将在同一个画面上被渲染, 输出产物只有一份.
|
||||||
- 自动分辨率. 该模式会忽略预览画面的分辨率和视区参数, 导出产物的分辨率与被导出内容的实际大小一致, 如果是动图或者视频则会与完整显示动画的必需大小一致.
|
- 自动分辨率. 该模式会忽略预览画面的分辨率和视区参数, 导出产物的分辨率与被导出内容的实际大小一致, 如果是动图或者视频则会与完整显示动画的必需大小一致.
|
||||||
|
|
||||||
|
### 动态壁纸
|
||||||
|
|
||||||
|
动态壁纸通过桌面投影实现, 可以将当前预览画面上的内容实时投影至桌面.
|
||||||
|
|
||||||
|
在程序首选项或者托盘图标右键菜单中可以进行桌面投影的启用与否, 模型和画面参数调整完成后, 可以将当前参数保存为工作区文件, 方便之后恢复该配置.
|
||||||
|
|
||||||
|
如果希望开机自启常驻壁纸, 也可以在首选项中启用开机自启, 并且设置启动后需要加载的工作区文件.
|
||||||
|
|
||||||
### 更多
|
### 更多
|
||||||
|
|
||||||
更为详细的使用方法和说明见 [Wiki](https://github.com/ww-rm/SpineViewer/wiki), 有使用上的问题或者 BUG 可以提个 [Issue](https://github.com/ww-rm/SpineViewer/issues).
|
更为详细的使用方法和说明见 [Wiki](https://github.com/ww-rm/SpineViewer/wiki), 有使用上的问题或者 BUG 可以提个 [Issue](https://github.com/ww-rm/SpineViewer/issues).
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<TargetFramework>net8.0-windows</TargetFramework>
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
<Version>0.15.19</Version>
|
<Version>0.16.0</Version>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<TargetFramework>net8.0-windows</TargetFramework>
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
<Version>0.15.19</Version>
|
<Version>0.16.0</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using NLog;
|
using Microsoft.Win32;
|
||||||
|
using NLog;
|
||||||
using SpineViewer.Natives;
|
using SpineViewer.Natives;
|
||||||
|
using SpineViewer.ViewModels.MainWindow;
|
||||||
using SpineViewer.Views;
|
using SpineViewer.Views;
|
||||||
using System.Collections.Frozen;
|
using System.Collections.Frozen;
|
||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
@@ -18,15 +20,28 @@ namespace SpineViewer
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class App : Application
|
public partial class App : Application
|
||||||
{
|
{
|
||||||
|
#if DEBUG
|
||||||
|
public const string AppName = "SpineViewer_D";
|
||||||
|
public const string ProgId = "SpineViewer_D.skel";
|
||||||
|
#else
|
||||||
|
public const string AppName = "SpineViewer";
|
||||||
public const string ProgId = "SpineViewer.skel";
|
public const string ProgId = "SpineViewer.skel";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public const string AutoRunFlag = "--autorun";
|
||||||
|
private const string MutexName = "__SpineViewerInstance__";
|
||||||
|
private const string PipeName = "__SpineViewerPipe__";
|
||||||
|
|
||||||
public static readonly string ProcessPath = Environment.ProcessPath;
|
public static readonly string ProcessPath = Environment.ProcessPath;
|
||||||
public static readonly string ProcessDirectory = Path.GetDirectoryName(Environment.ProcessPath);
|
public static readonly string ProcessDirectory = Path.GetDirectoryName(Environment.ProcessPath);
|
||||||
public static readonly string ProcessName = Process.GetCurrentProcess().ProcessName;
|
public static readonly string ProcessName = Process.GetCurrentProcess().ProcessName;
|
||||||
public static readonly string Version = Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
|
public static readonly string Version = Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
|
||||||
|
|
||||||
private const string MutexName = "SpineViewerInstance";
|
private static readonly string AutoRunCommand = $"\"{ProcessPath}\" {AutoRunFlag}";
|
||||||
private const string PipeName = "SpineViewerPipe";
|
|
||||||
|
private static readonly string SkelFileDescription = $"SpineViewer File";
|
||||||
|
private static readonly string SkelIconFilePath = Path.Combine(ProcessDirectory, "Resources\\Images\\skel.ico");
|
||||||
|
private static readonly string ShellOpenCommand = $"\"{ProcessPath}\" \"%1\"";
|
||||||
|
|
||||||
private static readonly Logger _logger;
|
private static readonly Logger _logger;
|
||||||
private static readonly Mutex _instanceMutex;
|
private static readonly Mutex _instanceMutex;
|
||||||
@@ -87,7 +102,7 @@ namespace SpineViewer
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 2. 遍历同名进程
|
// 遍历同名进程
|
||||||
var processes = Process.GetProcessesByName(ProcessName);
|
var processes = Process.GetProcessesByName(ProcessName);
|
||||||
foreach (var p in processes)
|
foreach (var p in processes)
|
||||||
{
|
{
|
||||||
@@ -171,7 +186,11 @@ namespace SpineViewer
|
|||||||
|
|
||||||
if (args.Count > 0)
|
if (args.Count > 0)
|
||||||
{
|
{
|
||||||
Current.Dispatcher.Invoke(() => ((MainWindow)Current.MainWindow).OpenFiles(args));
|
Current.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
var vm = (MainWindowViewModel)((MainWindow)Current.MainWindow).DataContext;
|
||||||
|
vm.SpineObjectListViewModel.AddSpineObjectFromFileList(args);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,7 +205,6 @@ namespace SpineViewer
|
|||||||
base.OnStartup(e);
|
base.OnStartup(e);
|
||||||
var uiCulture = CultureInfo.CurrentUICulture.Name.ToLowerInvariant();
|
var uiCulture = CultureInfo.CurrentUICulture.Name.ToLowerInvariant();
|
||||||
_logger.Info("Current UI Culture: {0}", uiCulture);
|
_logger.Info("Current UI Culture: {0}", uiCulture);
|
||||||
|
|
||||||
if (uiCulture.StartsWith("zh")) { } // 默认就是中文, 无需操作
|
if (uiCulture.StartsWith("zh")) { } // 默认就是中文, 无需操作
|
||||||
else if (uiCulture.StartsWith("ja")) Language = AppLanguage.JA;
|
else if (uiCulture.StartsWith("ja")) Language = AppLanguage.JA;
|
||||||
else Language = AppLanguage.EN;
|
else Language = AppLanguage.EN;
|
||||||
@@ -199,6 +217,116 @@ namespace SpineViewer
|
|||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool AutoRun
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run"))
|
||||||
|
{
|
||||||
|
var command = key?.GetValue(AppName) as string;
|
||||||
|
return string.Equals(command, AutoRunCommand, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error("Failed to query autorun registry key, {0}", ex.Message);
|
||||||
|
_logger.Trace(ex.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
// 写入自启命令
|
||||||
|
using (var key = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run"))
|
||||||
|
{
|
||||||
|
key?.SetValue(AppName, AutoRunCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 删除自启命令
|
||||||
|
using (var key = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run"))
|
||||||
|
{
|
||||||
|
key?.DeleteValue(AppName, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error("Failed to set autorun registry key, {0}", ex.Message);
|
||||||
|
_logger.Trace(ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AssociateFileSuffix
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 检查 .skel 的 ProgID
|
||||||
|
using (var key = Registry.CurrentUser.OpenSubKey(@"Software\Classes\.skel"))
|
||||||
|
{
|
||||||
|
var progIdValue = key?.GetValue("") as string;
|
||||||
|
if (!string.Equals(progIdValue, App.ProgId, StringComparison.OrdinalIgnoreCase))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查 command 指令是否相同
|
||||||
|
using (var key = Registry.CurrentUser.OpenSubKey($@"Software\Classes\{App.ProgId}\shell\open\command"))
|
||||||
|
{
|
||||||
|
var command = key?.GetValue("") as string;
|
||||||
|
if (string.IsNullOrWhiteSpace(command))
|
||||||
|
return false;
|
||||||
|
return command == ShellOpenCommand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
// 文件关联
|
||||||
|
using (var key = Registry.CurrentUser.CreateSubKey(@"Software\Classes\.skel"))
|
||||||
|
{
|
||||||
|
key?.SetValue("", App.ProgId);
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var key = Registry.CurrentUser.CreateSubKey($@"Software\Classes\{App.ProgId}"))
|
||||||
|
{
|
||||||
|
key?.SetValue("", SkelFileDescription);
|
||||||
|
using (var iconKey = key?.CreateSubKey("DefaultIcon"))
|
||||||
|
{
|
||||||
|
iconKey?.SetValue("", $"\"{SkelIconFilePath}\"");
|
||||||
|
}
|
||||||
|
using (var shellKey = key?.CreateSubKey(@"shell\open\command"))
|
||||||
|
{
|
||||||
|
shellKey?.SetValue("", ShellOpenCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 删除关联
|
||||||
|
Registry.CurrentUser.DeleteSubKeyTree(@"Software\Classes\.skel", false);
|
||||||
|
Registry.CurrentUser.DeleteSubKeyTree($@"Software\Classes\{App.ProgId}", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shell32.NotifyAssociationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 程序语言
|
/// 程序语言
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -221,7 +349,6 @@ namespace SpineViewer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private AppLanguage _language = AppLanguage.ZH;
|
private AppLanguage _language = AppLanguage.ZH;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum AppLanguage
|
public enum AppLanguage
|
||||||
|
|||||||
@@ -19,9 +19,16 @@ namespace SpineViewer.Models
|
|||||||
public WindowState WindowState { get; set; }
|
public WindowState WindowState { get; set; }
|
||||||
|
|
||||||
public double RootGridCol0Width { get; set; }
|
public double RootGridCol0Width { get; set; }
|
||||||
|
public double RootGridCol2Width { get; set; }
|
||||||
|
|
||||||
public double ModelListRow0Height { get; set; }
|
public double ModelListRow0Height { get; set; }
|
||||||
|
public double ModelListRow2Height { get; set; }
|
||||||
|
|
||||||
public double ExplorerGridRow0Height { get; set; }
|
public double ExplorerGridRow0Height { get; set; }
|
||||||
|
public double ExplorerGridRow2Height { get; set; }
|
||||||
|
|
||||||
public double RightPanelGridRow0Height { get; set; }
|
public double RightPanelGridRow0Height { get; set; }
|
||||||
|
public double RightPanelGridRow2Height { get; set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Spine.SpineWrappers;
|
using Spine.SpineWrappers;
|
||||||
|
using SpineViewer.Services;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -73,17 +75,34 @@ namespace SpineViewer.Models
|
|||||||
|
|
||||||
#region 程序选项
|
#region 程序选项
|
||||||
|
|
||||||
|
public RelayCommand Cmd_SelectAutoRunWorkspaceConfigPath => _cmd_SelectAutoRunWorkspaceConfigPath ??= new(() =>
|
||||||
|
{
|
||||||
|
if (!DialogService.ShowOpenJsonDialog(out var fileName))
|
||||||
|
return;
|
||||||
|
AutoRunWorkspaceConfigPath = fileName;
|
||||||
|
});
|
||||||
|
private RelayCommand? _cmd_SelectAutoRunWorkspaceConfigPath;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool _wallpaperView;
|
private AppLanguage _appLanguage;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool _renderSelectedOnly;
|
private bool _renderSelectedOnly;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private bool _associateFileSuffix;
|
private bool _wallpaperView;
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private AppLanguage _appLanguage;
|
private bool? _closeToTray = null;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _autoRun;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private string _autoRunWorkspaceConfigPath;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _associateFileSuffix;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -269,6 +269,12 @@ namespace SpineViewer.Models
|
|||||||
entry = _spineObject.AnimationState.SetAnimation(index, name, true);
|
entry = _spineObject.AnimationState.SetAnimation(index, name, true);
|
||||||
entry.TimeScale = lastTimeScale;
|
entry.TimeScale = lastTimeScale;
|
||||||
entry.Alpha = lastAlpha;
|
entry.Alpha = lastAlpha;
|
||||||
|
|
||||||
|
// XXX(#105): 部分 3.4.02 版本模型在设置动画后出现附件残留, 因此强制进行一次 Setup
|
||||||
|
if (_spineObject.Version == SpineVersion.V34)
|
||||||
|
{
|
||||||
|
_spineObject.Skeleton.SetSlotsToSetupPose();
|
||||||
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ namespace SpineViewer.Resources
|
|||||||
public static string Str_TooManyItemsToAddQuest => Get<string>("Str_TooManyItemsToAddQuest");
|
public static string Str_TooManyItemsToAddQuest => Get<string>("Str_TooManyItemsToAddQuest");
|
||||||
public static string Str_RemoveItemsQuest => Get<string>("Str_RemoveItemsQuest");
|
public static string Str_RemoveItemsQuest => Get<string>("Str_RemoveItemsQuest");
|
||||||
public static string Str_DeleteItemsQuest => Get<string>("Str_DeleteItemsQuest");
|
public static string Str_DeleteItemsQuest => Get<string>("Str_DeleteItemsQuest");
|
||||||
|
public static string Str_CloseToTrayQuest => Get<string>("Str_CloseToTrayQuest");
|
||||||
|
|
||||||
public static string Str_FrameExporterTitle => Get<string>("Str_FrameExporterTitle");
|
public static string Str_FrameExporterTitle => Get<string>("Str_FrameExporterTitle");
|
||||||
public static string Str_FrameSequenceExporterTitle => Get<string>("Str_FrameSequenceExporterTitle");
|
public static string Str_FrameSequenceExporterTitle => Get<string>("Str_FrameSequenceExporterTitle");
|
||||||
|
|||||||
@@ -149,6 +149,7 @@
|
|||||||
<s:String x:Key="Str_TooManyItemsToAddQuest">{0} items total, add all at once?</s:String>
|
<s:String x:Key="Str_TooManyItemsToAddQuest">{0} items total, add all at once?</s:String>
|
||||||
<s:String x:Key="Str_RemoveItemsQuest">Remove {0} items?</s:String>
|
<s:String x:Key="Str_RemoveItemsQuest">Remove {0} items?</s:String>
|
||||||
<s:String x:Key="Str_DeleteItemsQuest">Delete {0} items?</s:String>
|
<s:String x:Key="Str_DeleteItemsQuest">Delete {0} items?</s:String>
|
||||||
|
<s:String x:Key="Str_CloseToTrayQuest" xml:space="preserve">You clicked the close button. Do you want to minimize to the tray icon instead of closing the application directly?
(If you choose Yes, the window will be minimized to the tray and can be restored by double-clicking the icon. You can change this option later in the application preferences.)</s:String>
|
||||||
|
|
||||||
<!-- 导出对话框弹窗文本 -->
|
<!-- 导出对话框弹窗文本 -->
|
||||||
<s:String x:Key="Str_FrameExporterTitle">Export Single Frame</s:String>
|
<s:String x:Key="Str_FrameExporterTitle">Export Single Frame</s:String>
|
||||||
@@ -237,7 +238,11 @@
|
|||||||
<s:String x:Key="Str_RendererPreference">Preview Options</s:String>
|
<s:String x:Key="Str_RendererPreference">Preview Options</s:String>
|
||||||
|
|
||||||
<s:String x:Key="Str_AppPreference">Application Options</s:String>
|
<s:String x:Key="Str_AppPreference">Application Options</s:String>
|
||||||
<s:String x:Key="Str_AssociateFileSuffix">Associate File Extension</s:String>
|
|
||||||
<s:String x:Key="Str_Language">Language</s:String>
|
<s:String x:Key="Str_Language">Language</s:String>
|
||||||
|
<s:String x:Key="Str_CloseToTray">Minimize to tray when closing</s:String>
|
||||||
|
<s:String x:Key="Str_AutoRun">Auto Start</s:String>
|
||||||
|
<s:String x:Key="Str_AutoRunWorkspaceConfigPath">Auto-load Workspace File on Startup</s:String>
|
||||||
|
<s:String x:Key="Str_AutoRunWorkspaceConfigPathTooltip">Specifies the workspace configuration file to be automatically loaded when the program starts with Windows startup. This takes effect only if auto-startup is enabled.</s:String>
|
||||||
|
<s:String x:Key="Str_AssociateFileSuffix">Associate File Extension</s:String>
|
||||||
|
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|||||||
@@ -149,6 +149,7 @@
|
|||||||
<s:String x:Key="Str_TooManyItemsToAddQuest">全{0}件、一度に追加しますか?</s:String>
|
<s:String x:Key="Str_TooManyItemsToAddQuest">全{0}件、一度に追加しますか?</s:String>
|
||||||
<s:String x:Key="Str_RemoveItemsQuest">{0}件を削除してもよろしいですか?</s:String>
|
<s:String x:Key="Str_RemoveItemsQuest">{0}件を削除してもよろしいですか?</s:String>
|
||||||
<s:String x:Key="Str_DeleteItemsQuest">{0}件を削除してもよろしいですか?</s:String>
|
<s:String x:Key="Str_DeleteItemsQuest">{0}件を削除してもよろしいですか?</s:String>
|
||||||
|
<s:String x:Key="Str_CloseToTrayQuest" xml:space="preserve">閉じるボタンをクリックしました。アプリケーションを直接終了するのではなく、通知領域のアイコンに最小化しますか?
(「はい」を選択すると、ウィンドウは通知領域に最小化され、アイコンをダブルクリックすると復元できます。この設定は後でアプリケーションの環境設定から変更できます。)</s:String>
|
||||||
|
|
||||||
<!-- 导出对话框弹窗文本 -->
|
<!-- 导出对话框弹窗文本 -->
|
||||||
<s:String x:Key="Str_FrameExporterTitle">単一フレームをエクスポート</s:String>
|
<s:String x:Key="Str_FrameExporterTitle">単一フレームをエクスポート</s:String>
|
||||||
@@ -237,8 +238,12 @@
|
|||||||
<s:String x:Key="Str_RendererPreference">プレビュー画面オプション</s:String>
|
<s:String x:Key="Str_RendererPreference">プレビュー画面オプション</s:String>
|
||||||
|
|
||||||
<s:String x:Key="Str_AppPreference">アプリケーションプション</s:String>
|
<s:String x:Key="Str_AppPreference">アプリケーションプション</s:String>
|
||||||
<s:String x:Key="Str_AssociateFileSuffix">ファイル拡張子を関連付ける</s:String>
|
|
||||||
<s:String x:Key="Str_Language">言語</s:String>
|
<s:String x:Key="Str_Language">言語</s:String>
|
||||||
|
<s:String x:Key="Str_CloseToTray">閉じるときにトレイに最小化する</s:String>
|
||||||
|
<s:String x:Key="Str_AutoRun">自動起動</s:String>
|
||||||
|
<s:String x:Key="Str_AutoRunWorkspaceConfigPath">起動時にワークスペースファイルを自動読み込み</s:String>
|
||||||
|
<s:String x:Key="Str_AutoRunWorkspaceConfigPathTooltip">プログラムが Windows 起動と同時に自動起動した場合に、自動的に読み込むワークスペース設定ファイルを指定します。自動起動が有効な場合にのみ適用されます。</s:String>
|
||||||
|
<s:String x:Key="Str_AssociateFileSuffix">ファイル拡張子を関連付ける</s:String>
|
||||||
|
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|
||||||
|
|||||||
@@ -149,6 +149,7 @@
|
|||||||
<s:String x:Key="Str_TooManyItemsToAddQuest">共 {0} 项,是否一次性添加?</s:String>
|
<s:String x:Key="Str_TooManyItemsToAddQuest">共 {0} 项,是否一次性添加?</s:String>
|
||||||
<s:String x:Key="Str_RemoveItemsQuest">确定移除 {0} 项?</s:String>
|
<s:String x:Key="Str_RemoveItemsQuest">确定移除 {0} 项?</s:String>
|
||||||
<s:String x:Key="Str_DeleteItemsQuest">确定删除 {0} 项?</s:String>
|
<s:String x:Key="Str_DeleteItemsQuest">确定删除 {0} 项?</s:String>
|
||||||
|
<s:String x:Key="Str_CloseToTrayQuest" xml:space="preserve">您点击了关闭按钮,是否需要最小化至托盘图标而不是直接关闭?
(选是则最小化至托盘图标,可以通过双击图标还原窗口,以后也可以在程序首选项中重新设置该选项)</s:String>
|
||||||
|
|
||||||
<!-- 导出对话框弹窗文本 -->
|
<!-- 导出对话框弹窗文本 -->
|
||||||
<s:String x:Key="Str_FrameExporterTitle">导出单帧</s:String>
|
<s:String x:Key="Str_FrameExporterTitle">导出单帧</s:String>
|
||||||
@@ -237,7 +238,11 @@
|
|||||||
<s:String x:Key="Str_RendererPreference">预览画面选项</s:String>
|
<s:String x:Key="Str_RendererPreference">预览画面选项</s:String>
|
||||||
|
|
||||||
<s:String x:Key="Str_AppPreference">应用程序选项</s:String>
|
<s:String x:Key="Str_AppPreference">应用程序选项</s:String>
|
||||||
<s:String x:Key="Str_AssociateFileSuffix">关联文件后缀</s:String>
|
|
||||||
<s:String x:Key="Str_Language">语言</s:String>
|
<s:String x:Key="Str_Language">语言</s:String>
|
||||||
|
<s:String x:Key="Str_CloseToTray">关闭时最小化至托盘图标</s:String>
|
||||||
|
<s:String x:Key="Str_AutoRun">开机自启</s:String>
|
||||||
|
<s:String x:Key="Str_AutoRunWorkspaceConfigPath">自启动加载工作区文件</s:String>
|
||||||
|
<s:String x:Key="Str_AutoRunWorkspaceConfigPathTooltip">设置程序开机自启后自动加载的工作区配置文件,仅在启用开机自启时生效</s:String>
|
||||||
|
<s:String x:Key="Str_AssociateFileSuffix">关联文件后缀</s:String>
|
||||||
|
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
@@ -28,10 +28,16 @@ namespace SpineViewer.Services
|
|||||||
MessageBox.Show(text, title, MessageBoxButton.OK, MessageBoxImage.Error);
|
MessageBox.Show(text, title, MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Quest(string text, string? title = null)
|
public static bool OKCancel(string text, string? title = null)
|
||||||
{
|
{
|
||||||
title ??= AppResource.Str_QuestPopup;
|
title ??= AppResource.Str_QuestPopup;
|
||||||
return MessageBox.Show(text, title, MessageBoxButton.OKCancel, MessageBoxImage.Question) == MessageBoxResult.OK;
|
return MessageBox.Show(text, title, MessageBoxButton.OKCancel, MessageBoxImage.Question) == MessageBoxResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool YesNo(string text, string? title = null)
|
||||||
|
{
|
||||||
|
title ??= AppResource.Str_QuestPopup;
|
||||||
|
return MessageBox.Show(text, title, MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<TargetFramework>net8.0-windows</TargetFramework>
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
<Version>0.15.19</Version>
|
<Version>0.16.0</Version>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<UseWPF>true</UseWPF>
|
<UseWPF>true</UseWPF>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
private void DeletePreview_Execute(IList? args)
|
private void DeletePreview_Execute(IList? args)
|
||||||
{
|
{
|
||||||
if (args is null || args.Count <= 0) return;
|
if (args is null || args.Count <= 0) return;
|
||||||
if (!MessagePopupService.Quest(string.Format(AppResource.Str_DeleteItemsQuest, args.Count))) return;
|
if (!MessagePopupService.OKCancel(string.Format(AppResource.Str_DeleteItemsQuest, args.Count))) return;
|
||||||
|
|
||||||
if (args.Count <= 10)
|
if (args.Count <= 10)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,6 +29,26 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
|
|
||||||
public string Title => $"SpineViewer - v{App.Version}";
|
public string Title => $"SpineViewer - v{App.Version}";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 指示是否通过托盘图标进行退出
|
||||||
|
/// </summary>
|
||||||
|
public bool IsShuttingDownFromTray => _isShuttingDownFromTray;
|
||||||
|
private bool _isShuttingDownFromTray;
|
||||||
|
|
||||||
|
public bool? CloseToTray
|
||||||
|
{
|
||||||
|
get => _closeToTray;
|
||||||
|
set => SetProperty(ref _closeToTray, value);
|
||||||
|
}
|
||||||
|
private bool? _closeToTray = null;
|
||||||
|
|
||||||
|
public string AutoRunWorkspaceConfigPath
|
||||||
|
{
|
||||||
|
get => _autoRunWorkspaceConfigPath;
|
||||||
|
set => SetProperty(ref _autoRunWorkspaceConfigPath, value);
|
||||||
|
}
|
||||||
|
private string _autoRunWorkspaceConfigPath;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SFML 渲染对象
|
/// SFML 渲染对象
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -50,6 +70,9 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
public ObservableCollectionWithLock<SpineObjectModel> SpineObjects => _spineObjectModels;
|
public ObservableCollectionWithLock<SpineObjectModel> SpineObjects => _spineObjectModels;
|
||||||
private readonly ObservableCollectionWithLock<SpineObjectModel> _spineObjectModels = [];
|
private readonly ObservableCollectionWithLock<SpineObjectModel> _spineObjectModels = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 首选项 ViewModel
|
||||||
|
/// </summary>
|
||||||
public PreferenceViewModel PreferenceViewModel => _preferenceViewModel;
|
public PreferenceViewModel PreferenceViewModel => _preferenceViewModel;
|
||||||
private readonly PreferenceViewModel _preferenceViewModel;
|
private readonly PreferenceViewModel _preferenceViewModel;
|
||||||
|
|
||||||
@@ -84,8 +107,13 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
});
|
});
|
||||||
private RelayCommand _cmd_SwitchWallpaperView;
|
private RelayCommand _cmd_SwitchWallpaperView;
|
||||||
|
|
||||||
public RelayCommand Cmd_Exit => _cmd_Exit ??= new(App.Current.Shutdown);
|
public RelayCommand Cmd_ExitFromTray => _cmd_ExitFromTray ??= new(() =>
|
||||||
private RelayCommand? _cmd_Exit;
|
{
|
||||||
|
_isShuttingDownFromTray = true;
|
||||||
|
OnPropertyChanged(nameof(IsShuttingDownFromTray));
|
||||||
|
App.Current.Shutdown();
|
||||||
|
});
|
||||||
|
private RelayCommand? _cmd_ExitFromTray;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 打开工作区
|
/// 打开工作区
|
||||||
|
|||||||
@@ -26,10 +26,6 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly string PreferenceFilePath = Path.Combine(Path.GetDirectoryName(Environment.ProcessPath), "preference.json");
|
public static readonly string PreferenceFilePath = Path.Combine(Path.GetDirectoryName(Environment.ProcessPath), "preference.json");
|
||||||
|
|
||||||
private static readonly string SkelFileDescription = "SpineViewer File";
|
|
||||||
private static readonly string SkelIconFilePath = Path.Combine(App.ProcessDirectory, "Resources\\Images\\skel.ico");
|
|
||||||
private static readonly string ShellOpenCommand = $"\"{App.ProcessPath}\" \"%1\"";
|
|
||||||
|
|
||||||
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
|
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
private readonly MainWindowViewModel _vmMain;
|
private readonly MainWindowViewModel _vmMain;
|
||||||
@@ -111,10 +107,13 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
DebugPoints = DebugPoints,
|
DebugPoints = DebugPoints,
|
||||||
DebugClippings = DebugClippings,
|
DebugClippings = DebugClippings,
|
||||||
|
|
||||||
WallpaperView = WallpaperView,
|
|
||||||
RenderSelectedOnly = RenderSelectedOnly,
|
|
||||||
AssociateFileSuffix = AssociateFileSuffix,
|
|
||||||
AppLanguage = AppLanguage,
|
AppLanguage = AppLanguage,
|
||||||
|
RenderSelectedOnly = RenderSelectedOnly,
|
||||||
|
WallpaperView = WallpaperView,
|
||||||
|
CloseToTray = CloseToTray,
|
||||||
|
AutoRun = AutoRun,
|
||||||
|
AutoRunWorkspaceConfigPath = AutoRunWorkspaceConfigPath,
|
||||||
|
AssociateFileSuffix = AssociateFileSuffix,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
@@ -137,10 +136,13 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
DebugPoints = value.DebugPoints;
|
DebugPoints = value.DebugPoints;
|
||||||
DebugClippings = value.DebugClippings;
|
DebugClippings = value.DebugClippings;
|
||||||
|
|
||||||
WallpaperView = value.WallpaperView;
|
|
||||||
RenderSelectedOnly = value.RenderSelectedOnly;
|
|
||||||
AssociateFileSuffix = value.AssociateFileSuffix;
|
|
||||||
AppLanguage = value.AppLanguage;
|
AppLanguage = value.AppLanguage;
|
||||||
|
RenderSelectedOnly = value.RenderSelectedOnly;
|
||||||
|
WallpaperView = value.WallpaperView;
|
||||||
|
CloseToTray = value.CloseToTray;
|
||||||
|
AutoRun = value.AutoRun;
|
||||||
|
AutoRunWorkspaceConfigPath = value.AutoRunWorkspaceConfigPath;
|
||||||
|
AssociateFileSuffix = value.AssociateFileSuffix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,94 +248,46 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
|
|
||||||
public static ImmutableArray<AppLanguage> AppLanguageOptions { get; } = Enum.GetValues<AppLanguage>().ToImmutableArray();
|
public static ImmutableArray<AppLanguage> AppLanguageOptions { get; } = Enum.GetValues<AppLanguage>().ToImmutableArray();
|
||||||
|
|
||||||
public bool AutoRun
|
public AppLanguage AppLanguage
|
||||||
{
|
{
|
||||||
get => throw new NotImplementedException();
|
get => ((App)App.Current).Language;
|
||||||
set => throw new NotImplementedException();
|
set => SetProperty(((App)App.Current).Language, value, v => ((App)App.Current).Language = v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool WallpaperView
|
|
||||||
{
|
|
||||||
get => _wallpaperView;
|
|
||||||
set => SetProperty(ref _wallpaperView, value);
|
|
||||||
}
|
|
||||||
private bool _wallpaperView; // UI 变化通过 PropertyChanged 事件交由 View 层处理
|
|
||||||
|
|
||||||
public bool RenderSelectedOnly
|
public bool RenderSelectedOnly
|
||||||
{
|
{
|
||||||
get => _vmMain.SFMLRendererViewModel.RenderSelectedOnly;
|
get => _vmMain.SFMLRendererViewModel.RenderSelectedOnly;
|
||||||
set => SetProperty(_vmMain.SFMLRendererViewModel.RenderSelectedOnly, value, v => _vmMain.SFMLRendererViewModel.RenderSelectedOnly = v);
|
set => SetProperty(_vmMain.SFMLRendererViewModel.RenderSelectedOnly, value, v => _vmMain.SFMLRendererViewModel.RenderSelectedOnly = v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AssociateFileSuffix
|
public bool WallpaperView
|
||||||
{
|
{
|
||||||
get
|
get => _vmMain.SFMLRendererViewModel.WallpaperView;
|
||||||
{
|
set => SetProperty(_vmMain.SFMLRendererViewModel.WallpaperView, value, v => _vmMain.SFMLRendererViewModel.WallpaperView = v);
|
||||||
try
|
|
||||||
{
|
|
||||||
// 检查 .skel 的 ProgID
|
|
||||||
using (var key = Registry.CurrentUser.OpenSubKey(@"Software\Classes\.skel"))
|
|
||||||
{
|
|
||||||
var progIdValue = key?.GetValue("") as string;
|
|
||||||
if (!string.Equals(progIdValue, App.ProgId, StringComparison.OrdinalIgnoreCase))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查 command 指令是否相同
|
|
||||||
using (var key = Registry.CurrentUser.OpenSubKey($@"Software\Classes\{App.ProgId}\shell\open\command"))
|
|
||||||
{
|
|
||||||
var command = key?.GetValue("") as string;
|
|
||||||
if (string.IsNullOrWhiteSpace(command))
|
|
||||||
return false;
|
|
||||||
return command == ShellOpenCommand;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(AssociateFileSuffix, value, v =>
|
|
||||||
{
|
|
||||||
if (v)
|
|
||||||
{
|
|
||||||
// 文件关联
|
|
||||||
using (var key = Registry.CurrentUser.CreateSubKey(@"Software\Classes\.skel"))
|
|
||||||
{
|
|
||||||
key?.SetValue("", App.ProgId);
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var key = Registry.CurrentUser.CreateSubKey($@"Software\Classes\{App.ProgId}"))
|
|
||||||
{
|
|
||||||
key?.SetValue("", SkelFileDescription);
|
|
||||||
using (var iconKey = key?.CreateSubKey("DefaultIcon"))
|
|
||||||
{
|
|
||||||
iconKey?.SetValue("", $"\"{SkelIconFilePath}\"");
|
|
||||||
}
|
|
||||||
using (var shellKey = key?.CreateSubKey(@"shell\open\command"))
|
|
||||||
{
|
|
||||||
shellKey?.SetValue("", ShellOpenCommand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 删除关联
|
|
||||||
Registry.CurrentUser.DeleteSubKeyTree(@"Software\Classes\.skel", false);
|
|
||||||
Registry.CurrentUser.DeleteSubKeyTree($@"Software\Classes\{App.ProgId}", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Shell32.NotifyAssociationChanged();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AppLanguage AppLanguage
|
public bool? CloseToTray
|
||||||
{
|
{
|
||||||
get => ((App)App.Current).Language;
|
get => _vmMain.CloseToTray;
|
||||||
set => SetProperty(((App)App.Current).Language, value, v => ((App)App.Current).Language = v);
|
set => SetProperty(_vmMain.CloseToTray, value, v => _vmMain.CloseToTray = v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AutoRun
|
||||||
|
{
|
||||||
|
get => ((App)App.Current).AutoRun;
|
||||||
|
set => SetProperty(((App)App.Current).AutoRun, value, v => ((App)App.Current).AutoRun = v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string AutoRunWorkspaceConfigPath
|
||||||
|
{
|
||||||
|
get => _vmMain.AutoRunWorkspaceConfigPath;
|
||||||
|
set => SetProperty(_vmMain.AutoRunWorkspaceConfigPath, value, v => _vmMain.AutoRunWorkspaceConfigPath = v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AssociateFileSuffix
|
||||||
|
{
|
||||||
|
get => ((App)App.Current).AssociateFileSuffix;
|
||||||
|
set => SetProperty(((App)App.Current).AssociateFileSuffix, value, v => ((App)App.Current).AssociateFileSuffix = v);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@@ -240,6 +240,13 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
}
|
}
|
||||||
private Stretch _backgroundImageMode = Stretch.Uniform;
|
private Stretch _backgroundImageMode = Stretch.Uniform;
|
||||||
|
|
||||||
|
public bool WallpaperView
|
||||||
|
{
|
||||||
|
get => _wallpaperView;
|
||||||
|
set => SetProperty(ref _wallpaperView, value);
|
||||||
|
}
|
||||||
|
private bool _wallpaperView;
|
||||||
|
|
||||||
public bool RenderSelectedOnly
|
public bool RenderSelectedOnly
|
||||||
{
|
{
|
||||||
get => _renderSelectedOnly;
|
get => _renderSelectedOnly;
|
||||||
@@ -465,10 +472,13 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
using var v = _renderer.GetView();
|
using var v = _renderer.GetView();
|
||||||
_wallpaperRenderer.SetView(v);
|
|
||||||
|
|
||||||
_renderer.Clear(_backgroundColor);
|
_renderer.Clear(_backgroundColor);
|
||||||
_wallpaperRenderer.Clear(_backgroundColor);
|
|
||||||
|
if (_wallpaperView)
|
||||||
|
{
|
||||||
|
_wallpaperRenderer.SetView(v);
|
||||||
|
_wallpaperRenderer.Clear(_backgroundColor);
|
||||||
|
}
|
||||||
|
|
||||||
// 渲染背景
|
// 渲染背景
|
||||||
lock (_bgLock)
|
lock (_bgLock)
|
||||||
@@ -499,7 +509,11 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
bg.Position = view.Center;
|
bg.Position = view.Center;
|
||||||
bg.Rotation = view.Rotation;
|
bg.Rotation = view.Rotation;
|
||||||
_renderer.Draw(bg);
|
_renderer.Draw(bg);
|
||||||
_wallpaperRenderer.Draw(bg);
|
|
||||||
|
if (_wallpaperView)
|
||||||
|
{
|
||||||
|
_wallpaperRenderer.Draw(bg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,12 +553,20 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
sp.EnableDebug = true;
|
sp.EnableDebug = true;
|
||||||
_renderer.Draw(sp);
|
_renderer.Draw(sp);
|
||||||
sp.EnableDebug = false;
|
sp.EnableDebug = false;
|
||||||
_wallpaperRenderer.Draw(sp);
|
|
||||||
|
if (_wallpaperView)
|
||||||
|
{
|
||||||
|
_wallpaperRenderer.Draw(sp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_renderer.Display();
|
_renderer.Display();
|
||||||
_wallpaperRenderer.Display();
|
|
||||||
|
if (_wallpaperView)
|
||||||
|
{
|
||||||
|
_wallpaperRenderer.Display();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
|
|
||||||
if (args.Count > 1)
|
if (args.Count > 1)
|
||||||
{
|
{
|
||||||
if (!MessagePopupService.Quest(string.Format(AppResource.Str_RemoveItemsQuest, args.Count)))
|
if (!MessagePopupService.OKCancel(string.Format(AppResource.Str_RemoveItemsQuest, args.Count)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +159,7 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
{
|
{
|
||||||
if (!RemoveAllSpineObject_CanExecute(args)) return;
|
if (!RemoveAllSpineObject_CanExecute(args)) return;
|
||||||
|
|
||||||
if (!MessagePopupService.Quest(string.Format(AppResource.Str_RemoveItemsQuest, args.Count)))
|
if (!MessagePopupService.OKCancel(string.Format(AppResource.Str_RemoveItemsQuest, args.Count)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lock (_spineObjectModels.Lock)
|
lock (_spineObjectModels.Lock)
|
||||||
@@ -469,7 +469,7 @@ namespace SpineViewer.ViewModels.MainWindow
|
|||||||
{
|
{
|
||||||
if (validPaths.Count > 100)
|
if (validPaths.Count > 100)
|
||||||
{
|
{
|
||||||
if (!MessagePopupService.Quest(string.Format(AppResource.Str_TooManyItemsToAddQuest, validPaths.Count)))
|
if (!MessagePopupService.OKCancel(string.Format(AppResource.Str_TooManyItemsToAddQuest, validPaths.Count)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ProgressService.RunAsync((pr, ct) => AddSpineObjectsTask(
|
ProgressService.RunAsync((pr, ct) => AddSpineObjectsTask(
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace SpineViewer.ViewModels
|
|||||||
private void Cancel_Execute()
|
private void Cancel_Execute()
|
||||||
{
|
{
|
||||||
if (!Cancel_CanExecute()) return;
|
if (!Cancel_CanExecute()) return;
|
||||||
if (!MessagePopupService.Quest(AppResource.Str_CancelQuest)) return;
|
if (!MessagePopupService.OKCancel(AppResource.Str_CancelQuest)) return;
|
||||||
_cts.Cancel();
|
_cts.Cancel();
|
||||||
Cmd_Cancel.NotifyCanExecuteChanged();
|
Cmd_Cancel.NotifyCanExecuteChanged();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,73 +21,120 @@
|
|||||||
<Button Width="120" Content="{DynamicResource Str_CopyDiagnosticsInfo}" Command="{Binding Cmd_CopyToClipboard}"/>
|
<Button Width="120" Content="{DynamicResource Str_CopyDiagnosticsInfo}" Command="{Binding Cmd_CopyToClipboard}"/>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<Border>
|
<Border Grid.IsSharedSizeScope="True">
|
||||||
|
<Border.Resources>
|
||||||
|
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource LabelDefault}">
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Left"/>
|
||||||
|
</Style>
|
||||||
|
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxBaseStyle}">
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Left"/>
|
||||||
|
</Style>
|
||||||
|
</Border.Resources>
|
||||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||||
<Grid Margin="30 10">
|
<StackPanel Margin="30 10">
|
||||||
<Grid.Resources>
|
<Grid>
|
||||||
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource LabelDefault}">
|
<Grid.ColumnDefinitions>
|
||||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Left"/>
|
<ColumnDefinition Width="*" />
|
||||||
</Style>
|
</Grid.ColumnDefinitions>
|
||||||
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxBaseStyle}">
|
<Label Content="CPU"/>
|
||||||
<Setter Property="HorizontalContentAlignment" Value="Left"/>
|
<TextBox Grid.Column="1" IsReadOnly="True" Text="{Binding CPU, Mode=OneWay}"/>
|
||||||
</Style>
|
</Grid>
|
||||||
</Grid.Resources>
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<Label Grid.Row="0" Grid.Column="0" Content="CPU"/>
|
<Grid>
|
||||||
<TextBox Grid.Row="0" Grid.Column="1" IsReadOnly="True" Text="{Binding CPU, Mode=OneWay}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="GPU"/>
|
||||||
|
<TextBox Grid.Column="1" IsReadOnly="True" Text="{Binding GPU, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="1" Grid.Column="0" Content="GPU"/>
|
<Grid>
|
||||||
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Text="{Binding GPU, Mode=OneWay}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="Memory"/>
|
||||||
|
<TextBox Grid.Column="1" IsReadOnly="True" Text="{Binding Memory, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="2" Grid.Column="0" Content="Memory"/>
|
<Separator Height="10"/>
|
||||||
<TextBox Grid.Row="2" Grid.Column="1" IsReadOnly="True" Text="{Binding Memory, Mode=OneWay}"/>
|
|
||||||
|
|
||||||
<Separator Grid.Row="3" Grid.ColumnSpan="2" Height="10"/>
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="WindowsVersion"/>
|
||||||
|
<TextBox Grid.Column="1" IsReadOnly="True" Text="{Binding WindowsVersion, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="4" Grid.Column="0" Content="WindowsVersion"/>
|
<Grid>
|
||||||
<TextBox Grid.Row="4" Grid.Column="1" IsReadOnly="True" Text="{Binding WindowsVersion, Mode=OneWay}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="DotNetVersion"/>
|
||||||
|
<TextBox Grid.Column="1" IsReadOnly="True" Text="{Binding DotNetVersion, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="5" Grid.Column="0" Content="DotNetVersion"/>
|
<Grid>
|
||||||
<TextBox Grid.Row="5" Grid.Column="1" IsReadOnly="True" Text="{Binding DotNetVersion, Mode=OneWay}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="ProgramVersion"/>
|
||||||
|
<TextBox Grid.Column="1" IsReadOnly="True" Text="{Binding ProgramVersion, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="6" Grid.Column="0" Content="ProgramVersion"/>
|
<Grid>
|
||||||
<TextBox Grid.Row="6" Grid.Column="1" IsReadOnly="True" Text="{Binding ProgramVersion, Mode=OneWay}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="NLogVersion"/>
|
||||||
|
<TextBox Grid.Column="1" IsReadOnly="True" Text="{Binding NLogVersion, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="7" Grid.Column="0" Content="NLogVersion"/>
|
<Grid>
|
||||||
<TextBox Grid.Row="7" Grid.Column="1" IsReadOnly="True" Text="{Binding NLogVersion, Mode=OneWay}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="SFMLVersion"/>
|
||||||
|
<TextBox Grid.Column="1" IsReadOnly="True" Text="{Binding SFMLVersion, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="8" Grid.Column="0" Content="SFMLVersion"/>
|
<Grid>
|
||||||
<TextBox Grid.Row="8" Grid.Column="1" IsReadOnly="True" Text="{Binding SFMLVersion, Mode=OneWay}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="FFMpegCoreVersion"/>
|
||||||
|
<TextBox Grid.Column="1" IsReadOnly="True" Text="{Binding FFMpegCoreVersion, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="9" Grid.Column="0" Content="FFMpegCoreVersion"/>
|
<Grid>
|
||||||
<TextBox Grid.Row="9" Grid.Column="1" IsReadOnly="True" Text="{Binding FFMpegCoreVersion, Mode=OneWay}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="SkiaSharpVersion"/>
|
||||||
|
<TextBox Grid.Column="1" IsReadOnly="True" Text="{Binding SkiaSharpVersion, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="10" Grid.Column="0" Content="SkiaSharpVersion"/>
|
<Grid>
|
||||||
<TextBox Grid.Row="10" Grid.Column="1" IsReadOnly="True" Text="{Binding SkiaSharpVersion, Mode=OneWay}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="HandyControlVersion"/>
|
||||||
|
<TextBox Grid.Column="1" IsReadOnly="True" Text="{Binding HandyControlVersion, Mode=OneWay}"/>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<Label Grid.Row="11" Grid.Column="0" Content="HandyControlVersion"/>
|
|
||||||
<TextBox Grid.Row="11" Grid.Column="1" IsReadOnly="True" Text="{Binding HandyControlVersion, Mode=OneWay}"/>
|
|
||||||
|
|
||||||
</Grid>
|
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</Border>
|
</Border>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
<Grid x:Name="_rootGrid">
|
<Grid x:Name="_rootGrid">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto"/>
|
||||||
<ColumnDefinition Width="2.5*"/>
|
<ColumnDefinition Width="2.5*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
@@ -942,7 +942,7 @@
|
|||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
<MenuItem Header="{DynamicResource Str_WallpaperView}" Command="{Binding Cmd_SwitchWallpaperView}" IsChecked="{Binding PreferenceViewModel.WallpaperView}"/>
|
<MenuItem Header="{DynamicResource Str_WallpaperView}" Command="{Binding Cmd_SwitchWallpaperView}" IsChecked="{Binding PreferenceViewModel.WallpaperView}"/>
|
||||||
<Separator/>
|
<Separator/>
|
||||||
<MenuItem Header="{DynamicResource Str_Exit}" Command="{Binding Cmd_Exit}"/>
|
<MenuItem Header="{DynamicResource Str_Exit}" Command="{Binding Cmd_ExitFromTray}"/>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
</hc:NotifyIcon.ContextMenu>
|
</hc:NotifyIcon.ContextMenu>
|
||||||
</hc:NotifyIcon>
|
</hc:NotifyIcon>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using Spine;
|
|||||||
using SpineViewer.Models;
|
using SpineViewer.Models;
|
||||||
using SpineViewer.Natives;
|
using SpineViewer.Natives;
|
||||||
using SpineViewer.Resources;
|
using SpineViewer.Resources;
|
||||||
|
using SpineViewer.Services;
|
||||||
using SpineViewer.Utils;
|
using SpineViewer.Utils;
|
||||||
using SpineViewer.ViewModels.MainWindow;
|
using SpineViewer.ViewModels.MainWindow;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
@@ -65,11 +66,13 @@ public partial class MainWindow : Window
|
|||||||
|
|
||||||
Loaded += MainWindow_Loaded;
|
Loaded += MainWindow_Loaded;
|
||||||
ContentRendered += MainWindow_ContentRendered;
|
ContentRendered += MainWindow_ContentRendered;
|
||||||
|
Closing += MainWindow_Closing;
|
||||||
Closed += MainWindow_Closed;
|
Closed += MainWindow_Closed;
|
||||||
|
|
||||||
_vm.SpineObjectListViewModel.RequestSelectionChanging += SpinesListView_RequestSelectionChanging;
|
_vm.SpineObjectListViewModel.RequestSelectionChanging += SpinesListView_RequestSelectionChanging;
|
||||||
_vm.SFMLRendererViewModel.RequestSelectionChanging += SpinesListView_RequestSelectionChanging;
|
_vm.SFMLRendererViewModel.RequestSelectionChanging += SpinesListView_RequestSelectionChanging;
|
||||||
_vm.PreferenceViewModel.PropertyChanged += PreferenceViewModel_PropertyChanged;
|
|
||||||
|
_vm.SFMLRendererViewModel.PropertyChanged += SFMLRendererViewModel_PropertyChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -116,10 +119,17 @@ public partial class MainWindow : Window
|
|||||||
WindowState = WindowState.Normal;
|
WindowState = WindowState.Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
_rootGrid.ColumnDefinitions[0].Width = new(m.RootGridCol0Width);
|
_rootGrid.ColumnDefinitions[0].Width = new(m.RootGridCol0Width, GridUnitType.Star);
|
||||||
_modelListGrid.RowDefinitions[0].Height = new(m.ModelListRow0Height);
|
_rootGrid.ColumnDefinitions[2].Width = new(m.RootGridCol2Width, GridUnitType.Star);
|
||||||
if (m.ExplorerGridRow0Height > 0) _explorerGrid.RowDefinitions[0].Height = new(m.ExplorerGridRow0Height);
|
|
||||||
_rightPanelGrid.RowDefinitions[0].Height = new(m.RightPanelGridRow0Height);
|
_modelListGrid.RowDefinitions[0].Height = new(m.ModelListRow0Height, GridUnitType.Star);
|
||||||
|
_modelListGrid.RowDefinitions[2].Height = new(m.ModelListRow2Height, GridUnitType.Star);
|
||||||
|
|
||||||
|
_explorerGrid.RowDefinitions[0].Height = new(m.ExplorerGridRow0Height, GridUnitType.Star);
|
||||||
|
_explorerGrid.RowDefinitions[2].Height = new(m.ExplorerGridRow2Height, GridUnitType.Star);
|
||||||
|
|
||||||
|
_rightPanelGrid.RowDefinitions[0].Height = new(m.RightPanelGridRow0Height, GridUnitType.Star);
|
||||||
|
_rightPanelGrid.RowDefinitions[2].Height = new(m.RightPanelGridRow2Height, GridUnitType.Star);
|
||||||
|
|
||||||
_vm.SFMLRendererViewModel.SetResolution(m.ResolutionX, m.ResolutionY);
|
_vm.SFMLRendererViewModel.SetResolution(m.ResolutionX, m.ResolutionY);
|
||||||
_vm.SFMLRendererViewModel.MaxFps = m.MaxFps;
|
_vm.SFMLRendererViewModel.MaxFps = m.MaxFps;
|
||||||
@@ -132,18 +142,26 @@ public partial class MainWindow : Window
|
|||||||
|
|
||||||
private void SaveLastState()
|
private void SaveLastState()
|
||||||
{
|
{
|
||||||
|
var rb = RestoreBounds;
|
||||||
var m = new LastStateModel()
|
var m = new LastStateModel()
|
||||||
{
|
{
|
||||||
WindowLeft = Left,
|
WindowLeft = rb.Left,
|
||||||
WindowTop = Top,
|
WindowTop = rb.Top,
|
||||||
WindowWidth = Width,
|
WindowWidth = rb.Width,
|
||||||
WindowHeight = Height,
|
WindowHeight = rb.Height,
|
||||||
WindowState = WindowState,
|
WindowState = WindowState,
|
||||||
|
|
||||||
RootGridCol0Width = _rootGrid.ColumnDefinitions[0].ActualWidth,
|
RootGridCol0Width = _rootGrid.ColumnDefinitions[0].Width.Value,
|
||||||
ModelListRow0Height = _modelListGrid.RowDefinitions[0].ActualHeight,
|
RootGridCol2Width = _rootGrid.ColumnDefinitions[2].Width.Value,
|
||||||
ExplorerGridRow0Height = _explorerGrid.RowDefinitions[0].ActualHeight,
|
|
||||||
RightPanelGridRow0Height = _rightPanelGrid.RowDefinitions[0].ActualHeight,
|
ModelListRow0Height = _modelListGrid.RowDefinitions[0].Height.Value,
|
||||||
|
ModelListRow2Height = _modelListGrid.RowDefinitions[2].Height.Value,
|
||||||
|
|
||||||
|
ExplorerGridRow0Height = _explorerGrid.RowDefinitions[0].Height.Value,
|
||||||
|
ExplorerGridRow2Height = _explorerGrid.RowDefinitions[2].Height.Value,
|
||||||
|
|
||||||
|
RightPanelGridRow0Height = _rightPanelGrid.RowDefinitions[0].Height.Value,
|
||||||
|
RightPanelGridRow2Height = _rightPanelGrid.RowDefinitions[2].Height.Value,
|
||||||
|
|
||||||
ResolutionX = _vm.SFMLRendererViewModel.ResolutionX,
|
ResolutionX = _vm.SFMLRendererViewModel.ResolutionX,
|
||||||
ResolutionY = _vm.SFMLRendererViewModel.ResolutionY,
|
ResolutionY = _vm.SFMLRendererViewModel.ResolutionY,
|
||||||
@@ -157,14 +175,6 @@ public partial class MainWindow : Window
|
|||||||
JsonHelper.Serialize(m, LastStateFilePath);
|
JsonHelper.Serialize(m, LastStateFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 给管道通信提供的打开文件外部调用方法
|
|
||||||
/// </summary>
|
|
||||||
public void OpenFiles(IEnumerable<string> filePaths)
|
|
||||||
{
|
|
||||||
_vm.SpineObjectListViewModel.AddSpineObjectFromFileList(filePaths);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region MainWindow 事件处理
|
#region MainWindow 事件处理
|
||||||
|
|
||||||
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
|
||||||
@@ -193,30 +203,64 @@ public partial class MainWindow : Window
|
|||||||
private void MainWindow_ContentRendered(object? sender, EventArgs e)
|
private void MainWindow_ContentRendered(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
string[] args = Environment.GetCommandLineArgs();
|
string[] args = Environment.GetCommandLineArgs();
|
||||||
if (args.Length > 1)
|
|
||||||
|
// 不带参数启动
|
||||||
|
if (args.Length <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 带一个参数启动, 允许提供一些启动选项
|
||||||
|
if (args.Length == 2)
|
||||||
{
|
{
|
||||||
string[] filePaths = args.Skip(1).ToArray();
|
if (args[1] == App.AutoRunFlag)
|
||||||
_vm.SpineObjectListViewModel.AddSpineObjectFromFileList(filePaths);
|
{
|
||||||
|
var autoPath = _vm.AutoRunWorkspaceConfigPath;
|
||||||
|
if (!string.IsNullOrWhiteSpace(autoPath) && JsonHelper.Deserialize<WorkspaceModel>(autoPath, out var obj))
|
||||||
|
_vm.Workspace = obj;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 其余提供了任意参数的情况
|
||||||
|
string[] filePaths = args.Skip(1).ToArray();
|
||||||
|
_vm.SpineObjectListViewModel.AddSpineObjectFromFileList(filePaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MainWindow_Closing(object? sender, CancelEventArgs e)
|
||||||
|
{
|
||||||
|
if (!_vm.IsShuttingDownFromTray)
|
||||||
|
{
|
||||||
|
if (_vm.CloseToTray is null)
|
||||||
|
{
|
||||||
|
_vm.PreferenceViewModel.CloseToTray = MessagePopupService.YesNo(AppResource.Str_CloseToTrayQuest);
|
||||||
|
_vm.PreferenceViewModel.SavePreference();
|
||||||
|
}
|
||||||
|
if (_vm.CloseToTray is true)
|
||||||
|
{
|
||||||
|
Hide();
|
||||||
|
e.Cancel = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveLastState();
|
||||||
|
_vm.SFMLRendererViewModel.StopRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MainWindow_Closed(object? sender, EventArgs e)
|
private void MainWindow_Closed(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
SaveLastState();
|
|
||||||
|
|
||||||
var vm = _vm.SFMLRendererViewModel;
|
|
||||||
vm.StopRender();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region PreferenceViewModel 事件处理
|
#region ViewModel PropertyChanged 事件处理
|
||||||
|
|
||||||
private void PreferenceViewModel_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
private void SFMLRendererViewModel_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.PropertyName == nameof(PreferenceViewModel.WallpaperView))
|
if (e.PropertyName == nameof(SFMLRendererViewModel.WallpaperView))
|
||||||
{
|
{
|
||||||
if (_vm.PreferenceViewModel.WallpaperView)
|
var wnd = _wallpaperRenderWindow;
|
||||||
|
if (_vm.SFMLRendererViewModel.WallpaperView)
|
||||||
{
|
{
|
||||||
var workerw = User32.GetWorkerW();
|
var workerw = User32.GetWorkerW();
|
||||||
if (workerw == IntPtr.Zero)
|
if (workerw == IntPtr.Zero)
|
||||||
@@ -224,7 +268,6 @@ public partial class MainWindow : Window
|
|||||||
_logger.Error("Failed to enable wallpaper view, WorkerW not found");
|
_logger.Error("Failed to enable wallpaper view, WorkerW not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var wnd = _wallpaperRenderWindow;
|
|
||||||
var handle = wnd.SystemHandle;
|
var handle = wnd.SystemHandle;
|
||||||
|
|
||||||
User32.GetPrimaryScreenResolution(out var sw, out var sh);
|
User32.GetPrimaryScreenResolution(out var sw, out var sh);
|
||||||
@@ -232,6 +275,7 @@ public partial class MainWindow : Window
|
|||||||
User32.SetParent(handle, workerw);
|
User32.SetParent(handle, workerw);
|
||||||
User32.SetLayeredWindowAttributes(handle, 0, byte.MaxValue, User32.LWA_ALPHA);
|
User32.SetLayeredWindowAttributes(handle, 0, byte.MaxValue, User32.LWA_ALPHA);
|
||||||
|
|
||||||
|
_vm.SFMLRendererViewModel.SetResolution(sw, sh);
|
||||||
wnd.Position = new(0, 0);
|
wnd.Position = new(0, 0);
|
||||||
wnd.Size = new(sw + 1, sh);
|
wnd.Size = new(sw + 1, sh);
|
||||||
wnd.Size = new(sw, sh);
|
wnd.Size = new(sw, sh);
|
||||||
@@ -239,7 +283,7 @@ public partial class MainWindow : Window
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_wallpaperRenderWindow.SetVisible(false);
|
wnd.SetVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -394,7 +438,12 @@ public partial class MainWindow : Window
|
|||||||
|
|
||||||
private void _notifyIcon_MouseDoubleClick(object sender, RoutedEventArgs e)
|
private void _notifyIcon_MouseDoubleClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
Show();
|
||||||
|
if (WindowState == WindowState.Minimized)
|
||||||
|
{
|
||||||
|
WindowState = WindowState.Normal;
|
||||||
|
}
|
||||||
|
Activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -660,7 +709,11 @@ public partial class MainWindow : Window
|
|||||||
private void DebugMenuItem_Click(object sender, RoutedEventArgs e)
|
private void DebugMenuItem_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
var a = _rootGrid.ColumnDefinitions[0].Width;
|
||||||
|
var b = _rootGrid.ColumnDefinitions[1].Width;
|
||||||
|
var c = _rootGrid.ColumnDefinitions[2].Width;
|
||||||
|
Debug.WriteLine(a);
|
||||||
|
Debug.WriteLine(_rootGrid.ColumnDefinitions[0].Width.IsStar);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,115 +53,229 @@
|
|||||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||||
<StackPanel Grid.IsSharedSizeScope="True">
|
<StackPanel Grid.IsSharedSizeScope="True">
|
||||||
<GroupBox Header="{DynamicResource Str_TextureLoadPreference}">
|
<GroupBox Header="{DynamicResource Str_TextureLoadPreference}">
|
||||||
<Grid>
|
<StackPanel>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid>
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
</Grid.ColumnDefinitions>
|
<ColumnDefinition Width="*" />
|
||||||
<Grid.RowDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<Label Content="{DynamicResource Str_ForcePremul}" ToolTip="{DynamicResource Str_ForcePremulTooltip}"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<ToggleButton Grid.Column="1" IsChecked="{Binding ForcePremul}" ToolTip="{DynamicResource Str_ForcePremulTooltip}"/>
|
||||||
<RowDefinition Height="Auto"/>
|
</Grid>
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_ForcePremul}" ToolTip="{DynamicResource Str_ForcePremulTooltip}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="0" Grid.Column="1" IsChecked="{Binding ForcePremul}" ToolTip="{DynamicResource Str_ForcePremulTooltip}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_ForceNearest}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding ForceNearest}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_ForceNearest}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="1" Grid.Column="1" IsChecked="{Binding ForceNearest}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_ForceMipmap}" ToolTip="{DynamicResource Str_ForceMipmapTooltip}"/>
|
<ColumnDefinition Width="*" />
|
||||||
<ToggleButton Grid.Row="2" Grid.Column="1" IsChecked="{Binding ForceMipmap}" ToolTip="{DynamicResource Str_ForceMipmapTooltip}"/>
|
</Grid.ColumnDefinitions>
|
||||||
</Grid>
|
<Label Content="{DynamicResource Str_ForceMipmap}" ToolTip="{DynamicResource Str_ForceMipmapTooltip}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding ForceMipmap}" ToolTip="{DynamicResource Str_ForceMipmapTooltip}"/>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
|
|
||||||
<GroupBox Header="{DynamicResource Str_SpineLoadPreference}">
|
<GroupBox Header="{DynamicResource Str_SpineLoadPreference}">
|
||||||
<Grid>
|
<StackPanel>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid>
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
</Grid.ColumnDefinitions>
|
<ColumnDefinition Width="*" />
|
||||||
<Grid.RowDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<Label Content="{DynamicResource Str_IsShown}"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<ToggleButton Grid.Column="1" IsChecked="{Binding IsShown}"/>
|
||||||
<RowDefinition Height="Auto"/>
|
</Grid>
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_IsShown}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="0" Grid.Column="1" IsChecked="{Binding IsShown}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_UsePma}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding UsePma}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_UsePma}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="1" Grid.Column="1" IsChecked="{Binding UsePma}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_DebugTexture}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding DebugTexture}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_DebugTexture}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="2" Grid.Column="1" IsChecked="{Binding DebugTexture}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_DebugBounds}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding DebugBounds}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_DebugBounds}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="3" Grid.Column="1" IsChecked="{Binding DebugBounds}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_DebugBones}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding DebugBones}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="4" Grid.Column="0" Content="{DynamicResource Str_DebugBones}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="4" Grid.Column="1" IsChecked="{Binding DebugBones}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_DebugRegions}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding DebugRegions}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="5" Grid.Column="0" Content="{DynamicResource Str_DebugRegions}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="5" Grid.Column="1" IsChecked="{Binding DebugRegions}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_DebugMeshHulls}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding DebugMeshHulls}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="6" Grid.Column="0" Content="{DynamicResource Str_DebugMeshHulls}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="6" Grid.Column="1" IsChecked="{Binding DebugMeshHulls}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_DebugMeshes}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding DebugMeshes}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="7" Grid.Column="0" Content="{DynamicResource Str_DebugMeshes}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="7" Grid.Column="1" IsChecked="{Binding DebugMeshes}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_DebugClippings}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding DebugClippings}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="8" Grid.Column="0" Content="{DynamicResource Str_DebugClippings}"/>
|
<!-- <Grid>
|
||||||
<ToggleButton Grid.Row="8" Grid.Column="1" IsChecked="{Binding DebugClippings}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_DebugBoundingBoxes}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding DebugBoundingBoxes}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<!--<Label Grid.Row="9" Grid.Column="0" Content="{DynamicResource Str_DebugBoundingBoxes}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="9" Grid.Column="1" IsChecked="{Binding DebugBoundingBoxes}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_DebugPaths}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding DebugPaths}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="10" Grid.Column="0" Content="{DynamicResource Str_DebugPaths}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="10" Grid.Column="1" IsChecked="{Binding DebugPaths}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_DebugPoints}"/>
|
||||||
|
<ToggleButton Grid.Column="1" IsChecked="{Binding DebugPoints}"/>
|
||||||
|
</Grid> -->
|
||||||
|
|
||||||
<Label Grid.Row="11" Grid.Column="0" Content="{DynamicResource Str_DebugPoints}"/>
|
</StackPanel>
|
||||||
<ToggleButton Grid.Row="11" Grid.Column="1" IsChecked="{Binding DebugPoints}"/>-->
|
|
||||||
</Grid>
|
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
|
|
||||||
<GroupBox Header="{DynamicResource Str_AppPreference}">
|
<GroupBox Header="{DynamicResource Str_AppPreference}">
|
||||||
<Grid>
|
<StackPanel>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid>
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Col1"/>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
</Grid.ColumnDefinitions>
|
<ColumnDefinition Width="*" />
|
||||||
<Grid.RowDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<RowDefinition Height="Auto"/>
|
<Label Content="{DynamicResource Str_Language}"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<ComboBox Grid.Column="1"
|
||||||
<RowDefinition Height="Auto"/>
|
SelectedItem="{Binding AppLanguage}"
|
||||||
<RowDefinition Height="Auto"/>
|
ItemsSource="{x:Static vm:PreferenceViewModel.AppLanguageOptions}"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="0" Grid.Column="0" Content="{DynamicResource Str_WallpaperView}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="0" Grid.Column="1" IsChecked="{Binding WallpaperView}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_RenderSelectedOnly}"/>
|
||||||
|
<ToggleButton Grid.Column="1"
|
||||||
|
IsChecked="{Binding RenderSelectedOnly}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="1" Grid.Column="0" Content="{DynamicResource Str_RenderSelectedOnly}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="1" Grid.Column="1" IsChecked="{Binding RenderSelectedOnly}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_WallpaperView}"/>
|
||||||
|
<ToggleButton Grid.Column="1"
|
||||||
|
IsChecked="{Binding WallpaperView}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="2" Grid.Column="0" Content="{DynamicResource Str_AssociateFileSuffix}"/>
|
<Grid>
|
||||||
<ToggleButton Grid.Row="2" Grid.Column="1" IsChecked="{Binding AssociateFileSuffix}"/>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_CloseToTray}"/>
|
||||||
|
<ToggleButton Grid.Column="1"
|
||||||
|
IsChecked="{Binding CloseToTray}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Label Grid.Row="3" Grid.Column="0" Content="{DynamicResource Str_Language}"/>
|
<Grid>
|
||||||
<ComboBox Grid.Row="3" Grid.Column="1"
|
<Grid.ColumnDefinitions>
|
||||||
SelectedItem="{Binding AppLanguage}"
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
ItemsSource="{x:Static vm:PreferenceViewModel.AppLanguageOptions}"/>
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_AutoRun}"/>
|
||||||
|
<ToggleButton Grid.Column="1"
|
||||||
|
IsChecked="{Binding AutoRun}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
</Grid>
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_AutoRunWorkspaceConfigPath}"
|
||||||
|
ToolTip="{DynamicResource Str_AutoRunWorkspaceConfigPathTooltip}"/>
|
||||||
|
<DockPanel Grid.Column="1" IsEnabled="{Binding AutoRun}">
|
||||||
|
<Button DockPanel.Dock="Right"
|
||||||
|
Content="..."
|
||||||
|
Command="{Binding Cmd_SelectAutoRunWorkspaceConfigPath}"/>
|
||||||
|
<TextBox Grid.Column="1"
|
||||||
|
Text="{Binding AutoRunWorkspaceConfigPath}"
|
||||||
|
ToolTip="{DynamicResource Str_AutoRunWorkspaceConfigPathTooltip}"/>
|
||||||
|
</DockPanel>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Label Content="{DynamicResource Str_AssociateFileSuffix}"/>
|
||||||
|
<ToggleButton Grid.Column="1"
|
||||||
|
IsChecked="{Binding AssociateFileSuffix}"/>
|
||||||
|
</Grid>
|
||||||
|
</StackPanel>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|||||||
BIN
img/preview.webp
BIN
img/preview.webp
Binary file not shown.
|
Before Width: | Height: | Size: 177 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB |
Reference in New Issue
Block a user