Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e293daf62 | ||
|
|
f9d7fdc516 | ||
|
|
6a04f3955c | ||
|
|
dce3b1780c | ||
|
|
f47f3e9db6 | ||
|
|
4ac74acaf7 | ||
|
|
cf7588c288 | ||
|
|
ec7bdf4000 | ||
|
|
51cd97f782 | ||
|
|
a16f2f096d | ||
|
|
4e92f14551 | ||
|
|
8f6cc9ff44 | ||
|
|
f885df5c67 |
@@ -1,5 +1,14 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## v0.10.9
|
||||||
|
|
||||||
|
- 预览图导出增加名称后缀参数
|
||||||
|
|
||||||
|
## v0.10.8
|
||||||
|
|
||||||
|
- 完善预览图导出
|
||||||
|
- 优化骨骼文件选择
|
||||||
|
|
||||||
## v0.10.7
|
## v0.10.7
|
||||||
|
|
||||||
- 增加仅导出选中
|
- 增加仅导出选中
|
||||||
|
|||||||
90
README.en.md
90
README.en.md
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
[中文](README.md) | [English](README.en.md)
|
[中文](README.md) | [English](README.en.md)
|
||||||
|
|
||||||
A simple and user-friendly Spine file viewer and exporter.
|
A simple and user-friendly tool for viewing and exporting Spine files.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -12,59 +12,81 @@ A simple and user-friendly Spine file viewer and exporter.
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Download the zip package from the [Releases](https://github.com/ww-rm/SpineViewer/releases) page.
|
Go to the [Release](https://github.com/ww-rm/SpineViewer/releases) page to download the compressed package.
|
||||||
|
|
||||||
The application requires the [.NET Desktop Runtime 8.0.x](https://dotnet.microsoft.com/en-us/download/dotnet/8.0).
|
The software requires the dependency framework [.NET Desktop Runtime 8.0.x](https://dotnet.microsoft.com/zh-cn/download/dotnet/8.0).
|
||||||
|
|
||||||
Alternatively, you can download the zip package with the `SelfContained` suffix, which can run independently.
|
You can also download the package with the `SelfContained` suffix, which can run independently.
|
||||||
|
|
||||||
## Features
|
## Version Support
|
||||||
|
|
||||||
- Supports viewing Spine files of different versions:
|
| Version | View & Export | Format Conversion | Version Conversion |
|
||||||
- [x] `v2.1.x`
|
| :-------: | :--------------------: | :--------------------: | :----------------: |
|
||||||
- [x] `v3.6.x`
|
| `2.1.x` | :white_check_mark: | | |
|
||||||
- [x] `v3.7.x`
|
| `3.1.x` | | | |
|
||||||
- [x] `v3.8.x`
|
| `3.4.x` | | | |
|
||||||
- [x] `v4.0.x`
|
| `3.5.x` | | | |
|
||||||
- [x] `v4.1.x`
|
| `3.6.x` | :white_check_mark: | | |
|
||||||
- [x] `v4.2.x`
|
| `3.7.x` | :white_check_mark: | | |
|
||||||
- [ ] `v4.3.x`
|
| `3.8.x` | :white_check_mark: | :white_check_mark: | |
|
||||||
- Supports animation preview for multi-skeleton files
|
| `4.1.x` | :white_check_mark: | | |
|
||||||
- Allows independent parameter settings for each skeleton
|
| `4.2.x` | :white_check_mark: | | |
|
||||||
- Supports exporting animation as PNG frame sequences
|
| `4.3.x` | | | |
|
||||||
- Provides export settings such as zoom and rotation
|
|
||||||
- More features coming soon...
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### Importing Skeletons
|
### Importing Skeletons
|
||||||
|
|
||||||
Use the **File** menu to select **Open** or **Batch Open** to import skeleton files.
|
There are 3 ways to import skeleton files:
|
||||||
|
|
||||||
### Adjusting Skeletons
|
- **Drag & Drop/Paste:**
|
||||||
|
Drag and drop or paste the skeleton file/directory into the model list.
|
||||||
|
This method automatically searches through the provided files and subdirectories. Although convenient, it relies on the file structure and has its limitations.
|
||||||
|
|
||||||
|
- Only standard files with `*.json`, `*.skel`, or `.atlas` extensions are automatically detected.
|
||||||
|
- The skeleton file and atlas file must have the same name.
|
||||||
|
- The version string in the skeleton file must not be modified.
|
||||||
|
|
||||||
Select one or more items in the **Model List** to display adjustable parameters in the **Model Parameters** panel.
|
- **Batch Open from the File Menu:**
|
||||||
|
This method offers more file flexibility. You can drag and drop or paste files into the file selection dialog, and additional options are available.
|
||||||
|
|
||||||
|
- The filename restrictions are similar to the above, but you can use the panel’s file selection button to choose skeleton files with non-standard extensions.
|
||||||
|
- You can set a fixed load version to handle cases where the version number has been modified.
|
||||||
|
|
||||||
Right-clicking in the **Model List** allows you to add, delete, or adjust list items. You can also drag items with the left mouse button to rearrange them.
|
- **Open a Single Model:**
|
||||||
|
This method offers the highest degree of freedom, allowing you to select any skeleton file and atlas file without filename restrictions. You can also set the load version.
|
||||||
|
|
||||||
### Adjusting the View
|
### Adjusting Preview Content
|
||||||
|
|
||||||
Mouse operations supported in the **Preview** window:
|
The model list supports right-click menus and various shortcut keys, and you can select multiple models to adjust their parameters in bulk.
|
||||||
|
|
||||||
- Left-click to drag the skeleton
|
In addition to the parameter panel, the preview area supports several mouse actions:
|
||||||
- Right-click to drag the view
|
|
||||||
- Scroll wheel to zoom in/out
|
|
||||||
|
|
||||||
Additionally, you can adjust export and preview parameters through the **View Parameters** panel.
|
- **Left-click:** Select and drag models. Holding down the `Ctrl` key enables multi-selection, which syncs with the model list.
|
||||||
|
- **Right-click:** Drag the overall canvas.
|
||||||
|
- **Scroll wheel:** Zoom the view.
|
||||||
|
- **Selective Rendering:** The preview area supports a mode to render only the selected models. In this mode, only the selected models are displayed, and selection changes must be made through the model list.
|
||||||
|
|
||||||
In the **Functions** menu, you can reset and synchronize the animation time for all skeletons.
|
In the function menu, you can reset and synchronize the animation time for all skeletons.
|
||||||
|
|
||||||
### Exporting Animations
|
### Exporting Preview Content
|
||||||
|
|
||||||
Select **Export** from the **File** menu to export all loaded skeleton animations as PNG frame sequences, based on the current preview settings.
|
Both preview images and videos can be exported.
|
||||||
|
|
||||||
You can view the full duration of each animation in the **Model Parameters** of each skeleton.
|
- **Preview Image:**
|
||||||
|
The exported preview image shows the model in its default state, with one image per model.
|
||||||
|
|
||||||
|
- **Video (TODO: Currently only supports frame sequence export):**
|
||||||
|
The complete animation duration for each skeleton can be viewed in the model parameters.
|
||||||
|
|
||||||
|
When the preview area is set to render only the selected models, the exported content will include only the models that are displayed.
|
||||||
|
|
||||||
|
### Format & Version Conversion
|
||||||
|
|
||||||
|
You can use the tools menu to convert skeleton files. This feature supports conversion between binary and text formats, as well as between different versions.
|
||||||
|
|
||||||
|
Currently under development, it only supports converting `3.8.x` binary format to text format.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*If you find this project helpful, please give it a :star: and share it with others! :)*
|
*If you like this project, please give it a :star: and share it with more people! :)*
|
||||||
|
|||||||
86
README.md
86
README.md
@@ -18,62 +18,72 @@
|
|||||||
|
|
||||||
也可以下载带有 `SelfContained` 后缀的压缩包, 可以独立运行.
|
也可以下载带有 `SelfContained` 后缀的压缩包, 可以独立运行.
|
||||||
|
|
||||||
## 功能支持
|
## 版本支持
|
||||||
|
|
||||||
| 版本 | 查看&导出 | 格式转换 |
|
| 版本 | 查看&导出 | 格式转换 | 版本转换 |
|
||||||
| :---: | :---: | :---: |
|
| :---: | :---: | :---: | :---: |
|
||||||
| `2.1.x` | :white_check_mark: | |
|
| `2.1.x` | :white_check_mark: | | |
|
||||||
| `3.1.x` | | |
|
| `3.1.x` | | | |
|
||||||
| `3.4.x` | | |
|
| `3.4.x` | | | |
|
||||||
| `3.5.x` | | |
|
| `3.5.x` | | | |
|
||||||
| `3.6.x` | :white_check_mark: | |
|
| `3.6.x` | :white_check_mark: | | |
|
||||||
| `3.7.x` | :white_check_mark: | |
|
| `3.7.x` | :white_check_mark: | | |
|
||||||
| `3.8.x` | :white_check_mark: | :white_check_mark: |
|
| `3.8.x` | :white_check_mark: | :white_check_mark: | |
|
||||||
| `4.1.x` | :white_check_mark: | |
|
| `4.1.x` | :white_check_mark: | | |
|
||||||
| `4.2.x` | :white_check_mark: | |
|
| `4.2.x` | :white_check_mark: | | |
|
||||||
| `4.3.x` | | |
|
| `4.3.x` | | | |
|
||||||
|
|
||||||
- 支持文件拖放/复制到剪贴板打开
|
|
||||||
- 支持自动检测版本
|
|
||||||
- 支持列表缩略图预览
|
|
||||||
- 支持多骨骼文件动画预览
|
|
||||||
- 支持每个骨骼独立参数设置
|
|
||||||
- 支持动画PNG帧序列导出
|
|
||||||
- 支持缩放旋转等导出画面设置
|
|
||||||
- 支持对独立的骨骼文件进行格式转换
|
|
||||||
- Coming soon...
|
|
||||||
|
|
||||||
## 使用方法
|
## 使用方法
|
||||||
|
|
||||||
### 骨骼导入
|
### 骨骼导入
|
||||||
|
|
||||||
**文件**菜单可以选择**打开**或者**批量打开**进行骨骼文件导入.
|
有 3 种模式导入骨骼文件:
|
||||||
|
|
||||||
或者直接把要打开的骨骼文件拖进列表, 这种方式只支持 `.json` 和 `.skel` 后缀的文件, 其他的会被忽略.
|
- 拖放/粘贴需要导入的骨骼文件/目录到模型列表
|
||||||
|
|
||||||
### 骨骼调整
|
这种方式会自动查找传入的文件列表以及目录内的子级文件列表, 虽然方便但是依赖模型文件结构, 限制最多.
|
||||||
|
|
||||||
在**模型列表**中选择一项或多项, 将会在**模型参数**面板显示可供调节的参数.
|
- 仅支持自动发现标准的 `*.json`/`*.skel`/`.atlas` 后缀文件.
|
||||||
|
- 骨骼文件和 atlas 文件需要是同名.
|
||||||
|
- 需要保证骨骼文件里的版本字符串不是魔改过的.
|
||||||
|
- 从文件菜单里批量打开骨骼文件
|
||||||
|
|
||||||
**模型列表**右键菜单可以对列表项进行增删调整, 也可以使用鼠标左键拖动调整顺序.
|
这种方式提供一定程度的文件自由度, 文件选择框里同样支持拖放/粘贴, 但是多一些额外选项.
|
||||||
|
|
||||||
### 画面调整
|
- 文件名限制条件与上面类似, 但是可以通过面板的选择文件按钮选择非标准后缀的骨骼文件.
|
||||||
|
- 可以设置固定加载版本, 便于应对魔改过的版本号.
|
||||||
|
- 选择单个模型打开
|
||||||
|
|
||||||
**预览画面**支持的鼠标操作:
|
这种方式自由度最高, 允许选择任意的骨骼文件和 atlas 文件, 可以没有文件名限制, 并且也可以设置加载版本.
|
||||||
|
|
||||||
- 左键可以对骨骼进行拖动
|
### 预览内容调整
|
||||||
- 右键对画面进行拖动
|
|
||||||
- 滚轮进行画面缩放
|
|
||||||
|
|
||||||
除此之外, 也可以通过**画面参数**面板调节导出和预览时的画面参数.
|
模型列表支持右键菜单以及部分快捷键, 并且可以多选进行模型参数的批量调整.
|
||||||
|
|
||||||
在**功能**菜单中, 可以重置同步所有骨骼动画时间.
|
预览画面除了使用面板进行参数设置外, 支持部分鼠标动作:
|
||||||
|
|
||||||
### 动画导出
|
- 左键可以选择和拖拽模型, 按下 `Ctrl` 键可以实现多选, 与左侧列表选择是联动的.
|
||||||
|
- 右键对整体画面进行拖动.
|
||||||
|
- 滚轮进行画面缩放.
|
||||||
|
- 预览画面支持仅渲染选中, 在该模式下, 画面仅显示被选中的模型, 并且只能通过左侧列表改变选中状态.
|
||||||
|
|
||||||
**文件**菜单中选择**导出**可以将目前加载的所有骨骼动画按照预览时的画面进行PNG帧序列导出.
|
在功能菜单中, 可以重置同步所有骨骼动画时间.
|
||||||
|
|
||||||
可以在每个骨骼的**模型参数**中查看动画完整时长.
|
### 预览内容导出
|
||||||
|
|
||||||
|
支持预览图和视频的导出.
|
||||||
|
|
||||||
|
预览图导出的内容是模型的默认状态画面, 每个模型一张单独的预览图.
|
||||||
|
|
||||||
|
视频(TODO: 目前仅支持帧序列导出), 可以在每个骨骼的模型参数中查看动画完整时长.
|
||||||
|
|
||||||
|
当预览画面处于仅渲染选中状态时, 导出的内容仅包含被选中的模型, 也就是在画面中显示的内容.
|
||||||
|
|
||||||
|
### 格式与版本转换
|
||||||
|
|
||||||
|
可以通过工具菜单进行骨骼文件转换, 允许二进制和文本格式之间的转换, 以及不同版本间的转换.
|
||||||
|
|
||||||
|
目前处于施工中, 仅支持转换 `3.8.x` 二进制到文本格式.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
197
SpineViewer/Controls/SkelFileListBox.Designer.cs
generated
Normal file
197
SpineViewer/Controls/SkelFileListBox.Designer.cs
generated
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
namespace SpineViewer.Controls
|
||||||
|
{
|
||||||
|
partial class SkelFileListBox
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 必需的设计器变量。
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 清理所有正在使用的资源。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 组件设计器生成的代码
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设计器支持所需的方法 - 不要修改
|
||||||
|
/// 使用代码编辑器修改此方法的内容。
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
components = new System.ComponentModel.Container();
|
||||||
|
tableLayoutPanel1 = new TableLayoutPanel();
|
||||||
|
flowLayoutPanel1 = new FlowLayoutPanel();
|
||||||
|
button_AddFolder = new Button();
|
||||||
|
button_AddFile = new Button();
|
||||||
|
label_Tip = new Label();
|
||||||
|
listBox = new ListBox();
|
||||||
|
contextMenuStrip = new ContextMenuStrip(components);
|
||||||
|
toolStripMenuItem_SelectAll = new ToolStripMenuItem();
|
||||||
|
toolStripMenuItem_Paste = new ToolStripMenuItem();
|
||||||
|
toolStripMenuItem_Remove = new ToolStripMenuItem();
|
||||||
|
folderBrowserDialog = new FolderBrowserDialog();
|
||||||
|
openFileDialog_Skel = new OpenFileDialog();
|
||||||
|
tableLayoutPanel1.SuspendLayout();
|
||||||
|
flowLayoutPanel1.SuspendLayout();
|
||||||
|
contextMenuStrip.SuspendLayout();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// tableLayoutPanel1
|
||||||
|
//
|
||||||
|
tableLayoutPanel1.ColumnCount = 1;
|
||||||
|
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
||||||
|
tableLayoutPanel1.Controls.Add(flowLayoutPanel1, 0, 0);
|
||||||
|
tableLayoutPanel1.Controls.Add(listBox, 0, 1);
|
||||||
|
tableLayoutPanel1.Dock = DockStyle.Fill;
|
||||||
|
tableLayoutPanel1.Location = new Point(0, 0);
|
||||||
|
tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||||
|
tableLayoutPanel1.RowCount = 2;
|
||||||
|
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
||||||
|
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||||
|
tableLayoutPanel1.Size = new Size(801, 394);
|
||||||
|
tableLayoutPanel1.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// flowLayoutPanel1
|
||||||
|
//
|
||||||
|
flowLayoutPanel1.AutoSize = true;
|
||||||
|
flowLayoutPanel1.AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
||||||
|
flowLayoutPanel1.Controls.Add(button_AddFolder);
|
||||||
|
flowLayoutPanel1.Controls.Add(button_AddFile);
|
||||||
|
flowLayoutPanel1.Controls.Add(label_Tip);
|
||||||
|
flowLayoutPanel1.Dock = DockStyle.Fill;
|
||||||
|
flowLayoutPanel1.Location = new Point(3, 3);
|
||||||
|
flowLayoutPanel1.Name = "flowLayoutPanel1";
|
||||||
|
flowLayoutPanel1.Size = new Size(795, 40);
|
||||||
|
flowLayoutPanel1.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// button_AddFolder
|
||||||
|
//
|
||||||
|
button_AddFolder.AutoSize = true;
|
||||||
|
button_AddFolder.AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
||||||
|
button_AddFolder.Location = new Point(3, 3);
|
||||||
|
button_AddFolder.Name = "button_AddFolder";
|
||||||
|
button_AddFolder.Size = new Size(122, 34);
|
||||||
|
button_AddFolder.TabIndex = 0;
|
||||||
|
button_AddFolder.Text = "添加文件夹...";
|
||||||
|
button_AddFolder.UseVisualStyleBackColor = true;
|
||||||
|
button_AddFolder.Click += button_AddFolder_Click;
|
||||||
|
//
|
||||||
|
// button_AddFile
|
||||||
|
//
|
||||||
|
button_AddFile.AutoSize = true;
|
||||||
|
button_AddFile.AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
||||||
|
button_AddFile.Location = new Point(131, 3);
|
||||||
|
button_AddFile.Name = "button_AddFile";
|
||||||
|
button_AddFile.Size = new Size(104, 34);
|
||||||
|
button_AddFile.TabIndex = 1;
|
||||||
|
button_AddFile.Text = "添加文件...";
|
||||||
|
button_AddFile.UseVisualStyleBackColor = true;
|
||||||
|
button_AddFile.Click += button_AddFile_Click;
|
||||||
|
//
|
||||||
|
// label_Tip
|
||||||
|
//
|
||||||
|
label_Tip.Anchor = AnchorStyles.Left;
|
||||||
|
label_Tip.AutoSize = true;
|
||||||
|
label_Tip.Location = new Point(241, 8);
|
||||||
|
label_Tip.Name = "label_Tip";
|
||||||
|
label_Tip.Size = new Size(139, 24);
|
||||||
|
label_Tip.TabIndex = 3;
|
||||||
|
label_Tip.Text = "已添加 0 个文件";
|
||||||
|
label_Tip.TextAlign = ContentAlignment.MiddleCenter;
|
||||||
|
//
|
||||||
|
// listBox
|
||||||
|
//
|
||||||
|
listBox.AllowDrop = true;
|
||||||
|
listBox.ContextMenuStrip = contextMenuStrip;
|
||||||
|
listBox.Dock = DockStyle.Fill;
|
||||||
|
listBox.FormattingEnabled = true;
|
||||||
|
listBox.HorizontalScrollbar = true;
|
||||||
|
listBox.ItemHeight = 24;
|
||||||
|
listBox.Location = new Point(3, 49);
|
||||||
|
listBox.Name = "listBox";
|
||||||
|
listBox.SelectionMode = SelectionMode.MultiExtended;
|
||||||
|
listBox.Size = new Size(795, 342);
|
||||||
|
listBox.TabIndex = 0;
|
||||||
|
listBox.DragDrop += listBox_DragDrop;
|
||||||
|
listBox.DragEnter += listBox_DragEnter;
|
||||||
|
//
|
||||||
|
// contextMenuStrip
|
||||||
|
//
|
||||||
|
contextMenuStrip.ImageScalingSize = new Size(24, 24);
|
||||||
|
contextMenuStrip.Items.AddRange(new ToolStripItem[] { toolStripMenuItem_SelectAll, toolStripMenuItem_Paste, toolStripMenuItem_Remove });
|
||||||
|
contextMenuStrip.Name = "contextMenuStrip";
|
||||||
|
contextMenuStrip.Size = new Size(184, 94);
|
||||||
|
//
|
||||||
|
// toolStripMenuItem_SelectAll
|
||||||
|
//
|
||||||
|
toolStripMenuItem_SelectAll.Name = "toolStripMenuItem_SelectAll";
|
||||||
|
toolStripMenuItem_SelectAll.ShortcutKeys = Keys.Control | Keys.A;
|
||||||
|
toolStripMenuItem_SelectAll.Size = new Size(183, 30);
|
||||||
|
toolStripMenuItem_SelectAll.Text = "全选";
|
||||||
|
toolStripMenuItem_SelectAll.Click += toolStripMenuItem_SelectAll_Click;
|
||||||
|
//
|
||||||
|
// toolStripMenuItem_Paste
|
||||||
|
//
|
||||||
|
toolStripMenuItem_Paste.Name = "toolStripMenuItem_Paste";
|
||||||
|
toolStripMenuItem_Paste.ShortcutKeys = Keys.Control | Keys.V;
|
||||||
|
toolStripMenuItem_Paste.Size = new Size(183, 30);
|
||||||
|
toolStripMenuItem_Paste.Text = "粘贴";
|
||||||
|
toolStripMenuItem_Paste.Click += toolStripMenuItem_Paste_Click;
|
||||||
|
//
|
||||||
|
// toolStripMenuItem_Remove
|
||||||
|
//
|
||||||
|
toolStripMenuItem_Remove.Name = "toolStripMenuItem_Remove";
|
||||||
|
toolStripMenuItem_Remove.ShortcutKeys = Keys.Delete;
|
||||||
|
toolStripMenuItem_Remove.Size = new Size(183, 30);
|
||||||
|
toolStripMenuItem_Remove.Text = "移除";
|
||||||
|
toolStripMenuItem_Remove.Click += toolStripMenuItem_Remove_Click;
|
||||||
|
//
|
||||||
|
// openFileDialog_Skel
|
||||||
|
//
|
||||||
|
openFileDialog_Skel.AddExtension = false;
|
||||||
|
openFileDialog_Skel.AddToRecent = false;
|
||||||
|
openFileDialog_Skel.Filter = "skel 文件 (*.skel; *.json)|*.skel;*.json|二进制文件 (*.skel)|*.skel|文本文件 (*.json)|*.json|所有文件 (*.*)|*.*";
|
||||||
|
openFileDialog_Skel.Multiselect = true;
|
||||||
|
openFileDialog_Skel.Title = "批量选择skel文件";
|
||||||
|
//
|
||||||
|
// SkelFileListBox
|
||||||
|
//
|
||||||
|
AutoScaleDimensions = new SizeF(11F, 24F);
|
||||||
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
|
Controls.Add(tableLayoutPanel1);
|
||||||
|
Name = "SkelFileListBox";
|
||||||
|
Size = new Size(801, 394);
|
||||||
|
tableLayoutPanel1.ResumeLayout(false);
|
||||||
|
tableLayoutPanel1.PerformLayout();
|
||||||
|
flowLayoutPanel1.ResumeLayout(false);
|
||||||
|
flowLayoutPanel1.PerformLayout();
|
||||||
|
contextMenuStrip.ResumeLayout(false);
|
||||||
|
ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private TableLayoutPanel tableLayoutPanel1;
|
||||||
|
private ListBox listBox;
|
||||||
|
private FlowLayoutPanel flowLayoutPanel1;
|
||||||
|
private Button button_AddFolder;
|
||||||
|
private Button button_AddFile;
|
||||||
|
private FolderBrowserDialog folderBrowserDialog;
|
||||||
|
private Label label_Tip;
|
||||||
|
private ContextMenuStrip contextMenuStrip;
|
||||||
|
private OpenFileDialog openFileDialog_Skel;
|
||||||
|
private ToolStripMenuItem toolStripMenuItem_SelectAll;
|
||||||
|
private ToolStripMenuItem toolStripMenuItem_Paste;
|
||||||
|
private ToolStripMenuItem toolStripMenuItem_Remove;
|
||||||
|
}
|
||||||
|
}
|
||||||
123
SpineViewer/Controls/SkelFileListBox.cs
Normal file
123
SpineViewer/Controls/SkelFileListBox.cs
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace SpineViewer.Controls
|
||||||
|
{
|
||||||
|
public partial class SkelFileListBox : UserControl
|
||||||
|
{
|
||||||
|
public SkelFileListBox()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
Items = listBox.Items;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ListBox.Items
|
||||||
|
/// </summary>
|
||||||
|
public readonly ListBox.ObjectCollection Items;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从路径列表添加
|
||||||
|
/// </summary>
|
||||||
|
private void AddFromFileDrop(string[] paths)
|
||||||
|
{
|
||||||
|
foreach (var path in paths)
|
||||||
|
{
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
if (Spine.Spine.CommonSkelSuffix.Contains(Path.GetExtension(path).ToLower()))
|
||||||
|
listBox.Items.Add(Path.GetFullPath(path));
|
||||||
|
}
|
||||||
|
else if (Directory.Exists(path))
|
||||||
|
{
|
||||||
|
foreach (var file in Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
if (Spine.Spine.CommonSkelSuffix.Contains(Path.GetExtension(file).ToLower()))
|
||||||
|
listBox.Items.Add(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void button_AddFolder_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (folderBrowserDialog.ShowDialog() != DialogResult.OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var path = folderBrowserDialog.SelectedPath;
|
||||||
|
if (Directory.Exists(path))
|
||||||
|
{
|
||||||
|
foreach (var file in Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
if (Spine.Spine.CommonSkelSuffix.Contains(Path.GetExtension(file).ToLower()))
|
||||||
|
listBox.Items.Add(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label_Tip.Text = $"已选择 {listBox.Items.Count} 个文件";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void button_AddFile_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (openFileDialog_Skel.ShowDialog() != DialogResult.OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var p in openFileDialog_Skel.FileNames)
|
||||||
|
listBox.Items.Add(Path.GetFullPath(p));
|
||||||
|
|
||||||
|
label_Tip.Text = $"已选择 {listBox.Items.Count} 个文件";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void listBox_DragEnter(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||||
|
e.Effect = DragDropEffects.Copy;
|
||||||
|
else
|
||||||
|
e.Effect = DragDropEffects.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void listBox_DragDrop(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
if (!e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||||
|
return;
|
||||||
|
|
||||||
|
AddFromFileDrop((string[])e.Data.GetData(DataFormats.FileDrop));
|
||||||
|
label_Tip.Text = $"已选择 {listBox.Items.Count} 个文件";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toolStripMenuItem_SelectAll_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < listBox.Items.Count; i++)
|
||||||
|
listBox.SelectedIndices.Add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toolStripMenuItem_Paste_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (!Clipboard.ContainsFileDropList())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var fileDropList = Clipboard.GetFileDropList();
|
||||||
|
var paths = new string[fileDropList.Count];
|
||||||
|
fileDropList.CopyTo(paths, 0);
|
||||||
|
AddFromFileDrop(paths);
|
||||||
|
label_Tip.Text = $"已选择 {listBox.Items.Count} 个文件";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toolStripMenuItem_Remove_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var indices = new int[listBox.SelectedIndices.Count];
|
||||||
|
listBox.SelectedIndices.CopyTo(indices, 0);
|
||||||
|
for (int i = indices.Length - 1; i >= 0; i--)
|
||||||
|
listBox.Items.RemoveAt(indices[i]);
|
||||||
|
label_Tip.Text = $"已选择 {listBox.Items.Count} 个文件";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
129
SpineViewer/Controls/SkelFileListBox.resx
Normal file
129
SpineViewer/Controls/SkelFileListBox.resx
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<metadata name="contextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>556, 18</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="folderBrowserDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>286, 21</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="openFileDialog_Skel.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>31, 27</value>
|
||||||
|
</metadata>
|
||||||
|
</root>
|
||||||
98
SpineViewer/Dialogs/BatchOpenSpineDialog.Designer.cs
generated
98
SpineViewer/Dialogs/BatchOpenSpineDialog.Designer.cs
generated
@@ -37,10 +37,7 @@
|
|||||||
tableLayoutPanel2 = new TableLayoutPanel();
|
tableLayoutPanel2 = new TableLayoutPanel();
|
||||||
button_Ok = new Button();
|
button_Ok = new Button();
|
||||||
button_Cancel = new Button();
|
button_Cancel = new Button();
|
||||||
listBox_FilePath = new ListBox();
|
skelFileListBox = new SpineViewer.Controls.SkelFileListBox();
|
||||||
button_SelectSkel = new Button();
|
|
||||||
label_Tip = new Label();
|
|
||||||
openFileDialog_Skel = new OpenFileDialog();
|
|
||||||
panel.SuspendLayout();
|
panel.SuspendLayout();
|
||||||
tableLayoutPanel1.SuspendLayout();
|
tableLayoutPanel1.SuspendLayout();
|
||||||
tableLayoutPanel2.SuspendLayout();
|
tableLayoutPanel2.SuspendLayout();
|
||||||
@@ -53,7 +50,7 @@
|
|||||||
panel.Location = new Point(0, 0);
|
panel.Location = new Point(0, 0);
|
||||||
panel.Name = "panel";
|
panel.Name = "panel";
|
||||||
panel.Padding = new Padding(50, 15, 50, 10);
|
panel.Padding = new Padding(50, 15, 50, 10);
|
||||||
panel.Size = new Size(1126, 449);
|
panel.Size = new Size(1042, 472);
|
||||||
panel.TabIndex = 1;
|
panel.TabIndex = 1;
|
||||||
//
|
//
|
||||||
// tableLayoutPanel1
|
// tableLayoutPanel1
|
||||||
@@ -62,22 +59,19 @@
|
|||||||
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle());
|
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle());
|
||||||
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
||||||
tableLayoutPanel1.Controls.Add(label4, 0, 0);
|
tableLayoutPanel1.Controls.Add(label4, 0, 0);
|
||||||
tableLayoutPanel1.Controls.Add(label3, 0, 3);
|
tableLayoutPanel1.Controls.Add(label3, 0, 2);
|
||||||
tableLayoutPanel1.Controls.Add(comboBox_Version, 1, 3);
|
tableLayoutPanel1.Controls.Add(comboBox_Version, 1, 2);
|
||||||
tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 4);
|
tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 3);
|
||||||
tableLayoutPanel1.Controls.Add(listBox_FilePath, 0, 2);
|
tableLayoutPanel1.Controls.Add(skelFileListBox, 0, 1);
|
||||||
tableLayoutPanel1.Controls.Add(button_SelectSkel, 0, 1);
|
|
||||||
tableLayoutPanel1.Controls.Add(label_Tip, 1, 1);
|
|
||||||
tableLayoutPanel1.Dock = DockStyle.Fill;
|
tableLayoutPanel1.Dock = DockStyle.Fill;
|
||||||
tableLayoutPanel1.Location = new Point(50, 15);
|
tableLayoutPanel1.Location = new Point(50, 15);
|
||||||
tableLayoutPanel1.Name = "tableLayoutPanel1";
|
tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||||
tableLayoutPanel1.RowCount = 5;
|
tableLayoutPanel1.RowCount = 3;
|
||||||
|
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
||||||
|
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
tableLayoutPanel1.Size = new Size(942, 447);
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
|
||||||
tableLayoutPanel1.Size = new Size(1026, 424);
|
|
||||||
tableLayoutPanel1.TabIndex = 1;
|
tableLayoutPanel1.TabIndex = 1;
|
||||||
//
|
//
|
||||||
// label4
|
// label4
|
||||||
@@ -88,7 +82,7 @@
|
|||||||
label4.Location = new Point(15, 15);
|
label4.Location = new Point(15, 15);
|
||||||
label4.Margin = new Padding(15);
|
label4.Margin = new Padding(15);
|
||||||
label4.Name = "label4";
|
label4.Name = "label4";
|
||||||
label4.Size = new Size(996, 24);
|
label4.Size = new Size(912, 24);
|
||||||
label4.TabIndex = 14;
|
label4.TabIndex = 14;
|
||||||
label4.Text = "说明:批量导入只需要选择skel文件,atlas文件需要在同目录下并且与skel文件名相同";
|
label4.Text = "说明:批量导入只需要选择skel文件,atlas文件需要在同目录下并且与skel文件名相同";
|
||||||
label4.TextAlign = ContentAlignment.MiddleCenter;
|
label4.TextAlign = ContentAlignment.MiddleCenter;
|
||||||
@@ -97,7 +91,7 @@
|
|||||||
//
|
//
|
||||||
label3.Anchor = AnchorStyles.Right;
|
label3.Anchor = AnchorStyles.Right;
|
||||||
label3.AutoSize = true;
|
label3.AutoSize = true;
|
||||||
label3.Location = new Point(90, 307);
|
label3.Location = new Point(3, 343);
|
||||||
label3.Name = "label3";
|
label3.Name = "label3";
|
||||||
label3.Size = new Size(50, 24);
|
label3.Size = new Size(50, 24);
|
||||||
label3.TabIndex = 12;
|
label3.TabIndex = 12;
|
||||||
@@ -108,7 +102,7 @@
|
|||||||
comboBox_Version.Anchor = AnchorStyles.Left;
|
comboBox_Version.Anchor = AnchorStyles.Left;
|
||||||
comboBox_Version.DropDownStyle = ComboBoxStyle.DropDownList;
|
comboBox_Version.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||||
comboBox_Version.FormattingEnabled = true;
|
comboBox_Version.FormattingEnabled = true;
|
||||||
comboBox_Version.Location = new Point(146, 303);
|
comboBox_Version.Location = new Point(59, 339);
|
||||||
comboBox_Version.Name = "comboBox_Version";
|
comboBox_Version.Name = "comboBox_Version";
|
||||||
comboBox_Version.Size = new Size(182, 32);
|
comboBox_Version.Size = new Size(182, 32);
|
||||||
comboBox_Version.Sorted = true;
|
comboBox_Version.Sorted = true;
|
||||||
@@ -124,18 +118,19 @@
|
|||||||
tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
|
tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
|
||||||
tableLayoutPanel2.Controls.Add(button_Ok, 0, 0);
|
tableLayoutPanel2.Controls.Add(button_Ok, 0, 0);
|
||||||
tableLayoutPanel2.Controls.Add(button_Cancel, 1, 0);
|
tableLayoutPanel2.Controls.Add(button_Cancel, 1, 0);
|
||||||
tableLayoutPanel2.Dock = DockStyle.Bottom;
|
tableLayoutPanel2.Dock = DockStyle.Fill;
|
||||||
tableLayoutPanel2.Location = new Point(3, 381);
|
tableLayoutPanel2.Location = new Point(3, 404);
|
||||||
|
tableLayoutPanel2.Margin = new Padding(3, 30, 3, 3);
|
||||||
tableLayoutPanel2.Name = "tableLayoutPanel2";
|
tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||||
tableLayoutPanel2.RowCount = 1;
|
tableLayoutPanel2.RowCount = 1;
|
||||||
tableLayoutPanel2.RowStyles.Add(new RowStyle());
|
tableLayoutPanel2.RowStyles.Add(new RowStyle());
|
||||||
tableLayoutPanel2.Size = new Size(1020, 40);
|
tableLayoutPanel2.Size = new Size(936, 40);
|
||||||
tableLayoutPanel2.TabIndex = 11;
|
tableLayoutPanel2.TabIndex = 11;
|
||||||
//
|
//
|
||||||
// button_Ok
|
// button_Ok
|
||||||
//
|
//
|
||||||
button_Ok.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
button_Ok.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||||
button_Ok.Location = new Point(368, 3);
|
button_Ok.Location = new Point(326, 3);
|
||||||
button_Ok.Margin = new Padding(3, 3, 30, 3);
|
button_Ok.Margin = new Padding(3, 3, 30, 3);
|
||||||
button_Ok.Name = "button_Ok";
|
button_Ok.Name = "button_Ok";
|
||||||
button_Ok.Size = new Size(112, 34);
|
button_Ok.Size = new Size(112, 34);
|
||||||
@@ -147,7 +142,7 @@
|
|||||||
// button_Cancel
|
// button_Cancel
|
||||||
//
|
//
|
||||||
button_Cancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
|
button_Cancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
|
||||||
button_Cancel.Location = new Point(540, 3);
|
button_Cancel.Location = new Point(498, 3);
|
||||||
button_Cancel.Margin = new Padding(30, 3, 3, 3);
|
button_Cancel.Margin = new Padding(30, 3, 3, 3);
|
||||||
button_Cancel.Name = "button_Cancel";
|
button_Cancel.Name = "button_Cancel";
|
||||||
button_Cancel.Size = new Size(112, 34);
|
button_Cancel.Size = new Size(112, 34);
|
||||||
@@ -156,47 +151,14 @@
|
|||||||
button_Cancel.UseVisualStyleBackColor = true;
|
button_Cancel.UseVisualStyleBackColor = true;
|
||||||
button_Cancel.Click += button_Cancel_Click;
|
button_Cancel.Click += button_Cancel_Click;
|
||||||
//
|
//
|
||||||
// listBox_FilePath
|
// skelFileListBox
|
||||||
//
|
//
|
||||||
tableLayoutPanel1.SetColumnSpan(listBox_FilePath, 2);
|
tableLayoutPanel1.SetColumnSpan(skelFileListBox, 2);
|
||||||
listBox_FilePath.Dock = DockStyle.Fill;
|
skelFileListBox.Dock = DockStyle.Fill;
|
||||||
listBox_FilePath.FormattingEnabled = true;
|
skelFileListBox.Location = new Point(3, 57);
|
||||||
listBox_FilePath.HorizontalScrollbar = true;
|
skelFileListBox.Name = "skelFileListBox";
|
||||||
listBox_FilePath.ItemHeight = 24;
|
skelFileListBox.Size = new Size(936, 276);
|
||||||
listBox_FilePath.Location = new Point(3, 97);
|
skelFileListBox.TabIndex = 15;
|
||||||
listBox_FilePath.Name = "listBox_FilePath";
|
|
||||||
listBox_FilePath.Size = new Size(1020, 200);
|
|
||||||
listBox_FilePath.TabIndex = 2;
|
|
||||||
//
|
|
||||||
// button_SelectSkel
|
|
||||||
//
|
|
||||||
button_SelectSkel.Anchor = AnchorStyles.None;
|
|
||||||
button_SelectSkel.Location = new Point(3, 57);
|
|
||||||
button_SelectSkel.Name = "button_SelectSkel";
|
|
||||||
button_SelectSkel.Size = new Size(137, 34);
|
|
||||||
button_SelectSkel.TabIndex = 1;
|
|
||||||
button_SelectSkel.Text = "选择文件...";
|
|
||||||
button_SelectSkel.UseVisualStyleBackColor = true;
|
|
||||||
button_SelectSkel.Click += button_SelectSkel_Click;
|
|
||||||
//
|
|
||||||
// label_Tip
|
|
||||||
//
|
|
||||||
label_Tip.AutoSize = true;
|
|
||||||
label_Tip.Dock = DockStyle.Fill;
|
|
||||||
label_Tip.Location = new Point(146, 54);
|
|
||||||
label_Tip.Name = "label_Tip";
|
|
||||||
label_Tip.Size = new Size(877, 40);
|
|
||||||
label_Tip.TabIndex = 0;
|
|
||||||
label_Tip.Text = "已选择 0 个文件";
|
|
||||||
label_Tip.TextAlign = ContentAlignment.MiddleLeft;
|
|
||||||
//
|
|
||||||
// openFileDialog_Skel
|
|
||||||
//
|
|
||||||
openFileDialog_Skel.AddExtension = false;
|
|
||||||
openFileDialog_Skel.AddToRecent = false;
|
|
||||||
openFileDialog_Skel.Filter = "skel 文件 (*.skel; *.json)|*.skel;*.json|二进制文件 (*.skel)|*.skel|文本文件 (*.json)|*.json|所有文件 (*.*)|*.*";
|
|
||||||
openFileDialog_Skel.Multiselect = true;
|
|
||||||
openFileDialog_Skel.Title = "批量选择skel文件";
|
|
||||||
//
|
//
|
||||||
// BatchOpenSpineDialog
|
// BatchOpenSpineDialog
|
||||||
//
|
//
|
||||||
@@ -204,7 +166,7 @@
|
|||||||
AutoScaleDimensions = new SizeF(11F, 24F);
|
AutoScaleDimensions = new SizeF(11F, 24F);
|
||||||
AutoScaleMode = AutoScaleMode.Font;
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
CancelButton = button_Cancel;
|
CancelButton = button_Cancel;
|
||||||
ClientSize = new Size(1126, 449);
|
ClientSize = new Size(1042, 472);
|
||||||
Controls.Add(panel);
|
Controls.Add(panel);
|
||||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||||
Icon = (Icon)resources.GetObject("$this.Icon");
|
Icon = (Icon)resources.GetObject("$this.Icon");
|
||||||
@@ -214,7 +176,6 @@
|
|||||||
ShowInTaskbar = false;
|
ShowInTaskbar = false;
|
||||||
StartPosition = FormStartPosition.CenterScreen;
|
StartPosition = FormStartPosition.CenterScreen;
|
||||||
Text = "批量打开骨骼";
|
Text = "批量打开骨骼";
|
||||||
Load += BatchOpenSpineDialog_Load;
|
|
||||||
panel.ResumeLayout(false);
|
panel.ResumeLayout(false);
|
||||||
tableLayoutPanel1.ResumeLayout(false);
|
tableLayoutPanel1.ResumeLayout(false);
|
||||||
tableLayoutPanel1.PerformLayout();
|
tableLayoutPanel1.PerformLayout();
|
||||||
@@ -225,15 +186,12 @@
|
|||||||
#endregion
|
#endregion
|
||||||
private Panel panel;
|
private Panel panel;
|
||||||
private TableLayoutPanel tableLayoutPanel1;
|
private TableLayoutPanel tableLayoutPanel1;
|
||||||
private Label label_Tip;
|
|
||||||
private ListBox listBox_FilePath;
|
|
||||||
private Button button_SelectSkel;
|
|
||||||
private TableLayoutPanel tableLayoutPanel2;
|
private TableLayoutPanel tableLayoutPanel2;
|
||||||
private Button button_Ok;
|
private Button button_Ok;
|
||||||
private Button button_Cancel;
|
private Button button_Cancel;
|
||||||
private Label label3;
|
private Label label3;
|
||||||
private ComboBox comboBox_Version;
|
private ComboBox comboBox_Version;
|
||||||
private OpenFileDialog openFileDialog_Skel;
|
|
||||||
private Label label4;
|
private Label label4;
|
||||||
|
private Controls.SkelFileListBox skelFileListBox;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,33 +27,19 @@ namespace SpineViewer.Dialogs
|
|||||||
comboBox_Version.SelectedValue = Spine.Version.Auto;
|
comboBox_Version.SelectedValue = Spine.Version.Auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BatchOpenSpineDialog_Load(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
button_SelectSkel_Click(sender, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void button_SelectSkel_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (openFileDialog_Skel.ShowDialog() == DialogResult.OK)
|
|
||||||
{
|
|
||||||
listBox_FilePath.Items.Clear();
|
|
||||||
foreach (var p in openFileDialog_Skel.FileNames)
|
|
||||||
listBox_FilePath.Items.Add(Path.GetFullPath(p));
|
|
||||||
label_Tip.Text = $"已选择 {listBox_FilePath.Items.Count} 个文件";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void button_Ok_Click(object sender, EventArgs e)
|
private void button_Ok_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var version = (Spine.Version)comboBox_Version.SelectedValue;
|
var version = (Spine.Version)comboBox_Version.SelectedValue;
|
||||||
|
|
||||||
if (listBox_FilePath.Items.Count <= 0)
|
var items = skelFileListBox.Items;
|
||||||
|
|
||||||
|
if (items.Count <= 0)
|
||||||
{
|
{
|
||||||
MessageBox.Info("未选择任何文件");
|
MessageBox.Info("未选择任何文件");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (string p in listBox_FilePath.Items)
|
foreach (string p in items)
|
||||||
{
|
{
|
||||||
if (!File.Exists(p))
|
if (!File.Exists(p))
|
||||||
{
|
{
|
||||||
@@ -68,7 +54,7 @@ namespace SpineViewer.Dialogs
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = new(version, listBox_FilePath.Items.Cast<string>().ToArray());
|
Result = new(version, items.Cast<string>().ToArray());
|
||||||
DialogResult = DialogResult.OK;
|
DialogResult = DialogResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,9 +117,6 @@
|
|||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<metadata name="openFileDialog_Skel.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>92, 26</value>
|
|
||||||
</metadata>
|
|
||||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
|
|||||||
171
SpineViewer/Dialogs/ConvertFileFormatDialog.Designer.cs
generated
171
SpineViewer/Dialogs/ConvertFileFormatDialog.Designer.cs
generated
@@ -31,6 +31,7 @@
|
|||||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ConvertFileFormatDialog));
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ConvertFileFormatDialog));
|
||||||
panel = new Panel();
|
panel = new Panel();
|
||||||
tableLayoutPanel1 = new TableLayoutPanel();
|
tableLayoutPanel1 = new TableLayoutPanel();
|
||||||
|
comboBox_TargetVersion = new ComboBox();
|
||||||
flowLayoutPanel_TargetFormat = new FlowLayoutPanel();
|
flowLayoutPanel_TargetFormat = new FlowLayoutPanel();
|
||||||
radioButton_BinaryTarget = new RadioButton();
|
radioButton_BinaryTarget = new RadioButton();
|
||||||
radioButton_JsonTarget = new RadioButton();
|
radioButton_JsonTarget = new RadioButton();
|
||||||
@@ -41,19 +42,13 @@
|
|||||||
tableLayoutPanel2 = new TableLayoutPanel();
|
tableLayoutPanel2 = new TableLayoutPanel();
|
||||||
button_Ok = new Button();
|
button_Ok = new Button();
|
||||||
button_Cancel = new Button();
|
button_Cancel = new Button();
|
||||||
listBox_FilePath = new ListBox();
|
|
||||||
button_SelectSkel = new Button();
|
|
||||||
label_Tip = new Label();
|
|
||||||
label2 = new Label();
|
label2 = new Label();
|
||||||
flowLayoutPanel_SourceFormat = new FlowLayoutPanel();
|
skelFileListBox = new SpineViewer.Controls.SkelFileListBox();
|
||||||
radioButton_BinarySource = new RadioButton();
|
|
||||||
radioButton_JsonSource = new RadioButton();
|
|
||||||
openFileDialog_Skel = new OpenFileDialog();
|
openFileDialog_Skel = new OpenFileDialog();
|
||||||
panel.SuspendLayout();
|
panel.SuspendLayout();
|
||||||
tableLayoutPanel1.SuspendLayout();
|
tableLayoutPanel1.SuspendLayout();
|
||||||
flowLayoutPanel_TargetFormat.SuspendLayout();
|
flowLayoutPanel_TargetFormat.SuspendLayout();
|
||||||
tableLayoutPanel2.SuspendLayout();
|
tableLayoutPanel2.SuspendLayout();
|
||||||
flowLayoutPanel_SourceFormat.SuspendLayout();
|
|
||||||
SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// panel
|
// panel
|
||||||
@@ -63,7 +58,7 @@
|
|||||||
panel.Location = new Point(0, 0);
|
panel.Location = new Point(0, 0);
|
||||||
panel.Name = "panel";
|
panel.Name = "panel";
|
||||||
panel.Padding = new Padding(50, 15, 50, 10);
|
panel.Padding = new Padding(50, 15, 50, 10);
|
||||||
panel.Size = new Size(1039, 530);
|
panel.Size = new Size(1051, 538);
|
||||||
panel.TabIndex = 2;
|
panel.TabIndex = 2;
|
||||||
//
|
//
|
||||||
// tableLayoutPanel1
|
// tableLayoutPanel1
|
||||||
@@ -71,40 +66,48 @@
|
|||||||
tableLayoutPanel1.ColumnCount = 2;
|
tableLayoutPanel1.ColumnCount = 2;
|
||||||
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle());
|
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle());
|
||||||
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
||||||
tableLayoutPanel1.Controls.Add(flowLayoutPanel_TargetFormat, 1, 5);
|
tableLayoutPanel1.Controls.Add(comboBox_TargetVersion, 1, 3);
|
||||||
tableLayoutPanel1.Controls.Add(label1, 0, 4);
|
tableLayoutPanel1.Controls.Add(flowLayoutPanel_TargetFormat, 1, 4);
|
||||||
|
tableLayoutPanel1.Controls.Add(label1, 0, 3);
|
||||||
tableLayoutPanel1.Controls.Add(label4, 0, 0);
|
tableLayoutPanel1.Controls.Add(label4, 0, 0);
|
||||||
tableLayoutPanel1.Controls.Add(label3, 0, 3);
|
tableLayoutPanel1.Controls.Add(label3, 0, 2);
|
||||||
tableLayoutPanel1.Controls.Add(comboBox_SourceVersion, 1, 3);
|
tableLayoutPanel1.Controls.Add(comboBox_SourceVersion, 1, 2);
|
||||||
tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 6);
|
tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 5);
|
||||||
tableLayoutPanel1.Controls.Add(listBox_FilePath, 0, 2);
|
tableLayoutPanel1.Controls.Add(label2, 0, 4);
|
||||||
tableLayoutPanel1.Controls.Add(button_SelectSkel, 0, 1);
|
tableLayoutPanel1.Controls.Add(skelFileListBox, 0, 1);
|
||||||
tableLayoutPanel1.Controls.Add(label_Tip, 1, 1);
|
|
||||||
tableLayoutPanel1.Controls.Add(label2, 0, 5);
|
|
||||||
tableLayoutPanel1.Controls.Add(flowLayoutPanel_SourceFormat, 1, 4);
|
|
||||||
tableLayoutPanel1.Dock = DockStyle.Fill;
|
tableLayoutPanel1.Dock = DockStyle.Fill;
|
||||||
tableLayoutPanel1.Location = new Point(50, 15);
|
tableLayoutPanel1.Location = new Point(50, 15);
|
||||||
tableLayoutPanel1.Name = "tableLayoutPanel1";
|
tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||||
tableLayoutPanel1.RowCount = 7;
|
tableLayoutPanel1.RowCount = 6;
|
||||||
|
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
||||||
|
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
tableLayoutPanel1.Size = new Size(951, 513);
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
|
||||||
tableLayoutPanel1.Size = new Size(939, 505);
|
|
||||||
tableLayoutPanel1.TabIndex = 1;
|
tableLayoutPanel1.TabIndex = 1;
|
||||||
//
|
//
|
||||||
|
// comboBox_TargetVersion
|
||||||
|
//
|
||||||
|
comboBox_TargetVersion.Anchor = AnchorStyles.Left;
|
||||||
|
comboBox_TargetVersion.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||||
|
comboBox_TargetVersion.FormattingEnabled = true;
|
||||||
|
comboBox_TargetVersion.Location = new Point(95, 365);
|
||||||
|
comboBox_TargetVersion.Name = "comboBox_TargetVersion";
|
||||||
|
comboBox_TargetVersion.Size = new Size(182, 32);
|
||||||
|
comboBox_TargetVersion.Sorted = true;
|
||||||
|
comboBox_TargetVersion.TabIndex = 21;
|
||||||
|
//
|
||||||
// flowLayoutPanel_TargetFormat
|
// flowLayoutPanel_TargetFormat
|
||||||
//
|
//
|
||||||
flowLayoutPanel_TargetFormat.AutoSize = true;
|
flowLayoutPanel_TargetFormat.AutoSize = true;
|
||||||
flowLayoutPanel_TargetFormat.Controls.Add(radioButton_BinaryTarget);
|
flowLayoutPanel_TargetFormat.Controls.Add(radioButton_BinaryTarget);
|
||||||
flowLayoutPanel_TargetFormat.Controls.Add(radioButton_JsonTarget);
|
flowLayoutPanel_TargetFormat.Controls.Add(radioButton_JsonTarget);
|
||||||
flowLayoutPanel_TargetFormat.Dock = DockStyle.Fill;
|
flowLayoutPanel_TargetFormat.Dock = DockStyle.Fill;
|
||||||
flowLayoutPanel_TargetFormat.Location = new Point(146, 381);
|
flowLayoutPanel_TargetFormat.Location = new Point(95, 403);
|
||||||
flowLayoutPanel_TargetFormat.Name = "flowLayoutPanel_TargetFormat";
|
flowLayoutPanel_TargetFormat.Name = "flowLayoutPanel_TargetFormat";
|
||||||
flowLayoutPanel_TargetFormat.Size = new Size(790, 34);
|
flowLayoutPanel_TargetFormat.Size = new Size(853, 34);
|
||||||
flowLayoutPanel_TargetFormat.TabIndex = 19;
|
flowLayoutPanel_TargetFormat.TabIndex = 19;
|
||||||
//
|
//
|
||||||
// radioButton_BinaryTarget
|
// radioButton_BinaryTarget
|
||||||
@@ -116,7 +119,6 @@
|
|||||||
radioButton_BinaryTarget.TabIndex = 17;
|
radioButton_BinaryTarget.TabIndex = 17;
|
||||||
radioButton_BinaryTarget.Text = "二进制 (*.skel)";
|
radioButton_BinaryTarget.Text = "二进制 (*.skel)";
|
||||||
radioButton_BinaryTarget.UseVisualStyleBackColor = true;
|
radioButton_BinaryTarget.UseVisualStyleBackColor = true;
|
||||||
radioButton_BinaryTarget.CheckedChanged += radioButton_Target_CheckedChanged;
|
|
||||||
//
|
//
|
||||||
// radioButton_JsonTarget
|
// radioButton_JsonTarget
|
||||||
//
|
//
|
||||||
@@ -129,17 +131,16 @@
|
|||||||
radioButton_JsonTarget.TabStop = true;
|
radioButton_JsonTarget.TabStop = true;
|
||||||
radioButton_JsonTarget.Text = "文本 (*.json)";
|
radioButton_JsonTarget.Text = "文本 (*.json)";
|
||||||
radioButton_JsonTarget.UseVisualStyleBackColor = true;
|
radioButton_JsonTarget.UseVisualStyleBackColor = true;
|
||||||
radioButton_JsonTarget.CheckedChanged += radioButton_Target_CheckedChanged;
|
|
||||||
//
|
//
|
||||||
// label1
|
// label1
|
||||||
//
|
//
|
||||||
label1.Anchor = AnchorStyles.Right;
|
label1.Anchor = AnchorStyles.Right;
|
||||||
label1.AutoSize = true;
|
label1.AutoSize = true;
|
||||||
label1.Location = new Point(72, 346);
|
label1.Location = new Point(3, 369);
|
||||||
label1.Name = "label1";
|
label1.Name = "label1";
|
||||||
label1.Size = new Size(68, 24);
|
label1.Size = new Size(86, 24);
|
||||||
label1.TabIndex = 15;
|
label1.TabIndex = 15;
|
||||||
label1.Text = "源格式:";
|
label1.Text = "目标版本:";
|
||||||
//
|
//
|
||||||
// label4
|
// label4
|
||||||
//
|
//
|
||||||
@@ -149,7 +150,7 @@
|
|||||||
label4.Location = new Point(15, 15);
|
label4.Location = new Point(15, 15);
|
||||||
label4.Margin = new Padding(15);
|
label4.Margin = new Padding(15);
|
||||||
label4.Name = "label4";
|
label4.Name = "label4";
|
||||||
label4.Size = new Size(909, 24);
|
label4.Size = new Size(921, 24);
|
||||||
label4.TabIndex = 14;
|
label4.TabIndex = 14;
|
||||||
label4.Text = "说明:将在每个文件同级目录下生成目标格式后缀的文件,会覆盖已存在文件";
|
label4.Text = "说明:将在每个文件同级目录下生成目标格式后缀的文件,会覆盖已存在文件";
|
||||||
label4.TextAlign = ContentAlignment.MiddleCenter;
|
label4.TextAlign = ContentAlignment.MiddleCenter;
|
||||||
@@ -158,19 +159,19 @@
|
|||||||
//
|
//
|
||||||
label3.Anchor = AnchorStyles.Right;
|
label3.Anchor = AnchorStyles.Right;
|
||||||
label3.AutoSize = true;
|
label3.AutoSize = true;
|
||||||
label3.Location = new Point(72, 307);
|
label3.Location = new Point(21, 331);
|
||||||
label3.Name = "label3";
|
label3.Name = "label3";
|
||||||
label3.Size = new Size(68, 24);
|
label3.Size = new Size(68, 24);
|
||||||
label3.TabIndex = 12;
|
label3.TabIndex = 12;
|
||||||
label3.Text = "源版本:";
|
label3.Text = "源版本:";
|
||||||
//
|
//
|
||||||
// comboBox_Version
|
// comboBox_SourceVersion
|
||||||
//
|
//
|
||||||
comboBox_SourceVersion.Anchor = AnchorStyles.Left;
|
comboBox_SourceVersion.Anchor = AnchorStyles.Left;
|
||||||
comboBox_SourceVersion.DropDownStyle = ComboBoxStyle.DropDownList;
|
comboBox_SourceVersion.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||||
comboBox_SourceVersion.FormattingEnabled = true;
|
comboBox_SourceVersion.FormattingEnabled = true;
|
||||||
comboBox_SourceVersion.Location = new Point(146, 303);
|
comboBox_SourceVersion.Location = new Point(95, 327);
|
||||||
comboBox_SourceVersion.Name = "comboBox_Version";
|
comboBox_SourceVersion.Name = "comboBox_SourceVersion";
|
||||||
comboBox_SourceVersion.Size = new Size(182, 32);
|
comboBox_SourceVersion.Size = new Size(182, 32);
|
||||||
comboBox_SourceVersion.Sorted = true;
|
comboBox_SourceVersion.Sorted = true;
|
||||||
comboBox_SourceVersion.TabIndex = 13;
|
comboBox_SourceVersion.TabIndex = 13;
|
||||||
@@ -185,18 +186,19 @@
|
|||||||
tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
|
tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
|
||||||
tableLayoutPanel2.Controls.Add(button_Ok, 0, 0);
|
tableLayoutPanel2.Controls.Add(button_Ok, 0, 0);
|
||||||
tableLayoutPanel2.Controls.Add(button_Cancel, 1, 0);
|
tableLayoutPanel2.Controls.Add(button_Cancel, 1, 0);
|
||||||
tableLayoutPanel2.Dock = DockStyle.Bottom;
|
tableLayoutPanel2.Dock = DockStyle.Fill;
|
||||||
tableLayoutPanel2.Location = new Point(3, 462);
|
tableLayoutPanel2.Location = new Point(3, 470);
|
||||||
|
tableLayoutPanel2.Margin = new Padding(3, 30, 3, 3);
|
||||||
tableLayoutPanel2.Name = "tableLayoutPanel2";
|
tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||||
tableLayoutPanel2.RowCount = 1;
|
tableLayoutPanel2.RowCount = 1;
|
||||||
tableLayoutPanel2.RowStyles.Add(new RowStyle());
|
tableLayoutPanel2.RowStyles.Add(new RowStyle());
|
||||||
tableLayoutPanel2.Size = new Size(933, 40);
|
tableLayoutPanel2.Size = new Size(945, 40);
|
||||||
tableLayoutPanel2.TabIndex = 11;
|
tableLayoutPanel2.TabIndex = 11;
|
||||||
//
|
//
|
||||||
// button_Ok
|
// button_Ok
|
||||||
//
|
//
|
||||||
button_Ok.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
button_Ok.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||||
button_Ok.Location = new Point(324, 3);
|
button_Ok.Location = new Point(330, 3);
|
||||||
button_Ok.Margin = new Padding(3, 3, 30, 3);
|
button_Ok.Margin = new Padding(3, 3, 30, 3);
|
||||||
button_Ok.Name = "button_Ok";
|
button_Ok.Name = "button_Ok";
|
||||||
button_Ok.Size = new Size(112, 34);
|
button_Ok.Size = new Size(112, 34);
|
||||||
@@ -208,7 +210,7 @@
|
|||||||
// button_Cancel
|
// button_Cancel
|
||||||
//
|
//
|
||||||
button_Cancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
|
button_Cancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
|
||||||
button_Cancel.Location = new Point(496, 3);
|
button_Cancel.Location = new Point(502, 3);
|
||||||
button_Cancel.Margin = new Padding(30, 3, 3, 3);
|
button_Cancel.Margin = new Padding(30, 3, 3, 3);
|
||||||
button_Cancel.Name = "button_Cancel";
|
button_Cancel.Name = "button_Cancel";
|
||||||
button_Cancel.Size = new Size(112, 34);
|
button_Cancel.Size = new Size(112, 34);
|
||||||
@@ -217,84 +219,24 @@
|
|||||||
button_Cancel.UseVisualStyleBackColor = true;
|
button_Cancel.UseVisualStyleBackColor = true;
|
||||||
button_Cancel.Click += button_Cancel_Click;
|
button_Cancel.Click += button_Cancel_Click;
|
||||||
//
|
//
|
||||||
// listBox_FilePath
|
|
||||||
//
|
|
||||||
tableLayoutPanel1.SetColumnSpan(listBox_FilePath, 2);
|
|
||||||
listBox_FilePath.Dock = DockStyle.Fill;
|
|
||||||
listBox_FilePath.FormattingEnabled = true;
|
|
||||||
listBox_FilePath.HorizontalScrollbar = true;
|
|
||||||
listBox_FilePath.ItemHeight = 24;
|
|
||||||
listBox_FilePath.Location = new Point(3, 97);
|
|
||||||
listBox_FilePath.Name = "listBox_FilePath";
|
|
||||||
listBox_FilePath.Size = new Size(933, 200);
|
|
||||||
listBox_FilePath.TabIndex = 2;
|
|
||||||
//
|
|
||||||
// button_SelectSkel
|
|
||||||
//
|
|
||||||
button_SelectSkel.Anchor = AnchorStyles.None;
|
|
||||||
button_SelectSkel.Location = new Point(3, 57);
|
|
||||||
button_SelectSkel.Name = "button_SelectSkel";
|
|
||||||
button_SelectSkel.Size = new Size(137, 34);
|
|
||||||
button_SelectSkel.TabIndex = 1;
|
|
||||||
button_SelectSkel.Text = "选择文件...";
|
|
||||||
button_SelectSkel.UseVisualStyleBackColor = true;
|
|
||||||
button_SelectSkel.Click += button_SelectSkel_Click;
|
|
||||||
//
|
|
||||||
// label_Tip
|
|
||||||
//
|
|
||||||
label_Tip.AutoSize = true;
|
|
||||||
label_Tip.Dock = DockStyle.Fill;
|
|
||||||
label_Tip.Location = new Point(146, 54);
|
|
||||||
label_Tip.Name = "label_Tip";
|
|
||||||
label_Tip.Size = new Size(790, 40);
|
|
||||||
label_Tip.TabIndex = 0;
|
|
||||||
label_Tip.Text = "已选择 0 个文件";
|
|
||||||
label_Tip.TextAlign = ContentAlignment.MiddleLeft;
|
|
||||||
//
|
|
||||||
// label2
|
// label2
|
||||||
//
|
//
|
||||||
label2.Anchor = AnchorStyles.Right;
|
label2.Anchor = AnchorStyles.Right;
|
||||||
label2.AutoSize = true;
|
label2.AutoSize = true;
|
||||||
label2.Location = new Point(54, 386);
|
label2.Location = new Point(3, 408);
|
||||||
label2.Name = "label2";
|
label2.Name = "label2";
|
||||||
label2.Size = new Size(86, 24);
|
label2.Size = new Size(86, 24);
|
||||||
label2.TabIndex = 16;
|
label2.TabIndex = 16;
|
||||||
label2.Text = "目标格式:";
|
label2.Text = "目标格式:";
|
||||||
//
|
//
|
||||||
// flowLayoutPanel_SourceFormat
|
// skelFileListBox
|
||||||
//
|
//
|
||||||
flowLayoutPanel_SourceFormat.AutoSize = true;
|
tableLayoutPanel1.SetColumnSpan(skelFileListBox, 2);
|
||||||
flowLayoutPanel_SourceFormat.Controls.Add(radioButton_BinarySource);
|
skelFileListBox.Dock = DockStyle.Fill;
|
||||||
flowLayoutPanel_SourceFormat.Controls.Add(radioButton_JsonSource);
|
skelFileListBox.Location = new Point(3, 57);
|
||||||
flowLayoutPanel_SourceFormat.Dock = DockStyle.Fill;
|
skelFileListBox.Name = "skelFileListBox";
|
||||||
flowLayoutPanel_SourceFormat.Location = new Point(146, 341);
|
skelFileListBox.Size = new Size(945, 264);
|
||||||
flowLayoutPanel_SourceFormat.Name = "flowLayoutPanel_SourceFormat";
|
skelFileListBox.TabIndex = 20;
|
||||||
flowLayoutPanel_SourceFormat.Size = new Size(790, 34);
|
|
||||||
flowLayoutPanel_SourceFormat.TabIndex = 18;
|
|
||||||
//
|
|
||||||
// radioButton_BinarySource
|
|
||||||
//
|
|
||||||
radioButton_BinarySource.AutoSize = true;
|
|
||||||
radioButton_BinarySource.Checked = true;
|
|
||||||
radioButton_BinarySource.Location = new Point(3, 3);
|
|
||||||
radioButton_BinarySource.Name = "radioButton_BinarySource";
|
|
||||||
radioButton_BinarySource.Size = new Size(151, 28);
|
|
||||||
radioButton_BinarySource.TabIndex = 17;
|
|
||||||
radioButton_BinarySource.TabStop = true;
|
|
||||||
radioButton_BinarySource.Text = "二进制 (*.skel)";
|
|
||||||
radioButton_BinarySource.UseVisualStyleBackColor = true;
|
|
||||||
radioButton_BinarySource.CheckedChanged += radioButton_Source_CheckedChanged;
|
|
||||||
//
|
|
||||||
// radioButton_JsonSource
|
|
||||||
//
|
|
||||||
radioButton_JsonSource.AutoSize = true;
|
|
||||||
radioButton_JsonSource.Location = new Point(160, 3);
|
|
||||||
radioButton_JsonSource.Name = "radioButton_JsonSource";
|
|
||||||
radioButton_JsonSource.Size = new Size(135, 28);
|
|
||||||
radioButton_JsonSource.TabIndex = 18;
|
|
||||||
radioButton_JsonSource.Text = "文本 (*.json)";
|
|
||||||
radioButton_JsonSource.UseVisualStyleBackColor = true;
|
|
||||||
radioButton_JsonSource.CheckedChanged += radioButton_Source_CheckedChanged;
|
|
||||||
//
|
//
|
||||||
// openFileDialog_Skel
|
// openFileDialog_Skel
|
||||||
//
|
//
|
||||||
@@ -310,7 +252,7 @@
|
|||||||
AutoScaleDimensions = new SizeF(11F, 24F);
|
AutoScaleDimensions = new SizeF(11F, 24F);
|
||||||
AutoScaleMode = AutoScaleMode.Font;
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
CancelButton = button_Cancel;
|
CancelButton = button_Cancel;
|
||||||
ClientSize = new Size(1039, 530);
|
ClientSize = new Size(1051, 538);
|
||||||
Controls.Add(panel);
|
Controls.Add(panel);
|
||||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||||
Icon = (Icon)resources.GetObject("$this.Icon");
|
Icon = (Icon)resources.GetObject("$this.Icon");
|
||||||
@@ -320,15 +262,12 @@
|
|||||||
ShowInTaskbar = false;
|
ShowInTaskbar = false;
|
||||||
StartPosition = FormStartPosition.CenterScreen;
|
StartPosition = FormStartPosition.CenterScreen;
|
||||||
Text = "骨骼文件格式转换";
|
Text = "骨骼文件格式转换";
|
||||||
Load += ConvertFileFormatDialog_Load;
|
|
||||||
panel.ResumeLayout(false);
|
panel.ResumeLayout(false);
|
||||||
tableLayoutPanel1.ResumeLayout(false);
|
tableLayoutPanel1.ResumeLayout(false);
|
||||||
tableLayoutPanel1.PerformLayout();
|
tableLayoutPanel1.PerformLayout();
|
||||||
flowLayoutPanel_TargetFormat.ResumeLayout(false);
|
flowLayoutPanel_TargetFormat.ResumeLayout(false);
|
||||||
flowLayoutPanel_TargetFormat.PerformLayout();
|
flowLayoutPanel_TargetFormat.PerformLayout();
|
||||||
tableLayoutPanel2.ResumeLayout(false);
|
tableLayoutPanel2.ResumeLayout(false);
|
||||||
flowLayoutPanel_SourceFormat.ResumeLayout(false);
|
|
||||||
flowLayoutPanel_SourceFormat.PerformLayout();
|
|
||||||
ResumeLayout(false);
|
ResumeLayout(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,17 +281,13 @@
|
|||||||
private TableLayoutPanel tableLayoutPanel2;
|
private TableLayoutPanel tableLayoutPanel2;
|
||||||
private Button button_Ok;
|
private Button button_Ok;
|
||||||
private Button button_Cancel;
|
private Button button_Cancel;
|
||||||
private ListBox listBox_FilePath;
|
|
||||||
private Button button_SelectSkel;
|
|
||||||
private Label label_Tip;
|
|
||||||
private OpenFileDialog openFileDialog_Skel;
|
private OpenFileDialog openFileDialog_Skel;
|
||||||
private Label label1;
|
private Label label1;
|
||||||
private Label label2;
|
private Label label2;
|
||||||
private RadioButton radioButton_BinarySource;
|
|
||||||
private FlowLayoutPanel flowLayoutPanel_SourceFormat;
|
|
||||||
private RadioButton radioButton_JsonSource;
|
|
||||||
private FlowLayoutPanel flowLayoutPanel_TargetFormat;
|
private FlowLayoutPanel flowLayoutPanel_TargetFormat;
|
||||||
private RadioButton radioButton_BinaryTarget;
|
private RadioButton radioButton_BinaryTarget;
|
||||||
private RadioButton radioButton_JsonTarget;
|
private RadioButton radioButton_JsonTarget;
|
||||||
|
private Controls.SkelFileListBox skelFileListBox;
|
||||||
|
private ComboBox comboBox_TargetVersion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,62 +13,44 @@ namespace SpineViewer.Dialogs
|
|||||||
{
|
{
|
||||||
public partial class ConvertFileFormatDialog : Form
|
public partial class ConvertFileFormatDialog : Form
|
||||||
{
|
{
|
||||||
// TODO: 增加版本转换选项
|
/// <summary>
|
||||||
// TODO: 使用结果包装类
|
/// 对话框结果, 取消时为 null
|
||||||
public string[] SkelPaths { get; private set; }
|
/// </summary>
|
||||||
public Spine.Version SourceVersion { get; private set; }
|
public ConvertFileFormatDialogResult Result { get; private set; }
|
||||||
public Spine.Version TargetVersion { get; private set; }
|
|
||||||
public bool JsonSource { get; private set; }
|
|
||||||
public bool JsonTarget { get; private set; }
|
|
||||||
|
|
||||||
public ConvertFileFormatDialog()
|
public ConvertFileFormatDialog()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
// XXX: 文件格式转换暂时不支持自动检测版本
|
comboBox_SourceVersion.DataSource = VersionHelper.Names.ToList();
|
||||||
var impVersions = VersionHelper.Names.ToDictionary();
|
|
||||||
impVersions.Remove(Spine.Version.Auto);
|
|
||||||
|
|
||||||
comboBox_SourceVersion.DataSource = impVersions.ToList();
|
|
||||||
comboBox_SourceVersion.DisplayMember = "Value";
|
comboBox_SourceVersion.DisplayMember = "Value";
|
||||||
comboBox_SourceVersion.ValueMember = "Key";
|
comboBox_SourceVersion.ValueMember = "Key";
|
||||||
comboBox_SourceVersion.SelectedValue = Spine.Version.V38;
|
comboBox_SourceVersion.SelectedValue = Spine.Version.Auto;
|
||||||
//comboBox_TargetVersion.DataSource = VersionHelper.Versions.ToList();
|
|
||||||
//comboBox_TargetVersion.DisplayMember = "Value";
|
|
||||||
//comboBox_TargetVersion.ValueMember = "Key";
|
|
||||||
//comboBox_TargetVersion.SelectedValue = Spine.Version.V38;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConvertFileFormatDialog_Load(object sender, EventArgs e)
|
// 目标版本不包含自动
|
||||||
{
|
var versionsWithoutAuto = VersionHelper.Names.ToDictionary();
|
||||||
button_SelectSkel_Click(sender, e);
|
versionsWithoutAuto.Remove(Spine.Version.Auto);
|
||||||
}
|
comboBox_TargetVersion.DataSource = versionsWithoutAuto.ToList();
|
||||||
|
comboBox_TargetVersion.DisplayMember = "Value";
|
||||||
private void button_SelectSkel_Click(object sender, EventArgs e)
|
comboBox_TargetVersion.ValueMember = "Key";
|
||||||
{
|
comboBox_TargetVersion.SelectedValue = Spine.Version.V38;
|
||||||
if (openFileDialog_Skel.ShowDialog() == DialogResult.OK)
|
|
||||||
{
|
|
||||||
listBox_FilePath.Items.Clear();
|
|
||||||
foreach (var p in openFileDialog_Skel.FileNames)
|
|
||||||
listBox_FilePath.Items.Add(Path.GetFullPath(p));
|
|
||||||
label_Tip.Text = $"已选择 {listBox_FilePath.Items.Count} 个文件";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void button_Ok_Click(object sender, EventArgs e)
|
private void button_Ok_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var sourceVersion = (Spine.Version)comboBox_SourceVersion.SelectedValue;
|
var sourceVersion = (Spine.Version)comboBox_SourceVersion.SelectedValue;
|
||||||
var targetVersion = (Spine.Version)comboBox_SourceVersion.SelectedValue; // TODO: 增加目标版本
|
var targetVersion = (Spine.Version)comboBox_TargetVersion.SelectedValue;
|
||||||
var jsonSource = radioButton_JsonSource.Checked;
|
|
||||||
var jsonTarget = radioButton_JsonTarget.Checked;
|
var jsonTarget = radioButton_JsonTarget.Checked;
|
||||||
|
|
||||||
if (listBox_FilePath.Items.Count <= 0)
|
var items = skelFileListBox.Items;
|
||||||
|
|
||||||
|
if (items.Count <= 0)
|
||||||
{
|
{
|
||||||
MessageBox.Info("未选择任何文件");
|
MessageBox.Info("未选择任何文件");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (string p in listBox_FilePath.Items)
|
foreach (string p in items)
|
||||||
{
|
{
|
||||||
if (!File.Exists(p))
|
if (!File.Exists(p))
|
||||||
{
|
{
|
||||||
@@ -77,7 +59,7 @@ namespace SpineViewer.Dialogs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SkeletonConverter.ImplementedVersions.Contains(sourceVersion))
|
if (sourceVersion != Spine.Version.Auto && !SkeletonConverter.ImplementedVersions.Contains(sourceVersion))
|
||||||
{
|
{
|
||||||
MessageBox.Info($"{sourceVersion.GetName()} 版本尚未实现(咕咕咕~)");
|
MessageBox.Info($"{sourceVersion.GetName()} 版本尚未实现(咕咕咕~)");
|
||||||
return;
|
return;
|
||||||
@@ -89,18 +71,7 @@ namespace SpineViewer.Dialogs
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jsonSource == jsonTarget && sourceVersion == targetVersion)
|
Result = new(items.Cast<string>().ToArray(), sourceVersion, targetVersion, jsonTarget);
|
||||||
{
|
|
||||||
MessageBox.Info($"不需要转换相同的格式和版本");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SkelPaths = listBox_FilePath.Items.Cast<string>().ToArray();
|
|
||||||
SourceVersion = sourceVersion;
|
|
||||||
TargetVersion = targetVersion;
|
|
||||||
JsonSource = jsonSource;
|
|
||||||
JsonTarget = jsonTarget;
|
|
||||||
|
|
||||||
DialogResult = DialogResult.OK;
|
DialogResult = DialogResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,21 +79,31 @@ namespace SpineViewer.Dialogs
|
|||||||
{
|
{
|
||||||
DialogResult = DialogResult.Cancel;
|
DialogResult = DialogResult.Cancel;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void radioButton_Source_CheckedChanged(object sender, EventArgs e)
|
/// <summary>
|
||||||
{
|
/// 文件格式转换对话框结果包装类
|
||||||
if (radioButton_BinarySource.Checked)
|
/// </summary>
|
||||||
radioButton_JsonTarget.Checked = true;
|
public class ConvertFileFormatDialogResult(string[] skelPaths, Spine.Version sourceVersion, Spine.Version targetVersion, bool jsonTarget)
|
||||||
else
|
{
|
||||||
radioButton_BinaryTarget.Checked = true;
|
/// <summary>
|
||||||
}
|
/// 骨骼文件路径列表
|
||||||
|
/// </summary>
|
||||||
|
public string[] SkelPaths => skelPaths;
|
||||||
|
|
||||||
private void radioButton_Target_CheckedChanged(object sender, EventArgs e)
|
/// <summary>
|
||||||
{
|
/// 源版本
|
||||||
if (radioButton_BinaryTarget.Checked)
|
/// </summary>
|
||||||
radioButton_JsonSource.Checked = true;
|
public Spine.Version SourceVersion => sourceVersion;
|
||||||
else
|
|
||||||
radioButton_BinarySource.Checked = true;
|
/// <summary>
|
||||||
}
|
/// 目标版本
|
||||||
|
/// </summary>
|
||||||
|
public Spine.Version TargetVersion => targetVersion;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 目标格式是否为 Json
|
||||||
|
/// </summary>
|
||||||
|
public bool JsonTarget => jsonTarget;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
105
SpineViewer/Dialogs/ExportPreviewDialog.Designer.cs
generated
105
SpineViewer/Dialogs/ExportPreviewDialog.Designer.cs
generated
@@ -31,23 +31,18 @@
|
|||||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ExportPreviewDialog));
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ExportPreviewDialog));
|
||||||
panel1 = new Panel();
|
panel1 = new Panel();
|
||||||
tableLayoutPanel1 = new TableLayoutPanel();
|
tableLayoutPanel1 = new TableLayoutPanel();
|
||||||
|
propertyGrid = new PropertyGrid();
|
||||||
label4 = new Label();
|
label4 = new Label();
|
||||||
label1 = new Label();
|
label1 = new Label();
|
||||||
label2 = new Label();
|
|
||||||
label3 = new Label();
|
|
||||||
textBox_OutputDir = new TextBox();
|
textBox_OutputDir = new TextBox();
|
||||||
button_SelectOutputDir = new Button();
|
button_SelectOutputDir = new Button();
|
||||||
tableLayoutPanel2 = new TableLayoutPanel();
|
tableLayoutPanel2 = new TableLayoutPanel();
|
||||||
button_Ok = new Button();
|
button_Ok = new Button();
|
||||||
button_Cancel = new Button();
|
button_Cancel = new Button();
|
||||||
numericUpDown_Width = new NumericUpDown();
|
|
||||||
numericUpDown_Height = new NumericUpDown();
|
|
||||||
folderBrowserDialog = new FolderBrowserDialog();
|
folderBrowserDialog = new FolderBrowserDialog();
|
||||||
panel1.SuspendLayout();
|
panel1.SuspendLayout();
|
||||||
tableLayoutPanel1.SuspendLayout();
|
tableLayoutPanel1.SuspendLayout();
|
||||||
tableLayoutPanel2.SuspendLayout();
|
tableLayoutPanel2.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)numericUpDown_Width).BeginInit();
|
|
||||||
((System.ComponentModel.ISupportInitialize)numericUpDown_Height).BeginInit();
|
|
||||||
SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// panel1
|
// panel1
|
||||||
@@ -57,7 +52,7 @@
|
|||||||
panel1.Location = new Point(0, 0);
|
panel1.Location = new Point(0, 0);
|
||||||
panel1.Name = "panel1";
|
panel1.Name = "panel1";
|
||||||
panel1.Padding = new Padding(50, 15, 50, 10);
|
panel1.Padding = new Padding(50, 15, 50, 10);
|
||||||
panel1.Size = new Size(919, 276);
|
panel1.Size = new Size(914, 482);
|
||||||
panel1.TabIndex = 2;
|
panel1.TabIndex = 2;
|
||||||
//
|
//
|
||||||
// tableLayoutPanel1
|
// tableLayoutPanel1
|
||||||
@@ -68,27 +63,34 @@
|
|||||||
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
|
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
|
||||||
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
|
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50F));
|
||||||
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle());
|
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle());
|
||||||
|
tableLayoutPanel1.Controls.Add(propertyGrid, 0, 2);
|
||||||
tableLayoutPanel1.Controls.Add(label4, 0, 0);
|
tableLayoutPanel1.Controls.Add(label4, 0, 0);
|
||||||
tableLayoutPanel1.Controls.Add(label1, 0, 1);
|
tableLayoutPanel1.Controls.Add(label1, 0, 1);
|
||||||
tableLayoutPanel1.Controls.Add(label2, 0, 2);
|
|
||||||
tableLayoutPanel1.Controls.Add(label3, 0, 3);
|
|
||||||
tableLayoutPanel1.Controls.Add(textBox_OutputDir, 1, 1);
|
tableLayoutPanel1.Controls.Add(textBox_OutputDir, 1, 1);
|
||||||
tableLayoutPanel1.Controls.Add(button_SelectOutputDir, 3, 1);
|
tableLayoutPanel1.Controls.Add(button_SelectOutputDir, 3, 1);
|
||||||
tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 4);
|
tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 3);
|
||||||
tableLayoutPanel1.Controls.Add(numericUpDown_Width, 1, 2);
|
|
||||||
tableLayoutPanel1.Controls.Add(numericUpDown_Height, 1, 3);
|
|
||||||
tableLayoutPanel1.Dock = DockStyle.Fill;
|
tableLayoutPanel1.Dock = DockStyle.Fill;
|
||||||
tableLayoutPanel1.Location = new Point(50, 15);
|
tableLayoutPanel1.Location = new Point(50, 15);
|
||||||
tableLayoutPanel1.Name = "tableLayoutPanel1";
|
tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||||
tableLayoutPanel1.RowCount = 5;
|
tableLayoutPanel1.RowCount = 4;
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
||||||
|
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
tableLayoutPanel1.Size = new Size(814, 457);
|
||||||
tableLayoutPanel1.RowStyles.Add(new RowStyle());
|
|
||||||
tableLayoutPanel1.Size = new Size(819, 251);
|
|
||||||
tableLayoutPanel1.TabIndex = 0;
|
tableLayoutPanel1.TabIndex = 0;
|
||||||
//
|
//
|
||||||
|
// propertyGrid
|
||||||
|
//
|
||||||
|
tableLayoutPanel1.SetColumnSpan(propertyGrid, 4);
|
||||||
|
propertyGrid.Dock = DockStyle.Fill;
|
||||||
|
propertyGrid.HelpVisible = false;
|
||||||
|
propertyGrid.Location = new Point(3, 97);
|
||||||
|
propertyGrid.Name = "propertyGrid";
|
||||||
|
propertyGrid.Size = new Size(808, 284);
|
||||||
|
propertyGrid.TabIndex = 1;
|
||||||
|
propertyGrid.ToolbarVisible = false;
|
||||||
|
//
|
||||||
// label4
|
// label4
|
||||||
//
|
//
|
||||||
label4.AutoSize = true;
|
label4.AutoSize = true;
|
||||||
@@ -97,9 +99,9 @@
|
|||||||
label4.Location = new Point(15, 15);
|
label4.Location = new Point(15, 15);
|
||||||
label4.Margin = new Padding(15);
|
label4.Margin = new Padding(15);
|
||||||
label4.Name = "label4";
|
label4.Name = "label4";
|
||||||
label4.Size = new Size(789, 24);
|
label4.Size = new Size(784, 24);
|
||||||
label4.TabIndex = 11;
|
label4.TabIndex = 11;
|
||||||
label4.Text = "说明:导出的文件名与骨骼文件名相同";
|
label4.Text = "说明:输出文件夹为可选项,留空则将预览图输出到每个骨骼文件所在目录";
|
||||||
label4.TextAlign = ContentAlignment.MiddleCenter;
|
label4.TextAlign = ContentAlignment.MiddleCenter;
|
||||||
//
|
//
|
||||||
// label1
|
// label1
|
||||||
@@ -112,40 +114,20 @@
|
|||||||
label1.TabIndex = 0;
|
label1.TabIndex = 0;
|
||||||
label1.Text = "输出文件夹:";
|
label1.Text = "输出文件夹:";
|
||||||
//
|
//
|
||||||
// label2
|
|
||||||
//
|
|
||||||
label2.Anchor = AnchorStyles.Right;
|
|
||||||
label2.AutoSize = true;
|
|
||||||
label2.Location = new Point(75, 100);
|
|
||||||
label2.Name = "label2";
|
|
||||||
label2.Size = new Size(32, 24);
|
|
||||||
label2.TabIndex = 1;
|
|
||||||
label2.Text = "宽:";
|
|
||||||
//
|
|
||||||
// label3
|
|
||||||
//
|
|
||||||
label3.Anchor = AnchorStyles.Right;
|
|
||||||
label3.AutoSize = true;
|
|
||||||
label3.Location = new Point(75, 136);
|
|
||||||
label3.Name = "label3";
|
|
||||||
label3.Size = new Size(32, 24);
|
|
||||||
label3.TabIndex = 2;
|
|
||||||
label3.Text = "高:";
|
|
||||||
//
|
|
||||||
// textBox_OutputDir
|
// textBox_OutputDir
|
||||||
//
|
//
|
||||||
tableLayoutPanel1.SetColumnSpan(textBox_OutputDir, 2);
|
tableLayoutPanel1.SetColumnSpan(textBox_OutputDir, 2);
|
||||||
textBox_OutputDir.Dock = DockStyle.Fill;
|
textBox_OutputDir.Dock = DockStyle.Fill;
|
||||||
textBox_OutputDir.Location = new Point(113, 57);
|
textBox_OutputDir.Location = new Point(113, 57);
|
||||||
textBox_OutputDir.Name = "textBox_OutputDir";
|
textBox_OutputDir.Name = "textBox_OutputDir";
|
||||||
textBox_OutputDir.Size = new Size(664, 30);
|
textBox_OutputDir.Size = new Size(660, 30);
|
||||||
textBox_OutputDir.TabIndex = 3;
|
textBox_OutputDir.TabIndex = 3;
|
||||||
//
|
//
|
||||||
// button_SelectOutputDir
|
// button_SelectOutputDir
|
||||||
//
|
//
|
||||||
button_SelectOutputDir.AutoSize = true;
|
button_SelectOutputDir.AutoSize = true;
|
||||||
button_SelectOutputDir.AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
button_SelectOutputDir.AutoSizeMode = AutoSizeMode.GrowAndShrink;
|
||||||
button_SelectOutputDir.Location = new Point(783, 57);
|
button_SelectOutputDir.Location = new Point(779, 57);
|
||||||
button_SelectOutputDir.Name = "button_SelectOutputDir";
|
button_SelectOutputDir.Name = "button_SelectOutputDir";
|
||||||
button_SelectOutputDir.Size = new Size(32, 34);
|
button_SelectOutputDir.Size = new Size(32, 34);
|
||||||
button_SelectOutputDir.TabIndex = 5;
|
button_SelectOutputDir.TabIndex = 5;
|
||||||
@@ -164,17 +146,18 @@
|
|||||||
tableLayoutPanel2.Controls.Add(button_Ok, 0, 0);
|
tableLayoutPanel2.Controls.Add(button_Ok, 0, 0);
|
||||||
tableLayoutPanel2.Controls.Add(button_Cancel, 1, 0);
|
tableLayoutPanel2.Controls.Add(button_Cancel, 1, 0);
|
||||||
tableLayoutPanel2.Dock = DockStyle.Bottom;
|
tableLayoutPanel2.Dock = DockStyle.Bottom;
|
||||||
tableLayoutPanel2.Location = new Point(3, 208);
|
tableLayoutPanel2.Location = new Point(3, 414);
|
||||||
|
tableLayoutPanel2.Margin = new Padding(3, 30, 3, 3);
|
||||||
tableLayoutPanel2.Name = "tableLayoutPanel2";
|
tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||||
tableLayoutPanel2.RowCount = 1;
|
tableLayoutPanel2.RowCount = 1;
|
||||||
tableLayoutPanel2.RowStyles.Add(new RowStyle());
|
tableLayoutPanel2.RowStyles.Add(new RowStyle());
|
||||||
tableLayoutPanel2.Size = new Size(813, 40);
|
tableLayoutPanel2.Size = new Size(808, 40);
|
||||||
tableLayoutPanel2.TabIndex = 10;
|
tableLayoutPanel2.TabIndex = 10;
|
||||||
//
|
//
|
||||||
// button_Ok
|
// button_Ok
|
||||||
//
|
//
|
||||||
button_Ok.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
button_Ok.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||||
button_Ok.Location = new Point(264, 3);
|
button_Ok.Location = new Point(262, 3);
|
||||||
button_Ok.Margin = new Padding(3, 3, 30, 3);
|
button_Ok.Margin = new Padding(3, 3, 30, 3);
|
||||||
button_Ok.Name = "button_Ok";
|
button_Ok.Name = "button_Ok";
|
||||||
button_Ok.Size = new Size(112, 34);
|
button_Ok.Size = new Size(112, 34);
|
||||||
@@ -186,7 +169,7 @@
|
|||||||
// button_Cancel
|
// button_Cancel
|
||||||
//
|
//
|
||||||
button_Cancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
|
button_Cancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
|
||||||
button_Cancel.Location = new Point(436, 3);
|
button_Cancel.Location = new Point(434, 3);
|
||||||
button_Cancel.Margin = new Padding(30, 3, 3, 3);
|
button_Cancel.Margin = new Padding(30, 3, 3, 3);
|
||||||
button_Cancel.Name = "button_Cancel";
|
button_Cancel.Name = "button_Cancel";
|
||||||
button_Cancel.Size = new Size(112, 34);
|
button_Cancel.Size = new Size(112, 34);
|
||||||
@@ -195,30 +178,6 @@
|
|||||||
button_Cancel.UseVisualStyleBackColor = true;
|
button_Cancel.UseVisualStyleBackColor = true;
|
||||||
button_Cancel.Click += button_Cancel_Click;
|
button_Cancel.Click += button_Cancel_Click;
|
||||||
//
|
//
|
||||||
// numericUpDown_Width
|
|
||||||
//
|
|
||||||
numericUpDown_Width.Anchor = AnchorStyles.Left;
|
|
||||||
numericUpDown_Width.Location = new Point(113, 97);
|
|
||||||
numericUpDown_Width.Maximum = new decimal(new int[] { 4096, 0, 0, 0 });
|
|
||||||
numericUpDown_Width.Minimum = new decimal(new int[] { 32, 0, 0, 0 });
|
|
||||||
numericUpDown_Width.Name = "numericUpDown_Width";
|
|
||||||
numericUpDown_Width.Size = new Size(180, 30);
|
|
||||||
numericUpDown_Width.TabIndex = 12;
|
|
||||||
numericUpDown_Width.TextAlign = HorizontalAlignment.Right;
|
|
||||||
numericUpDown_Width.Value = new decimal(new int[] { 256, 0, 0, 0 });
|
|
||||||
//
|
|
||||||
// numericUpDown_Height
|
|
||||||
//
|
|
||||||
numericUpDown_Height.Anchor = AnchorStyles.Left;
|
|
||||||
numericUpDown_Height.Location = new Point(113, 133);
|
|
||||||
numericUpDown_Height.Maximum = new decimal(new int[] { 4096, 0, 0, 0 });
|
|
||||||
numericUpDown_Height.Minimum = new decimal(new int[] { 32, 0, 0, 0 });
|
|
||||||
numericUpDown_Height.Name = "numericUpDown_Height";
|
|
||||||
numericUpDown_Height.Size = new Size(180, 30);
|
|
||||||
numericUpDown_Height.TabIndex = 13;
|
|
||||||
numericUpDown_Height.TextAlign = HorizontalAlignment.Right;
|
|
||||||
numericUpDown_Height.Value = new decimal(new int[] { 256, 0, 0, 0 });
|
|
||||||
//
|
|
||||||
// folderBrowserDialog
|
// folderBrowserDialog
|
||||||
//
|
//
|
||||||
folderBrowserDialog.AddToRecent = false;
|
folderBrowserDialog.AddToRecent = false;
|
||||||
@@ -229,7 +188,7 @@
|
|||||||
AutoScaleDimensions = new SizeF(11F, 24F);
|
AutoScaleDimensions = new SizeF(11F, 24F);
|
||||||
AutoScaleMode = AutoScaleMode.Font;
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
CancelButton = button_Cancel;
|
CancelButton = button_Cancel;
|
||||||
ClientSize = new Size(919, 276);
|
ClientSize = new Size(914, 482);
|
||||||
Controls.Add(panel1);
|
Controls.Add(panel1);
|
||||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||||
Icon = (Icon)resources.GetObject("$this.Icon");
|
Icon = (Icon)resources.GetObject("$this.Icon");
|
||||||
@@ -239,14 +198,11 @@
|
|||||||
ShowInTaskbar = false;
|
ShowInTaskbar = false;
|
||||||
StartPosition = FormStartPosition.CenterScreen;
|
StartPosition = FormStartPosition.CenterScreen;
|
||||||
Text = "导出预览图";
|
Text = "导出预览图";
|
||||||
Load += ExportPreviewDialog_Load;
|
|
||||||
panel1.ResumeLayout(false);
|
panel1.ResumeLayout(false);
|
||||||
panel1.PerformLayout();
|
panel1.PerformLayout();
|
||||||
tableLayoutPanel1.ResumeLayout(false);
|
tableLayoutPanel1.ResumeLayout(false);
|
||||||
tableLayoutPanel1.PerformLayout();
|
tableLayoutPanel1.PerformLayout();
|
||||||
tableLayoutPanel2.ResumeLayout(false);
|
tableLayoutPanel2.ResumeLayout(false);
|
||||||
((System.ComponentModel.ISupportInitialize)numericUpDown_Width).EndInit();
|
|
||||||
((System.ComponentModel.ISupportInitialize)numericUpDown_Height).EndInit();
|
|
||||||
ResumeLayout(false);
|
ResumeLayout(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,15 +212,12 @@
|
|||||||
private TableLayoutPanel tableLayoutPanel1;
|
private TableLayoutPanel tableLayoutPanel1;
|
||||||
private Label label4;
|
private Label label4;
|
||||||
private Label label1;
|
private Label label1;
|
||||||
private Label label2;
|
|
||||||
private Label label3;
|
|
||||||
private TextBox textBox_OutputDir;
|
private TextBox textBox_OutputDir;
|
||||||
private Button button_SelectOutputDir;
|
private Button button_SelectOutputDir;
|
||||||
private TableLayoutPanel tableLayoutPanel2;
|
private TableLayoutPanel tableLayoutPanel2;
|
||||||
private Button button_Ok;
|
private Button button_Ok;
|
||||||
private Button button_Cancel;
|
private Button button_Cancel;
|
||||||
private NumericUpDown numericUpDown_Width;
|
|
||||||
private NumericUpDown numericUpDown_Height;
|
|
||||||
private FolderBrowserDialog folderBrowserDialog;
|
private FolderBrowserDialog folderBrowserDialog;
|
||||||
|
private PropertyGrid propertyGrid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -12,60 +13,66 @@ namespace SpineViewer.Dialogs
|
|||||||
{
|
{
|
||||||
public partial class ExportPreviewDialog: Form
|
public partial class ExportPreviewDialog: Form
|
||||||
{
|
{
|
||||||
// TODO: 用单独的结果包装类
|
/// <summary>
|
||||||
public string OutputDir { get; private set; }
|
/// 对话框结果
|
||||||
public uint PreviewWidth { get; private set; }
|
/// </summary>
|
||||||
public uint PreviewHeight { get; private set; }
|
public readonly ExportPreviewDialogResult Result = new();
|
||||||
|
|
||||||
public ExportPreviewDialog()
|
public ExportPreviewDialog()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
propertyGrid.SelectedObject = Result;
|
||||||
|
|
||||||
private void ExportPreviewDialog_Load(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
button_SelectOutputDir_Click(sender, e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void button_SelectOutputDir_Click(object sender, EventArgs e)
|
private void button_SelectOutputDir_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
folderBrowserDialog.InitialDirectory = textBox_OutputDir.Text;
|
folderBrowserDialog.InitialDirectory = textBox_OutputDir.Text;
|
||||||
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
|
if (folderBrowserDialog.ShowDialog() != DialogResult.OK)
|
||||||
{
|
return;
|
||||||
textBox_OutputDir.Text = Path.GetFullPath(folderBrowserDialog.SelectedPath);
|
textBox_OutputDir.Text = Path.GetFullPath(folderBrowserDialog.SelectedPath);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void button_Ok_Click(object sender, EventArgs e)
|
private void button_Ok_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var outputDir = textBox_OutputDir.Text;
|
var outputDir = textBox_OutputDir.Text;
|
||||||
if (File.Exists(outputDir))
|
if (string.IsNullOrEmpty(outputDir))
|
||||||
{
|
{
|
||||||
MessageBox.Info("输出文件夹无效");
|
outputDir = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (File.Exists(outputDir))
|
||||||
|
{
|
||||||
|
MessageBox.Info("输出文件夹无效");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(outputDir))
|
||||||
|
{
|
||||||
|
if (MessageBox.Quest($"文件夹 {outputDir} 不存在,是否创建?") != DialogResult.OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(outputDir);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Program.Logger.Error(ex.ToString());
|
||||||
|
MessageBox.Error(ex.ToString(), "文件夹创建失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outputDir = Path.GetFullPath(outputDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outputDir is null && string.IsNullOrEmpty(Result.NameSuffix))
|
||||||
|
{
|
||||||
|
MessageBox.Info("输出文件夹和名称后缀不可同时为空,存在文件覆盖风险");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Directory.Exists(outputDir))
|
Result.OutputDir = outputDir;
|
||||||
{
|
|
||||||
if (MessageBox.Quest($"文件夹 {outputDir} 不存在,是否创建?") != DialogResult.OK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(outputDir);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Program.Logger.Error(ex.ToString());
|
|
||||||
MessageBox.Error(ex.ToString(), "文件夹创建失败");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OutputDir = Path.GetFullPath(outputDir);
|
|
||||||
PreviewWidth = (uint)numericUpDown_Width.Value;
|
|
||||||
PreviewHeight = (uint)numericUpDown_Height.Value;
|
|
||||||
|
|
||||||
DialogResult = DialogResult.OK;
|
DialogResult = DialogResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,4 +81,89 @@ namespace SpineViewer.Dialogs
|
|||||||
DialogResult = DialogResult.Cancel;
|
DialogResult = DialogResult.Cancel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ExportPreviewDialogResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 输出路径
|
||||||
|
/// </summary>
|
||||||
|
[Browsable(false)]
|
||||||
|
public string? OutputDir { get; set; } = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 预览图格式
|
||||||
|
/// </summary>
|
||||||
|
[TypeConverter(typeof(ImageFormatConverter))]
|
||||||
|
[Category("图像"), DisplayName("预览图格式")]
|
||||||
|
public ImageFormat ImageFormat
|
||||||
|
{
|
||||||
|
get => imageFormat;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == ImageFormat.MemoryBmp) value = ImageFormat.Bmp;
|
||||||
|
imageFormat = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private ImageFormat imageFormat = ImageFormat.Png;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 预览图分辨率
|
||||||
|
/// </summary>
|
||||||
|
[TypeConverter(typeof(SizeConverter))]
|
||||||
|
[Category("图像"), DisplayName("分辨率")]
|
||||||
|
public Size Resolution
|
||||||
|
{
|
||||||
|
get => resolution;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value.Width <= 0) value.Width = 128;
|
||||||
|
if (value.Height <= 0) value.Height = 128;
|
||||||
|
resolution = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Size resolution = new(512, 512);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 四周填充像素值
|
||||||
|
/// </summary>
|
||||||
|
[TypeConverter(typeof(PaddingConverter))]
|
||||||
|
[Category("图像"), DisplayName("四周填充像素值")]
|
||||||
|
public Padding Padding
|
||||||
|
{
|
||||||
|
get => padding;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value.Left <= 0) value.Left = 10;
|
||||||
|
if (value.Right <= 0) value.Right = 10;
|
||||||
|
if (value.Top <= 0) value.Top = 10;
|
||||||
|
if (value.Bottom <= 0) value.Bottom = 10;
|
||||||
|
padding = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Padding padding = new(1);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DPI
|
||||||
|
/// </summary>
|
||||||
|
[TypeConverter(typeof(SizeFConverter))]
|
||||||
|
[Category("图像"), DisplayName("DPI")]
|
||||||
|
public SizeF DPI
|
||||||
|
{
|
||||||
|
get => dpi;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value.Width <= 0) value.Width = 144;
|
||||||
|
if (value.Height <= 0) value.Height = 144;
|
||||||
|
dpi = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private SizeF dpi = new(144, 144);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 名称后缀
|
||||||
|
/// </summary>
|
||||||
|
[Category("其他"), DisplayName("名称后缀")]
|
||||||
|
public string NameSuffix { get; set; } = "(preview)";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
64
SpineViewer/ExportHelper.cs
Normal file
64
SpineViewer/ExportHelper.cs
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
using FFMpegCore.Pipes;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
|
||||||
|
|
||||||
|
namespace SpineViewer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// SFML.Graphics.Image 帧对象包装类
|
||||||
|
/// </summary>
|
||||||
|
public class SFMLImageVideoFrame(SFML.Graphics.Image image) : IVideoFrame, IDisposable
|
||||||
|
{
|
||||||
|
public int Width => (int)image.Size.X;
|
||||||
|
public int Height => (int)image.Size.Y;
|
||||||
|
public string Format => "rgba";
|
||||||
|
public void Serialize(Stream pipe) => pipe.Write(image.Pixels);
|
||||||
|
public async Task SerializeAsync(Stream pipe, CancellationToken token) => await pipe.WriteAsync(image.Pixels, token);
|
||||||
|
public void Dispose() => image.Dispose();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Save the contents of the image to a file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filename">Path of the file to save (overwritten if already exist)</param>
|
||||||
|
/// <returns>True if saving was successful</returns>
|
||||||
|
public bool SaveToFile(string filename) => image.SaveToFile(filename);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Save the image to a buffer in memory The format of the image must be specified.
|
||||||
|
/// The supported image formats are bmp, png, tga and jpg. This function fails if
|
||||||
|
/// the image is empty, or if the format was invalid.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="output">Byte array filled with encoded data</param>
|
||||||
|
/// <param name="format">Encoding format to use</param>
|
||||||
|
/// <returns>True if saving was successful</returns>
|
||||||
|
public bool SaveToMemory(out byte[] output, string format) => image.SaveToMemory(out output, format);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 为帧导出创建的辅助类
|
||||||
|
/// </summary>
|
||||||
|
public static class ExportHelper
|
||||||
|
{
|
||||||
|
public static Bitmap CopyToBitmap(this SFML.Graphics.Texture tex)
|
||||||
|
{
|
||||||
|
using var img = tex.CopyToImage();
|
||||||
|
img.SaveToMemory(out var imgBuffer, "bmp");
|
||||||
|
using var stream = new MemoryStream(imgBuffer);
|
||||||
|
return new Bitmap(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SFMLImageVideoFrame CopyToFrame(this SFML.Graphics.Texture tex) => new(tex.CopyToImage());
|
||||||
|
|
||||||
|
public static string GetSuffix(this ImageFormat imageFormat)
|
||||||
|
{
|
||||||
|
if (imageFormat == ImageFormat.Icon) return ".ico";
|
||||||
|
else if (imageFormat == ImageFormat.Exif) return ".jpg";
|
||||||
|
else return $".{imageFormat.ToString().ToLower()}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -106,7 +106,7 @@ namespace SpineViewer
|
|||||||
|
|
||||||
var progressDialog = new Dialogs.ProgressDialog();
|
var progressDialog = new Dialogs.ProgressDialog();
|
||||||
progressDialog.DoWork += ExportPreview_Work;
|
progressDialog.DoWork += ExportPreview_Work;
|
||||||
progressDialog.RunWorkerAsync(saveDialog);
|
progressDialog.RunWorkerAsync(saveDialog.Result);
|
||||||
progressDialog.ShowDialog();
|
progressDialog.ShowDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ namespace SpineViewer
|
|||||||
|
|
||||||
var progressDialog = new Dialogs.ProgressDialog();
|
var progressDialog = new Dialogs.ProgressDialog();
|
||||||
progressDialog.DoWork += ConvertFileFormat_Work;
|
progressDialog.DoWork += ConvertFileFormat_Work;
|
||||||
progressDialog.RunWorkerAsync(openDialog);
|
progressDialog.RunWorkerAsync(openDialog.Result);
|
||||||
progressDialog.ShowDialog();
|
progressDialog.ShowDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,17 +294,17 @@ namespace SpineViewer
|
|||||||
private void ExportPreview_Work(object? sender, DoWorkEventArgs e)
|
private void ExportPreview_Work(object? sender, DoWorkEventArgs e)
|
||||||
{
|
{
|
||||||
var worker = sender as BackgroundWorker;
|
var worker = sender as BackgroundWorker;
|
||||||
var arguments = e.Argument as Dialogs.ExportPreviewDialog;
|
var arguments = e.Argument as Dialogs.ExportPreviewDialogResult;
|
||||||
var outputDir = arguments.OutputDir;
|
|
||||||
var width = arguments.PreviewWidth;
|
|
||||||
var height = arguments.PreviewHeight;
|
|
||||||
// TODO: 增加填充参数
|
|
||||||
var paddingL = 1u;
|
|
||||||
var paddingR = 1u;
|
|
||||||
var paddingT = 1u;
|
|
||||||
var paddingB = 1u;
|
|
||||||
|
|
||||||
var tex = new SFML.Graphics.RenderTexture(width, height);
|
var outputDir = arguments.OutputDir;
|
||||||
|
var imageFormat = arguments.ImageFormat;
|
||||||
|
var resolution = arguments.Resolution;
|
||||||
|
var padding = arguments.Padding;
|
||||||
|
var dpi = arguments.DPI;
|
||||||
|
var nameSuffix = arguments.NameSuffix;
|
||||||
|
var renderSelectedOnly = spinePreviewer.RenderSelectedOnly;
|
||||||
|
|
||||||
|
var tex = new SFML.Graphics.RenderTexture((uint)resolution.Width, (uint)resolution.Height);
|
||||||
|
|
||||||
int success = 0;
|
int success = 0;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
@@ -323,18 +323,26 @@ namespace SpineViewer
|
|||||||
}
|
}
|
||||||
|
|
||||||
var spine = spines[i];
|
var spine = spines[i];
|
||||||
|
if (renderSelectedOnly && !spine.IsSelected)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var filename = $"{spine.Name}{nameSuffix}{imageFormat.GetSuffix()}";
|
||||||
|
var savePath = outputDir is null ? Path.Combine(spine.AssetsDir, filename) : Path.Combine(outputDir, filename);
|
||||||
|
|
||||||
var tmp = spine.CurrentAnimation;
|
var tmp = spine.CurrentAnimation;
|
||||||
spine.CurrentAnimation = Spine.Spine.EMPTY_ANIMATION;
|
spine.CurrentAnimation = Spine.Spine.EMPTY_ANIMATION;
|
||||||
tex.SetView(spine.GetInitView(width, height, paddingL, paddingR, paddingT, paddingB));
|
tex.SetView(spine.GetInitView(resolution, padding));
|
||||||
tex.Clear(SFML.Graphics.Color.Transparent);
|
tex.Clear(SFML.Graphics.Color.Transparent);
|
||||||
tex.Draw(spine);
|
tex.Draw(spine);
|
||||||
tex.Display();
|
tex.Display();
|
||||||
spine.CurrentAnimation = tmp;
|
spine.CurrentAnimation = tmp;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var img = tex.Texture.CopyToImage())
|
using (var img = new Bitmap(tex.Texture.CopyToBitmap()))
|
||||||
{
|
{
|
||||||
img.SaveToFile(Path.Combine(outputDir, $"{spine.Name}.png"));
|
img.SetResolution(dpi.Width, dpi.Height);
|
||||||
|
img.Save(savePath, imageFormat);
|
||||||
}
|
}
|
||||||
success++;
|
success++;
|
||||||
}
|
}
|
||||||
@@ -365,28 +373,19 @@ namespace SpineViewer
|
|||||||
private void ConvertFileFormat_Work(object? sender, DoWorkEventArgs e)
|
private void ConvertFileFormat_Work(object? sender, DoWorkEventArgs e)
|
||||||
{
|
{
|
||||||
var worker = sender as BackgroundWorker;
|
var worker = sender as BackgroundWorker;
|
||||||
var arguments = e.Argument as Dialogs.ConvertFileFormatDialog;
|
var arguments = e.Argument as Dialogs.ConvertFileFormatDialogResult;
|
||||||
var skelPaths = arguments.SkelPaths;
|
var skelPaths = arguments.SkelPaths;
|
||||||
var srcVersion = arguments.SourceVersion;
|
var srcVersion = arguments.SourceVersion;
|
||||||
var tgtVersion = arguments.TargetVersion;
|
var tgtVersion = arguments.TargetVersion;
|
||||||
var jsonSource = arguments.JsonSource;
|
|
||||||
var jsonTarget = arguments.JsonTarget;
|
var jsonTarget = arguments.JsonTarget;
|
||||||
var newSuffix = jsonTarget ? ".json" : ".skel";
|
var newSuffix = jsonTarget ? ".json" : ".skel";
|
||||||
|
|
||||||
if (jsonTarget == jsonSource)
|
|
||||||
{
|
|
||||||
if (tgtVersion == srcVersion)
|
|
||||||
return;
|
|
||||||
else
|
|
||||||
newSuffix += $".{tgtVersion.ToString().ToLower()}"; // TODO: 仅转换版本的情况下考虑文件覆盖问题
|
|
||||||
}
|
|
||||||
|
|
||||||
int totalCount = skelPaths.Length;
|
int totalCount = skelPaths.Length;
|
||||||
int success = 0;
|
int success = 0;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
SkeletonConverter srcCvter = SkeletonConverter.New(srcVersion);
|
SkeletonConverter srcCvter = srcVersion != Spine.Version.Auto ? SkeletonConverter.New(srcVersion) : null;
|
||||||
SkeletonConverter tgtCvter = tgtVersion == srcVersion ? srcCvter : SkeletonConverter.New(tgtVersion);
|
SkeletonConverter tgtCvter = SkeletonConverter.New(tgtVersion);
|
||||||
|
|
||||||
worker.ReportProgress(0, $"已处理 0/{totalCount}");
|
worker.ReportProgress(0, $"已处理 0/{totalCount}");
|
||||||
for (int i = 0; i < totalCount; i++)
|
for (int i = 0; i < totalCount; i++)
|
||||||
@@ -402,8 +401,15 @@ namespace SpineViewer
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var root = jsonSource ? srcCvter.ReadJson(skelPath) : srcCvter.ReadBinary(skelPath);
|
if (srcVersion == Spine.Version.Auto)
|
||||||
if (tgtVersion != srcVersion) root = srcCvter.ToVersion(root, tgtVersion);
|
{
|
||||||
|
if (Spine.Spine.GetVersion(skelPath) is Spine.Version detectedSrcVersion)
|
||||||
|
srcCvter = SkeletonConverter.New(detectedSrcVersion);
|
||||||
|
else
|
||||||
|
throw new InvalidDataException($"Auto version detection failed for {skelPath}, try to use a specific version");
|
||||||
|
}
|
||||||
|
var root = srcCvter.Read(skelPath);
|
||||||
|
root = srcCvter.ToVersion(root, tgtVersion);
|
||||||
if (jsonTarget) tgtCvter.WriteJson(root, newPath); else tgtCvter.WriteBinary(root, newPath);
|
if (jsonTarget) tgtCvter.WriteJson(root, newPath); else tgtCvter.WriteBinary(root, newPath);
|
||||||
success++;
|
success++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,29 @@ namespace SpineViewer.Spine
|
|||||||
root.WriteTo(writer);
|
root.WriteTo(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取骨骼文件
|
||||||
|
/// </summary>
|
||||||
|
public JsonObject Read(string path)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ReadBinary(path);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return ReadJson(path);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// 都不行就报错
|
||||||
|
throw new InvalidDataException($"Unknown skeleton file format {path}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 转换到目标版本
|
/// 转换到目标版本
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
<Version>0.10.7</Version>
|
<Version>0.10.9</Version>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<ApplicationIcon>appicon.ico</ApplicationIcon>
|
<ApplicationIcon>appicon.ico</ApplicationIcon>
|
||||||
|
|||||||
Reference in New Issue
Block a user