Compare commits

..

52 Commits

Author SHA1 Message Date
ww-rm
acf48cd74d Merge pull request #51 from ww-rm/dev/wf
Release v0.12.17
2025-06-14 20:10:34 +08:00
ww-rm
2fecf4223a 更新至v0.12.17 2025-06-14 20:08:54 +08:00
ww-rm
2953ec44fb update changelog 2025-06-14 20:08:45 +08:00
ww-rm
77399b4524 改善动画边界检测 2025-06-14 20:07:09 +08:00
ww-rm
b34639c383 Merge pull request #48 from ww-rm/dev/wf
Release v0.12.16
2025-06-11 13:43:20 +08:00
ww-rm
c0e2bb81e5 更新至v0.12.16 2025-06-11 13:41:25 +08:00
ww-rm
55ebcc1857 合并导出时也允许自动时长 2025-06-11 13:38:55 +08:00
ww-rm
e3a201af89 Merge pull request #42 from ww-rm/dev/wf
修复工作流错误
2025-05-28 18:23:30 +08:00
ww-rm
292ede8461 修复工作流错误 2025-05-28 18:22:33 +08:00
ww-rm
112a9a1bf2 Merge pull request #41 from ww-rm/dev/wf
修复工作流错误
2025-05-28 17:29:22 +08:00
ww-rm
63ed8d7ca4 修复工作流错误 2025-05-28 17:27:55 +08:00
ww-rm
d1e33c25bc Merge pull request #40 from ww-rm/dev/wf
修复工作流错误
2025-05-28 17:15:34 +08:00
ww-rm
ce7c6f3802 修复工作流错误 2025-05-28 17:14:08 +08:00
ww-rm
0a30af0ad2 Merge pull request #39 from ww-rm/dev/wf
修复工作流错误
2025-05-28 17:11:05 +08:00
ww-rm
0b478cab18 修复工作流错误 2025-05-28 17:09:58 +08:00
ww-rm
b14849a0b1 Merge pull request #38 from ww-rm/dev/wf
Dev/wf
2025-05-28 17:00:46 +08:00
ww-rm
b7f5f24e6f Merge branch 'dev/wf' of github.com:ww-rm/SpineViewer into dev/wf 2025-05-28 16:59:51 +08:00
ww-rm
150331d2e4 修复工作流错误 2025-05-28 16:59:38 +08:00
ww-rm
dcec8797b0 Merge pull request #37 from ww-rm/dev/wf
Dev/wf
2025-05-28 16:46:12 +08:00
ww-rm
4d1aec9ed8 Merge branch 'release/wf' into dev/wf 2025-05-28 16:45:42 +08:00
ww-rm
0cb325820b 修复工作流版本提取错误 2025-05-28 16:38:00 +08:00
ww-rm
2a862b28be 更改工作流自动获取版本号 2025-05-28 16:29:29 +08:00
ww-rm
c2935f49e9 更新至v0.12.15 2025-05-28 16:29:29 +08:00
ww-rm
22043f8f38 update changelog 2025-05-28 16:29:29 +08:00
ww-rm
3020a818f0 修复附件类型枚举量的字符串大小写问题 2025-05-28 16:29:29 +08:00
ww-rm
30177e8d7f 更改工作流自动获取版本号 2025-05-28 16:28:12 +08:00
ww-rm
3ad49838be 更新至v0.12.15 2025-05-28 16:05:55 +08:00
ww-rm
3e480abd44 update changelog 2025-05-28 16:05:42 +08:00
ww-rm
49f6b28aef 修复附件类型枚举量的字符串大小写问题 2025-05-28 16:05:09 +08:00
ww-rm
b81d13b582 更新至v0.12.14 2025-05-28 09:13:03 +08:00
ww-rm
04eb3cb640 update changelog 2025-05-28 09:12:37 +08:00
ww-rm
0ac75a088a 修复curve读取错误 2025-05-28 09:11:25 +08:00
ww-rm
cd652a72a1 更新至v0.12.13 2025-05-19 10:31:34 +08:00
ww-rm
828ff30dbf update changelog 2025-05-19 10:31:15 +08:00
ww-rm
f452fe8a71 生成文件增加额外的随机后缀 2025-05-19 10:30:29 +08:00
ww-rm
15e29a3b8a 修复readattachmentline里的顺序错误 2025-05-17 10:47:49 +08:00
ww-rm
5c6e98f5e1 更新至v0.12.12 2025-05-13 14:21:13 +08:00
ww-rm
ef06073119 update changelog 2025-05-13 14:19:52 +08:00
ww-rm
bca8b0ad85 补充SkinnedMeshAttachment附件的渲染 2025-05-13 14:19:15 +08:00
ww-rm
4983b1fa88 更新至v0.12.11 2025-05-08 18:35:23 +08:00
ww-rm
f6b6d9f0e7 update changelog 2025-05-08 18:35:12 +08:00
ww-rm
12a168df92 修复atlas null 引用导致的闪退 2025-05-08 18:34:43 +08:00
ww-rm
e06d2012d6 更新至v0.12.10 2025-05-07 17:45:07 +08:00
ww-rm
faed2448eb update changelog 2025-05-07 17:44:52 +08:00
ww-rm
a80aed54a0 增加纹理加载菜单选项 2025-05-07 17:43:55 +08:00
ww-rm
3f9c4dfe99 抽出TextureLoader,增加部分可调参数 2025-05-07 17:43:42 +08:00
ww-rm
3c91f335fc 修复skin索引顺序问题 2025-05-06 19:11:46 +08:00
ww-rm
1ea4586360 Merge pull request #21 from steve14608/main
4.1版本格式转换,以及4.2版本发现的一些小bug
2025-05-02 16:29:23 +08:00
YongQi Li
45e08b5b60 Merge branch 'main' of https://github.com/steve14608/SpineViewer 2025-05-02 16:25:53 +08:00
YongQi Li
43ce5a5288 修改了skin2idx的读取逻辑 2025-05-02 16:25:39 +08:00
YongQi Li
887315ceda Merge branch 'main' of https://github.com/steve14608/SpineViewer 2025-05-02 14:52:01 +08:00
ww-rm
30b5c8dd74 4.1的格式转换 2025-05-02 14:51:40 +08:00
24 changed files with 4636 additions and 1750 deletions

View File

@@ -1,46 +1,80 @@
name: Build & Release
on:
push:
tags:
- 'v*.*.*'
pull_request:
branches:
- release/wf
types:
- closed
jobs:
build-release:
if: ${{ github.event.pull_request.merged == true }}
runs-on: windows-latest
env:
PROJECT_NAME: SpineViewer
VERSION: ${{ github.ref_name }}
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
fetch-tags: true
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: '8.0.x'
dotnet-version: "8.0.x"
- name: Extract version from csproj
shell: pwsh
run: |
[xml]$proj = Get-Content "$env:PROJECT_NAME\$env:PROJECT_NAME.csproj"
$VERSION_NUM = $proj.Project.PropertyGroup.Version
$VERSION_TAG = "v$VERSION_NUM"
"VERSION=$VERSION_TAG" >> $env:GITHUB_ENV
- name: Check Version Tag
shell: pwsh
run: |
if (-not $env:VERSION) {
Write-Error "Version tag not found in csproj file."
exit 1
}
Write-Host "Version tag found: $env:VERSION"
- name: Tag merge commit
shell: pwsh
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag $env:VERSION
git push --tags
- name: Publish FrameworkDependent version
shell: pwsh
run: |
dotnet publish ${{ env.PROJECT_NAME }}/${{ env.PROJECT_NAME }}.csproj -c Release -r win-x64 --sc false -p:PublishSingleFile=true -o publish/${{ env.PROJECT_NAME }}-${{ env.VERSION }}
dotnet publish "$env:PROJECT_NAME\$env:PROJECT_NAME.csproj" -c Release -r win-x64 --sc false -o "publish\$env:PROJECT_NAME-$env:VERSION"
- name: Publish SelfContained version
shell: pwsh
run: |
dotnet publish ${{ env.PROJECT_NAME }}/${{ env.PROJECT_NAME }}.csproj -c Release -r win-x64 --sc true -p:PublishSingleFile=true -o publish/${{ env.PROJECT_NAME }}-${{ env.VERSION }}-SelfContained
dotnet publish "$env:PROJECT_NAME\$env:PROJECT_NAME.csproj" -c Release -r win-x64 --sc true -o "publish\$env:PROJECT_NAME-$env:VERSION-SelfContained"
- name: Create release directory
run: mkdir release
shell: pwsh
run: |
New-Item -ItemType Directory -Path release -Force | Out-Null
- name: Compress FrameworkDependent version
shell: pwsh
run: |
Compress-Archive -Path "publish/${env:PROJECT_NAME}-${env:VERSION}" -DestinationPath "release/${env:PROJECT_NAME}-${env:VERSION}.zip" -Force
Compress-Archive -Path "publish\$env:PROJECT_NAME-$env:VERSION\*" -DestinationPath "release\$env:PROJECT_NAME-$env:VERSION.zip" -Force
- name: Compress SelfContained version
shell: pwsh
run: |
Compress-Archive -Path "publish/${env:PROJECT_NAME}-${env:VERSION}-SelfContained" -DestinationPath "release/${env:PROJECT_NAME}-${env:VERSION}-SelfContained.zip" -Force
Compress-Archive -Path "publish\$env:PROJECT_NAME-$env:VERSION-SelfContained\*" -DestinationPath "release\$env:PROJECT_NAME-$env:VERSION-SelfContained.zip" -Force
- name: Create GitHub Release
id: create_release
uses: actions/create-release@v1
@@ -51,7 +85,7 @@ jobs:
release_name: Release ${{ env.VERSION }}
draft: false
prerelease: false
- name: Upload FrameworkDependent zip
uses: actions/upload-release-asset@v1
env:
@@ -61,7 +95,7 @@ jobs:
asset_path: release/${{ env.PROJECT_NAME }}-${{ env.VERSION }}.zip
asset_name: ${{ env.PROJECT_NAME }}-${{ env.VERSION }}.zip
asset_content_type: application/zip
- name: Upload SelfContained zip
uses: actions/upload-release-asset@v1
env:

View File

@@ -1,5 +1,37 @@
# CHANGELOG
## v0.12.17
- 动画边界检测的帧率提高到100帧每秒
## v0.12.16
- 导出多个时允许自动时长
## v0.12.15
- 修复附件类型枚举量字符串大小写问题
## v0.12.14
- 修复 v38 文件读取的小 bug
## v0.12.13
- 导出文件名增加额外的随机字符串
## v0.12.12
- 修复 2.1 版本遗漏的 SkinnedMeshAttachment 附件渲染
## v0.12.11
- 修复可能的闪退错误
## v0.12.10
- 增加纹理全局加载选项
## v0.12.9
- 修复由于未调用 UpdateCache 导致的约束 bug

View File

@@ -64,6 +64,10 @@
toolStripMenuItem_ExportCustom = new ToolStripMenuItem();
toolStripSeparator2 = new ToolStripSeparator();
toolStripMenuItem_Exit = new ToolStripMenuItem();
toolStripMenuItem_Texture = new ToolStripMenuItem();
toolStripMenuItem_ForceSmooth = new ToolStripMenuItem();
toolStripMenuItem_ForceRepeated = new ToolStripMenuItem();
toolStripMenuItem_ForceMipmap = new ToolStripMenuItem();
toolStripMenuItem_Tool = new ToolStripMenuItem();
toolStripMenuItem_ConvertFileFormat = new ToolStripMenuItem();
toolStripMenuItem_Download = new ToolStripMenuItem();
@@ -106,98 +110,80 @@
//
// splitContainer_MainForm
//
resources.ApplyResources(splitContainer_MainForm, "splitContainer_MainForm");
splitContainer_MainForm.Cursor = Cursors.SizeNS;
resources.ApplyResources(splitContainer_MainForm, "splitContainer_MainForm");
splitContainer_MainForm.FixedPanel = FixedPanel.Panel2;
splitContainer_MainForm.Name = "splitContainer_MainForm";
//
// splitContainer_MainForm.Panel1
//
resources.ApplyResources(splitContainer_MainForm.Panel1, "splitContainer_MainForm.Panel1");
splitContainer_MainForm.Panel1.Controls.Add(splitContainer_Functional);
splitContainer_MainForm.Panel1.Cursor = Cursors.Default;
toolTip.SetToolTip(splitContainer_MainForm.Panel1, resources.GetString("splitContainer_MainForm.Panel1.ToolTip"));
//
// splitContainer_MainForm.Panel2
//
resources.ApplyResources(splitContainer_MainForm.Panel2, "splitContainer_MainForm.Panel2");
splitContainer_MainForm.Panel2.Controls.Add(rtbLog);
splitContainer_MainForm.Panel2.Cursor = Cursors.Default;
toolTip.SetToolTip(splitContainer_MainForm.Panel2, resources.GetString("splitContainer_MainForm.Panel2.ToolTip"));
splitContainer_MainForm.TabStop = false;
toolTip.SetToolTip(splitContainer_MainForm, resources.GetString("splitContainer_MainForm.ToolTip"));
splitContainer_MainForm.SplitterMoved += splitContainer_SplitterMoved;
splitContainer_MainForm.MouseUp += splitContainer_MouseUp;
//
// splitContainer_Functional
//
resources.ApplyResources(splitContainer_Functional, "splitContainer_Functional");
splitContainer_Functional.Cursor = Cursors.SizeWE;
resources.ApplyResources(splitContainer_Functional, "splitContainer_Functional");
splitContainer_Functional.FixedPanel = FixedPanel.Panel1;
splitContainer_Functional.Name = "splitContainer_Functional";
//
// splitContainer_Functional.Panel1
//
resources.ApplyResources(splitContainer_Functional.Panel1, "splitContainer_Functional.Panel1");
splitContainer_Functional.Panel1.Controls.Add(splitContainer_Information);
splitContainer_Functional.Panel1.Cursor = Cursors.Default;
toolTip.SetToolTip(splitContainer_Functional.Panel1, resources.GetString("splitContainer_Functional.Panel1.ToolTip"));
//
// splitContainer_Functional.Panel2
//
resources.ApplyResources(splitContainer_Functional.Panel2, "splitContainer_Functional.Panel2");
splitContainer_Functional.Panel2.Controls.Add(groupBox_Preview);
splitContainer_Functional.Panel2.Cursor = Cursors.Default;
toolTip.SetToolTip(splitContainer_Functional.Panel2, resources.GetString("splitContainer_Functional.Panel2.ToolTip"));
splitContainer_Functional.TabStop = false;
toolTip.SetToolTip(splitContainer_Functional, resources.GetString("splitContainer_Functional.ToolTip"));
splitContainer_Functional.SplitterMoved += splitContainer_SplitterMoved;
splitContainer_Functional.MouseUp += splitContainer_MouseUp;
//
// splitContainer_Information
//
resources.ApplyResources(splitContainer_Information, "splitContainer_Information");
splitContainer_Information.Cursor = Cursors.SizeWE;
resources.ApplyResources(splitContainer_Information, "splitContainer_Information");
splitContainer_Information.Name = "splitContainer_Information";
//
// splitContainer_Information.Panel1
//
resources.ApplyResources(splitContainer_Information.Panel1, "splitContainer_Information.Panel1");
splitContainer_Information.Panel1.Controls.Add(groupBox_SkelList);
splitContainer_Information.Panel1.Cursor = Cursors.Default;
toolTip.SetToolTip(splitContainer_Information.Panel1, resources.GetString("splitContainer_Information.Panel1.ToolTip"));
//
// splitContainer_Information.Panel2
//
resources.ApplyResources(splitContainer_Information.Panel2, "splitContainer_Information.Panel2");
splitContainer_Information.Panel2.Controls.Add(splitContainer_Config);
splitContainer_Information.Panel2.Cursor = Cursors.Default;
toolTip.SetToolTip(splitContainer_Information.Panel2, resources.GetString("splitContainer_Information.Panel2.ToolTip"));
splitContainer_Information.TabStop = false;
toolTip.SetToolTip(splitContainer_Information, resources.GetString("splitContainer_Information.ToolTip"));
splitContainer_Information.SplitterMoved += splitContainer_SplitterMoved;
splitContainer_Information.MouseUp += splitContainer_MouseUp;
//
// groupBox_SkelList
//
resources.ApplyResources(groupBox_SkelList, "groupBox_SkelList");
groupBox_SkelList.Controls.Add(spineListView);
resources.ApplyResources(groupBox_SkelList, "groupBox_SkelList");
groupBox_SkelList.Name = "groupBox_SkelList";
groupBox_SkelList.TabStop = false;
toolTip.SetToolTip(groupBox_SkelList, resources.GetString("groupBox_SkelList.ToolTip"));
//
// spineListView
//
resources.ApplyResources(spineListView, "spineListView");
spineListView.Name = "spineListView";
spineListView.SpinePropertyGrid = spineViewPropertyGrid;
toolTip.SetToolTip(spineListView, resources.GetString("spineListView.ToolTip"));
//
// spineViewPropertyGrid
//
resources.ApplyResources(spineViewPropertyGrid, "spineViewPropertyGrid");
spineViewPropertyGrid.Name = "spineViewPropertyGrid";
toolTip.SetToolTip(spineViewPropertyGrid, resources.GetString("spineViewPropertyGrid.ToolTip"));
//
// splitContainer_Config
//
@@ -206,47 +192,38 @@
//
// splitContainer_Config.Panel1
//
resources.ApplyResources(splitContainer_Config.Panel1, "splitContainer_Config.Panel1");
splitContainer_Config.Panel1.Controls.Add(groupBox_PreviewConfig);
toolTip.SetToolTip(splitContainer_Config.Panel1, resources.GetString("splitContainer_Config.Panel1.ToolTip"));
//
// splitContainer_Config.Panel2
//
resources.ApplyResources(splitContainer_Config.Panel2, "splitContainer_Config.Panel2");
splitContainer_Config.Panel2.Controls.Add(groupBox_SkelConfig);
toolTip.SetToolTip(splitContainer_Config.Panel2, resources.GetString("splitContainer_Config.Panel2.ToolTip"));
toolTip.SetToolTip(splitContainer_Config, resources.GetString("splitContainer_Config.ToolTip"));
//
// groupBox_PreviewConfig
//
resources.ApplyResources(groupBox_PreviewConfig, "groupBox_PreviewConfig");
groupBox_PreviewConfig.Controls.Add(propertyGrid_Previewer);
resources.ApplyResources(groupBox_PreviewConfig, "groupBox_PreviewConfig");
groupBox_PreviewConfig.Name = "groupBox_PreviewConfig";
groupBox_PreviewConfig.TabStop = false;
toolTip.SetToolTip(groupBox_PreviewConfig, resources.GetString("groupBox_PreviewConfig.ToolTip"));
//
// propertyGrid_Previewer
//
resources.ApplyResources(propertyGrid_Previewer, "propertyGrid_Previewer");
propertyGrid_Previewer.Name = "propertyGrid_Previewer";
propertyGrid_Previewer.ToolbarVisible = false;
toolTip.SetToolTip(propertyGrid_Previewer, resources.GetString("propertyGrid_Previewer.ToolTip"));
//
// groupBox_SkelConfig
//
resources.ApplyResources(groupBox_SkelConfig, "groupBox_SkelConfig");
groupBox_SkelConfig.Controls.Add(spineViewPropertyGrid);
resources.ApplyResources(groupBox_SkelConfig, "groupBox_SkelConfig");
groupBox_SkelConfig.Name = "groupBox_SkelConfig";
groupBox_SkelConfig.TabStop = false;
toolTip.SetToolTip(groupBox_SkelConfig, resources.GetString("groupBox_SkelConfig.ToolTip"));
//
// groupBox_Preview
//
resources.ApplyResources(groupBox_Preview, "groupBox_Preview");
groupBox_Preview.Controls.Add(spinePreviewPanel);
resources.ApplyResources(groupBox_Preview, "groupBox_Preview");
groupBox_Preview.Name = "groupBox_Preview";
groupBox_Preview.TabStop = false;
toolTip.SetToolTip(groupBox_Preview, resources.GetString("groupBox_Preview.ToolTip"));
//
// spinePreviewPanel
//
@@ -254,230 +231,250 @@
spinePreviewPanel.Name = "spinePreviewPanel";
spinePreviewPanel.PropertyGrid = propertyGrid_Previewer;
spinePreviewPanel.SpineListView = spineListView;
toolTip.SetToolTip(spinePreviewPanel, resources.GetString("spinePreviewPanel.ToolTip"));
//
// rtbLog
//
resources.ApplyResources(rtbLog, "rtbLog");
rtbLog.BackColor = SystemColors.Window;
rtbLog.BorderStyle = BorderStyle.None;
resources.ApplyResources(rtbLog, "rtbLog");
rtbLog.Name = "rtbLog";
rtbLog.ReadOnly = true;
toolTip.SetToolTip(rtbLog, resources.GetString("rtbLog.ToolTip"));
//
// menuStrip
//
resources.ApplyResources(menuStrip, "menuStrip");
menuStrip.BackColor = SystemColors.Control;
menuStrip.ImageScalingSize = new Size(24, 24);
menuStrip.Items.AddRange(new ToolStripItem[] { toolStripMenuItem_File, toolStripMenuItem_Tool, toolStripMenuItem_Download, toolStripMenuItem_Help, toolStripMenuItem_Experiment, ToolStripMenuItem_Language });
menuStrip.Items.AddRange(new ToolStripItem[] { toolStripMenuItem_File, toolStripMenuItem_Texture, toolStripMenuItem_Tool, toolStripMenuItem_Download, toolStripMenuItem_Help, toolStripMenuItem_Experiment, ToolStripMenuItem_Language });
resources.ApplyResources(menuStrip, "menuStrip");
menuStrip.Name = "menuStrip";
toolTip.SetToolTip(menuStrip, resources.GetString("menuStrip.ToolTip"));
//
// toolStripMenuItem_File
//
resources.ApplyResources(toolStripMenuItem_File, "toolStripMenuItem_File");
toolStripMenuItem_File.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_Open, toolStripMenuItem_BatchOpen, toolStripSeparator1, toolStripMenuItem_Export, toolStripSeparator2, toolStripMenuItem_Exit });
toolStripMenuItem_File.Name = "toolStripMenuItem_File";
resources.ApplyResources(toolStripMenuItem_File, "toolStripMenuItem_File");
//
// toolStripMenuItem_Open
//
resources.ApplyResources(toolStripMenuItem_Open, "toolStripMenuItem_Open");
toolStripMenuItem_Open.Name = "toolStripMenuItem_Open";
resources.ApplyResources(toolStripMenuItem_Open, "toolStripMenuItem_Open");
toolStripMenuItem_Open.Click += toolStripMenuItem_Open_Click;
//
// toolStripMenuItem_BatchOpen
//
resources.ApplyResources(toolStripMenuItem_BatchOpen, "toolStripMenuItem_BatchOpen");
toolStripMenuItem_BatchOpen.Name = "toolStripMenuItem_BatchOpen";
resources.ApplyResources(toolStripMenuItem_BatchOpen, "toolStripMenuItem_BatchOpen");
toolStripMenuItem_BatchOpen.Click += toolStripMenuItem_BatchOpen_Click;
//
// toolStripSeparator1
//
resources.ApplyResources(toolStripSeparator1, "toolStripSeparator1");
toolStripSeparator1.Name = "toolStripSeparator1";
resources.ApplyResources(toolStripSeparator1, "toolStripSeparator1");
//
// toolStripMenuItem_Export
//
resources.ApplyResources(toolStripMenuItem_Export, "toolStripMenuItem_Export");
toolStripMenuItem_Export.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_ExportFrame, toolStripMenuItem_ExportFrameSequence, toolStripSeparator4, toolStripMenuItem_ExportGif, toolStripMenuItem_ExportWebp, toolStripMenuItem_ExportAvif, toolStripSeparator5, toolStripMenuItem_ExportMp4, toolStripMenuItem_ExportWebm, toolStripMenuItem_ExportMkv, toolStripMenuItem_ExportMov, toolStripSeparator6, toolStripMenuItem_ExportCustom });
toolStripMenuItem_Export.Name = "toolStripMenuItem_Export";
resources.ApplyResources(toolStripMenuItem_Export, "toolStripMenuItem_Export");
//
// toolStripMenuItem_ExportFrame
//
resources.ApplyResources(toolStripMenuItem_ExportFrame, "toolStripMenuItem_ExportFrame");
toolStripMenuItem_ExportFrame.Name = "toolStripMenuItem_ExportFrame";
resources.ApplyResources(toolStripMenuItem_ExportFrame, "toolStripMenuItem_ExportFrame");
toolStripMenuItem_ExportFrame.Click += toolStripMenuItem_ExportFrame_Click;
//
// toolStripMenuItem_ExportFrameSequence
//
resources.ApplyResources(toolStripMenuItem_ExportFrameSequence, "toolStripMenuItem_ExportFrameSequence");
toolStripMenuItem_ExportFrameSequence.Name = "toolStripMenuItem_ExportFrameSequence";
resources.ApplyResources(toolStripMenuItem_ExportFrameSequence, "toolStripMenuItem_ExportFrameSequence");
toolStripMenuItem_ExportFrameSequence.Click += toolStripMenuItem_ExportFrameSequence_Click;
//
// toolStripSeparator4
//
resources.ApplyResources(toolStripSeparator4, "toolStripSeparator4");
toolStripSeparator4.Name = "toolStripSeparator4";
resources.ApplyResources(toolStripSeparator4, "toolStripSeparator4");
//
// toolStripMenuItem_ExportGif
//
resources.ApplyResources(toolStripMenuItem_ExportGif, "toolStripMenuItem_ExportGif");
toolStripMenuItem_ExportGif.Name = "toolStripMenuItem_ExportGif";
resources.ApplyResources(toolStripMenuItem_ExportGif, "toolStripMenuItem_ExportGif");
toolStripMenuItem_ExportGif.Click += toolStripMenuItem_ExportGif_Click;
//
// toolStripMenuItem_ExportWebp
//
resources.ApplyResources(toolStripMenuItem_ExportWebp, "toolStripMenuItem_ExportWebp");
toolStripMenuItem_ExportWebp.Name = "toolStripMenuItem_ExportWebp";
resources.ApplyResources(toolStripMenuItem_ExportWebp, "toolStripMenuItem_ExportWebp");
toolStripMenuItem_ExportWebp.Click += toolStripMenuItem_ExportWebp_Click;
//
// toolStripMenuItem_ExportAvif
//
resources.ApplyResources(toolStripMenuItem_ExportAvif, "toolStripMenuItem_ExportAvif");
toolStripMenuItem_ExportAvif.Name = "toolStripMenuItem_ExportAvif";
resources.ApplyResources(toolStripMenuItem_ExportAvif, "toolStripMenuItem_ExportAvif");
toolStripMenuItem_ExportAvif.Click += toolStripMenuItem_ExportAvif_Click;
//
// toolStripSeparator5
//
resources.ApplyResources(toolStripSeparator5, "toolStripSeparator5");
toolStripSeparator5.Name = "toolStripSeparator5";
resources.ApplyResources(toolStripSeparator5, "toolStripSeparator5");
//
// toolStripMenuItem_ExportMp4
//
resources.ApplyResources(toolStripMenuItem_ExportMp4, "toolStripMenuItem_ExportMp4");
toolStripMenuItem_ExportMp4.Name = "toolStripMenuItem_ExportMp4";
resources.ApplyResources(toolStripMenuItem_ExportMp4, "toolStripMenuItem_ExportMp4");
toolStripMenuItem_ExportMp4.Click += toolStripMenuItem_ExportMp4_Click;
//
// toolStripMenuItem_ExportWebm
//
resources.ApplyResources(toolStripMenuItem_ExportWebm, "toolStripMenuItem_ExportWebm");
toolStripMenuItem_ExportWebm.Name = "toolStripMenuItem_ExportWebm";
resources.ApplyResources(toolStripMenuItem_ExportWebm, "toolStripMenuItem_ExportWebm");
toolStripMenuItem_ExportWebm.Click += toolStripMenuItem_ExportWebm_Click;
//
// toolStripMenuItem_ExportMkv
//
resources.ApplyResources(toolStripMenuItem_ExportMkv, "toolStripMenuItem_ExportMkv");
toolStripMenuItem_ExportMkv.Name = "toolStripMenuItem_ExportMkv";
resources.ApplyResources(toolStripMenuItem_ExportMkv, "toolStripMenuItem_ExportMkv");
toolStripMenuItem_ExportMkv.Click += toolStripMenuItem_ExportMkv_Click;
//
// toolStripMenuItem_ExportMov
//
resources.ApplyResources(toolStripMenuItem_ExportMov, "toolStripMenuItem_ExportMov");
toolStripMenuItem_ExportMov.Name = "toolStripMenuItem_ExportMov";
resources.ApplyResources(toolStripMenuItem_ExportMov, "toolStripMenuItem_ExportMov");
toolStripMenuItem_ExportMov.Click += toolStripMenuItem_ExportMov_Click;
//
// toolStripSeparator6
//
resources.ApplyResources(toolStripSeparator6, "toolStripSeparator6");
toolStripSeparator6.Name = "toolStripSeparator6";
resources.ApplyResources(toolStripSeparator6, "toolStripSeparator6");
//
// toolStripMenuItem_ExportCustom
//
resources.ApplyResources(toolStripMenuItem_ExportCustom, "toolStripMenuItem_ExportCustom");
toolStripMenuItem_ExportCustom.Name = "toolStripMenuItem_ExportCustom";
resources.ApplyResources(toolStripMenuItem_ExportCustom, "toolStripMenuItem_ExportCustom");
toolStripMenuItem_ExportCustom.Click += toolStripMenuItem_ExportCustom_Click;
//
// toolStripSeparator2
//
resources.ApplyResources(toolStripSeparator2, "toolStripSeparator2");
toolStripSeparator2.Name = "toolStripSeparator2";
resources.ApplyResources(toolStripSeparator2, "toolStripSeparator2");
//
// toolStripMenuItem_Exit
//
resources.ApplyResources(toolStripMenuItem_Exit, "toolStripMenuItem_Exit");
toolStripMenuItem_Exit.Name = "toolStripMenuItem_Exit";
resources.ApplyResources(toolStripMenuItem_Exit, "toolStripMenuItem_Exit");
toolStripMenuItem_Exit.Click += toolStripMenuItem_Exit_Click;
//
// toolStripMenuItem_Texture
//
toolStripMenuItem_Texture.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_ForceSmooth, toolStripMenuItem_ForceRepeated, toolStripMenuItem_ForceMipmap });
toolStripMenuItem_Texture.Name = "toolStripMenuItem_Texture";
resources.ApplyResources(toolStripMenuItem_Texture, "toolStripMenuItem_Texture");
//
// toolStripMenuItem_ForceSmooth
//
toolStripMenuItem_ForceSmooth.Name = "toolStripMenuItem_ForceSmooth";
resources.ApplyResources(toolStripMenuItem_ForceSmooth, "toolStripMenuItem_ForceSmooth");
toolStripMenuItem_ForceSmooth.Click += toolStripMenuItem_ForceSmooth_Click;
//
// toolStripMenuItem_ForceRepeated
//
toolStripMenuItem_ForceRepeated.Name = "toolStripMenuItem_ForceRepeated";
resources.ApplyResources(toolStripMenuItem_ForceRepeated, "toolStripMenuItem_ForceRepeated");
toolStripMenuItem_ForceRepeated.Click += toolStripMenuItem_ForceRepeated_Click;
//
// toolStripMenuItem_ForceMipmap
//
toolStripMenuItem_ForceMipmap.Name = "toolStripMenuItem_ForceMipmap";
resources.ApplyResources(toolStripMenuItem_ForceMipmap, "toolStripMenuItem_ForceMipmap");
toolStripMenuItem_ForceMipmap.Click += toolStripMenuItem_ForceMipmap_Click;
//
// toolStripMenuItem_Tool
//
resources.ApplyResources(toolStripMenuItem_Tool, "toolStripMenuItem_Tool");
toolStripMenuItem_Tool.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_ConvertFileFormat });
toolStripMenuItem_Tool.Name = "toolStripMenuItem_Tool";
resources.ApplyResources(toolStripMenuItem_Tool, "toolStripMenuItem_Tool");
//
// toolStripMenuItem_ConvertFileFormat
//
resources.ApplyResources(toolStripMenuItem_ConvertFileFormat, "toolStripMenuItem_ConvertFileFormat");
toolStripMenuItem_ConvertFileFormat.Name = "toolStripMenuItem_ConvertFileFormat";
resources.ApplyResources(toolStripMenuItem_ConvertFileFormat, "toolStripMenuItem_ConvertFileFormat");
toolStripMenuItem_ConvertFileFormat.Click += toolStripMenuItem_ConvertFileFormat_Click;
//
// toolStripMenuItem_Download
//
resources.ApplyResources(toolStripMenuItem_Download, "toolStripMenuItem_Download");
toolStripMenuItem_Download.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_ManageResource });
toolStripMenuItem_Download.Name = "toolStripMenuItem_Download";
resources.ApplyResources(toolStripMenuItem_Download, "toolStripMenuItem_Download");
//
// toolStripMenuItem_ManageResource
//
resources.ApplyResources(toolStripMenuItem_ManageResource, "toolStripMenuItem_ManageResource");
toolStripMenuItem_ManageResource.Name = "toolStripMenuItem_ManageResource";
resources.ApplyResources(toolStripMenuItem_ManageResource, "toolStripMenuItem_ManageResource");
toolStripMenuItem_ManageResource.Click += toolStripMenuItem_ManageResource_Click;
//
// toolStripMenuItem_Help
//
resources.ApplyResources(toolStripMenuItem_Help, "toolStripMenuItem_Help");
toolStripMenuItem_Help.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_Diagnostics, toolStripSeparator3, toolStripMenuItem_About, toolStripMenuItem_Debug });
toolStripMenuItem_Help.Name = "toolStripMenuItem_Help";
resources.ApplyResources(toolStripMenuItem_Help, "toolStripMenuItem_Help");
//
// toolStripMenuItem_Diagnostics
//
resources.ApplyResources(toolStripMenuItem_Diagnostics, "toolStripMenuItem_Diagnostics");
toolStripMenuItem_Diagnostics.Name = "toolStripMenuItem_Diagnostics";
resources.ApplyResources(toolStripMenuItem_Diagnostics, "toolStripMenuItem_Diagnostics");
toolStripMenuItem_Diagnostics.Click += toolStripMenuItem_Diagnostics_Click;
//
// toolStripSeparator3
//
resources.ApplyResources(toolStripSeparator3, "toolStripSeparator3");
toolStripSeparator3.Name = "toolStripSeparator3";
resources.ApplyResources(toolStripSeparator3, "toolStripSeparator3");
//
// toolStripMenuItem_About
//
resources.ApplyResources(toolStripMenuItem_About, "toolStripMenuItem_About");
toolStripMenuItem_About.Name = "toolStripMenuItem_About";
resources.ApplyResources(toolStripMenuItem_About, "toolStripMenuItem_About");
toolStripMenuItem_About.Click += toolStripMenuItem_About_Click;
//
// toolStripMenuItem_Debug
//
resources.ApplyResources(toolStripMenuItem_Debug, "toolStripMenuItem_Debug");
toolStripMenuItem_Debug.Name = "toolStripMenuItem_Debug";
resources.ApplyResources(toolStripMenuItem_Debug, "toolStripMenuItem_Debug");
toolStripMenuItem_Debug.Click += toolStripMenuItem_Debug_Click;
//
// toolStripMenuItem_Experiment
//
resources.ApplyResources(toolStripMenuItem_Experiment, "toolStripMenuItem_Experiment");
toolStripMenuItem_Experiment.DropDownItems.AddRange(new ToolStripItem[] { toolStripMenuItem_DesktopProjection });
toolStripMenuItem_Experiment.Name = "toolStripMenuItem_Experiment";
resources.ApplyResources(toolStripMenuItem_Experiment, "toolStripMenuItem_Experiment");
//
// toolStripMenuItem_DesktopProjection
//
resources.ApplyResources(toolStripMenuItem_DesktopProjection, "toolStripMenuItem_DesktopProjection");
toolStripMenuItem_DesktopProjection.Name = "toolStripMenuItem_DesktopProjection";
resources.ApplyResources(toolStripMenuItem_DesktopProjection, "toolStripMenuItem_DesktopProjection");
toolStripMenuItem_DesktopProjection.Click += toolStripMenuItem_DesktopProjection_Click;
//
// ToolStripMenuItem_Language
//
resources.ApplyResources(ToolStripMenuItem_Language, "ToolStripMenuItem_Language");
ToolStripMenuItem_Language.DropDownItems.AddRange(new ToolStripItem[] { ToolStripMenuItem_English, ToolStripMenuItem_Chinese });
ToolStripMenuItem_Language.Name = "ToolStripMenuItem_Language";
resources.ApplyResources(ToolStripMenuItem_Language, "ToolStripMenuItem_Language");
//
// ToolStripMenuItem_English
//
resources.ApplyResources(ToolStripMenuItem_English, "ToolStripMenuItem_English");
ToolStripMenuItem_English.Name = "ToolStripMenuItem_English";
resources.ApplyResources(ToolStripMenuItem_English, "ToolStripMenuItem_English");
ToolStripMenuItem_English.Click += ToolStripMenuItem_English_Click;
//
// ToolStripMenuItem_Chinese
//
resources.ApplyResources(ToolStripMenuItem_Chinese, "ToolStripMenuItem_Chinese");
ToolStripMenuItem_Chinese.Name = "ToolStripMenuItem_Chinese";
resources.ApplyResources(ToolStripMenuItem_Chinese, "ToolStripMenuItem_Chinese");
ToolStripMenuItem_Chinese.Click += ToolStripMenuItem_Chinese_Click;
//
// panel_MainForm
//
resources.ApplyResources(panel_MainForm, "panel_MainForm");
panel_MainForm.Controls.Add(splitContainer_MainForm);
resources.ApplyResources(panel_MainForm, "panel_MainForm");
panel_MainForm.Name = "panel_MainForm";
toolTip.SetToolTip(panel_MainForm, resources.GetString("panel_MainForm.ToolTip"));
//
// toolTip
//
@@ -491,7 +488,6 @@
Controls.Add(menuStrip);
MainMenuStrip = menuStrip;
Name = "SpineViewerForm";
toolTip.SetToolTip(this, resources.GetString("$this.ToolTip"));
FormClosing += MainForm_FormClosing;
Load += MainForm_Load;
splitContainer_MainForm.Panel1.ResumeLayout(false);
@@ -573,5 +569,9 @@
private ToolStripMenuItem ToolStripMenuItem_Language;
private ToolStripMenuItem ToolStripMenuItem_English;
private ToolStripMenuItem ToolStripMenuItem_Chinese;
}
private ToolStripMenuItem toolStripMenuItem_Texture;
private ToolStripMenuItem toolStripMenuItem_ForceSmooth;
private ToolStripMenuItem toolStripMenuItem_ForceRepeated;
private ToolStripMenuItem toolStripMenuItem_ForceMipmap;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -119,7 +119,7 @@
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="groupBox_SkelList.Size" type="System.Drawing.Size, System.Drawing">
<value>350, 808</value>
<value>350, 804</value>
</data>
<data name="groupBox_SkelList.Text" xml:space="preserve">
<value>Model List</value>
@@ -131,7 +131,7 @@
<value />
</data>
<data name="groupBox_PreviewConfig.Size" type="System.Drawing.Size, System.Drawing">
<value>430, 267</value>
<value>430, 265</value>
</data>
<data name="groupBox_PreviewConfig.Text" xml:space="preserve">
<value>Image Parameters</value>
@@ -143,7 +143,7 @@
<value />
</data>
<data name="groupBox_SkelConfig.Size" type="System.Drawing.Size, System.Drawing">
<value>430, 533</value>
<value>430, 531</value>
</data>
<data name="groupBox_SkelConfig.Text" xml:space="preserve">
<value>Model Parameters</value>
@@ -155,11 +155,11 @@
<value />
</data>
<data name="splitContainer_Config.Size" type="System.Drawing.Size, System.Drawing">
<value>430, 808</value>
<value>430, 804</value>
</data>
<assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="splitContainer_Config.SplitterDistance" type="System.Int32, mscorlib">
<value>267</value>
<value>265</value>
</data>
<data name="splitContainer_Config.ToolTip" xml:space="preserve">
<value />
@@ -168,7 +168,7 @@
<value />
</data>
<data name="splitContainer_Information.Size" type="System.Drawing.Size, System.Drawing">
<value>788, 808</value>
<value>788, 804</value>
</data>
<data name="splitContainer_Information.ToolTip" xml:space="preserve">
<value />
@@ -177,7 +177,7 @@
<value />
</data>
<data name="groupBox_Preview.Size" type="System.Drawing.Size, System.Drawing">
<value>962, 808</value>
<value>962, 804</value>
</data>
<data name="groupBox_Preview.Text" xml:space="preserve">
<value>Preview Screen</value>
@@ -189,7 +189,7 @@
<value />
</data>
<data name="splitContainer_Functional.Size" type="System.Drawing.Size, System.Drawing">
<value>1758, 808</value>
<value>1758, 804</value>
</data>
<data name="splitContainer_Functional.ToolTip" xml:space="preserve">
<value />
@@ -198,7 +198,7 @@
<value />
</data>
<data name="rtbLog.Size" type="System.Drawing.Size, System.Drawing">
<value>1758, 188</value>
<value>1758, 192</value>
</data>
<data name="rtbLog.ToolTip" xml:space="preserve">
<value />
@@ -207,16 +207,16 @@
<value />
</data>
<data name="splitContainer_MainForm.SplitterDistance" type="System.Int32, mscorlib">
<value>808</value>
<value>804</value>
</data>
<data name="splitContainer_MainForm.ToolTip" xml:space="preserve">
<value />
</data>
<data name="spineListView.Size" type="System.Drawing.Size, System.Drawing">
<value>346, 781</value>
<value>346, 777</value>
</data>
<data name="spineViewPropertyGrid.Size" type="System.Drawing.Size, System.Drawing">
<value>426, 506</value>
<value>426, 504</value>
</data>
<data name="spineViewPropertyGrid.ToolTip" xml:space="preserve">
<value />
@@ -225,13 +225,13 @@
<value />
</data>
<data name="propertyGrid_Previewer.Size" type="System.Drawing.Size, System.Drawing">
<value>426, 240</value>
<value>426, 238</value>
</data>
<data name="propertyGrid_Previewer.ToolTip" xml:space="preserve">
<value />
</data>
<data name="spinePreviewPanel.Size" type="System.Drawing.Size, System.Drawing">
<value>958, 781</value>
<value>958, 777</value>
</data>
<data name="spinePreviewPanel.ToolTip" xml:space="preserve">
<value />
@@ -246,22 +246,22 @@
<value>File(&amp;F)</value>
</data>
<data name="toolStripMenuItem_Open.Size" type="System.Drawing.Size, System.Drawing">
<value>270, 34</value>
<value>266, 34</value>
</data>
<data name="toolStripMenuItem_Open.Text" xml:space="preserve">
<value>Open(&amp;O)...</value>
</data>
<data name="toolStripMenuItem_BatchOpen.Size" type="System.Drawing.Size, System.Drawing">
<value>270, 34</value>
<value>266, 34</value>
</data>
<data name="toolStripMenuItem_BatchOpen.Text" xml:space="preserve">
<value>Batch Open(&amp;B)...</value>
</data>
<data name="toolStripSeparator1.Size" type="System.Drawing.Size, System.Drawing">
<value>267, 6</value>
<value>263, 6</value>
</data>
<data name="toolStripMenuItem_Export.Size" type="System.Drawing.Size, System.Drawing">
<value>270, 34</value>
<value>266, 34</value>
</data>
<data name="toolStripMenuItem_Export.Text" xml:space="preserve">
<value>Export(&amp;E)</value>
@@ -315,14 +315,29 @@
<value>FFmpeg Custom Export...</value>
</data>
<data name="toolStripSeparator2.Size" type="System.Drawing.Size, System.Drawing">
<value>267, 6</value>
<value>263, 6</value>
</data>
<data name="toolStripMenuItem_Exit.Size" type="System.Drawing.Size, System.Drawing">
<value>270, 34</value>
<value>266, 34</value>
</data>
<data name="toolStripMenuItem_Exit.Text" xml:space="preserve">
<value>Exit(&amp;X)</value>
</data>
<data name="toolStripMenuItem_Texture.Size" type="System.Drawing.Size, System.Drawing">
<value>112, 32</value>
</data>
<data name="toolStripMenuItem_Texture.Text" xml:space="preserve">
<value>Texture(&amp;E)</value>
</data>
<data name="toolStripMenuItem_ForceSmooth.Text" xml:space="preserve">
<value>Force Smooth</value>
</data>
<data name="toolStripMenuItem_ForceRepeated.Text" xml:space="preserve">
<value>Force Repeated</value>
</data>
<data name="toolStripMenuItem_ForceMipmap.Text" xml:space="preserve">
<value>Force Mipmap</value>
</data>
<data name="toolStripMenuItem_Tool.Size" type="System.Drawing.Size, System.Drawing">
<value>93, 32</value>
</data>
@@ -392,12 +407,6 @@
<data name="ToolStripMenuItem_Language.Text" xml:space="preserve">
<value>Language(&amp;L)</value>
</data>
<data name="ToolStripMenuItem_English.Size" type="System.Drawing.Size, System.Drawing">
<value>270, 34</value>
</data>
<data name="ToolStripMenuItem_Chinese.Size" type="System.Drawing.Size, System.Drawing">
<value>270, 34</value>
</data>
<data name="panel_MainForm.ToolTip" xml:space="preserve">
<value />
</data>

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
using NLog;
using SpineViewer.Spine.Implementations.SkeletonConverter;
using SpineViewer.Utils;
using SpineViewer.Utils.Localize;
using System.Configuration;
@@ -45,16 +46,16 @@ namespace SpineViewer
{
// 此处先初始化全局配置再触发静态字段 Logger 引用构造, 才能将配置应用到新的日志器上
InitializeLogConfiguration();
logger.Info("Program Started");
logger.Info("Program Started");
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
// To customize application configuration such as set high DPI settings or default font,
// see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
LocalizeConfiguration.SetCulture();
try
try
{
Application.Run(new SpineViewerForm() { Text = $"SpineViewer - v{Version}"});
Application.Run(new SpineViewerForm() { Text = $"SpineViewer - v{Version}" });
}
catch (Exception ex)
{

View File

@@ -51,6 +51,17 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
[RotateMode.ChainScale] = "chainScale",
};
private static readonly Dictionary<AttachmentType, string> AttachmentTypeJsonValue = new()
{
[AttachmentType.Region] = "region",
[AttachmentType.Boundingbox] = "bounding",
[AttachmentType.Mesh] = "mesh",
[AttachmentType.Linkedmesh] = "linkedmesh",
[AttachmentType.Path] = "path",
[AttachmentType.Point] = "point",
[AttachmentType.Clipping] = "clipping",
};
private BinaryReader reader = null;
private JsonObject root = null;
private bool nonessential = false;
@@ -298,7 +309,7 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
var name = reader.ReadStringRef() ?? keyName;
var type = (AttachmentType)reader.ReadByte();
attachment["name"] = name;
attachment["type"] = type.ToString();
attachment["type"] = AttachmentTypeJsonValue[type];
switch (type)
{
case AttachmentType.Region:
@@ -586,7 +597,7 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
["compress"] = reader.ReadBoolean(),
["stretch"] = reader.ReadBoolean(),
};
if (frameCount > 1) ReadCurve(o);
if (frameIdx < frameCount - 1) ReadCurve(o);
frames.Add(o);
}
}
@@ -613,7 +624,7 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
["scaleMix"] = reader.ReadFloat(),
["shearMix"] = reader.ReadFloat(),
};
if (frameCount > 1) ReadCurve(o);
if (frameIdx < frameCount - 1) ReadCurve(o);
frames.Add(o);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -52,7 +52,7 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
[AttachmentType.Region] = "region",
[AttachmentType.Boundingbox] = "bounding",
[AttachmentType.Mesh] = "mesh",
[AttachmentType.Linkedmesh] = "linkedMesh",
[AttachmentType.Linkedmesh] = "linkedmesh",
[AttachmentType.Path] = "path",
[AttachmentType.Point] = "point",
[AttachmentType.Clipping] = "clipping",
@@ -294,7 +294,7 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
data["inertia"] = reader.ReadFloat();
data["strength"] = reader.ReadFloat();
data["damping"] = reader.ReadFloat();
if ((flags & 128) != 0) data["mass"] = reader.ReadFloat();
if ((flags & 128) != 0) data["mass"] = 1.0f / reader.ReadFloat(); //在binary中存储的是质量的倒数在json中存储的是质量
data["wind"] = reader.ReadFloat();
data["gravity"] = reader.ReadFloat();
@@ -325,6 +325,21 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
// other skins
for (int n = reader.ReadVarInt(); n > 0; n--)
skins.Add(ReadSkin());
//处理linkedmesh的问题后面有相关代码和注释
foreach (JsonObject skin in skins)
{
foreach (var (_, slot) in skin["attachments"].AsObject())
{
foreach (var (_, attachment) in slot.AsObject())
{
if ((string)attachment["type"] == "linkedMesh")
{
attachment["skin"] = (string)skins[(int)attachment["skin"]]["name"];
}
}
}
}
}
private JsonObject? ReadSkin(bool isDefault = false)
@@ -423,7 +438,9 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
if ((flags & 32) != 0) attachment["color"] = reader.ReadInt().ToString("x8");
if ((flags & 64) != 0) attachment["sequence"] = ReadSequence();
if ((flags & 128) == 0) attachment["timelines"] = false;
attachment["skin"] = (string)skins[reader.ReadVarInt()]["name"];
//attachment["skin"] = (string)skins[reader.ReadVarInt()]["name"];
//还是那个mix-and-match4.2版本的mix-and-match出现了读取错误,后面写的时候也一样linkedmesh的skin为后面还未访问的skin
attachment["skin"] = reader.ReadVarInt();
attachment["parent"] = reader.ReadStringRef();
if (nonessential)
{
@@ -1052,14 +1069,14 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
{
["time"] = reader.ReadFloat(),
};
ReadCurve(frame, 1);
frame = o;
end = reader.ReadVarInt();
if (end > 0)
{
frame["offset"] = reader.ReadVarInt();
frame["vertices"] = ReadFloatArray(end);
}
ReadCurve(frame, 1);
frame = o;
frames.Add(frame);
}
break;
@@ -1084,7 +1101,7 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
}
return attachmentTimelines.Count > 0 ? attachmentTimelines : null;
}
private JsonArray? ReadDrawOrderTimelines()
{
JsonArray slots = root["slots"].AsArray();
@@ -1500,7 +1517,7 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
writer.WriteFloat((float)(data["inertia"] ?? 1f));
writer.WriteFloat((float)(data["strength"] ?? 100f));
writer.WriteFloat((float)(data["damping"] ?? 1f));
if ((flags & 128) != 0) writer.WriteFloat(1f / (float)data["mass"]);
if ((flags & 128) != 0) writer.WriteFloat(1f / (float)data["mass"]);
writer.WriteFloat((float)(data["wind"] ?? 0f));
writer.WriteFloat((float)(data["gravity"] ?? 0f));
@@ -1528,8 +1545,26 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
writer.WriteVarInt(0); // 其他皮肤数量
return;
}
//此处还是得先把数据全读了反面例子还是那个mix-and-match4.2版本的mix-and-match中default用到了后面的skin,转换失败
//mix-and-match的full-skins/boy这个skin他的linkedmesh调用了后面的full-skins/boy
JsonArray skins = root["skins"].AsArray();
foreach (JsonObject sk in skins)
{
if ((string)sk["name"] == "default")
{
skin2idx["default"] = 0;
break;
}
}
foreach (JsonObject sk in skins)
{
if ((string)sk["name"] != "default")
{
skin2idx["default"] = skin2idx.Count;
}
}
bool hasDefault = false;
foreach (JsonObject skin in skins)
{
@@ -1537,7 +1572,7 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
{
hasDefault = true;
WriteSkin(skin, true);
skin2idx["default"] = skin2idx.Count;
//skin2idx["default"] = skin2idx.Count;
break;
}
}
@@ -1558,7 +1593,7 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
if (name != "default")
{
WriteSkin(skin);
skin2idx[name] = skin2idx.Count;
//skin2idx[name] = skin2idx.Count;
}
}
}
@@ -1960,7 +1995,7 @@ namespace SpineViewer.Spine.Implementations.SkeletonConverter
}
continue;
}
if (type == "rotate")
{
writer.WriteByte(SkeletonBinary.BONE_ROTATE);

View File

@@ -29,26 +29,6 @@ namespace SpineViewer.Spine.Implementations.SpineObject
// };
//}
private class TextureLoader : SpineRuntime21.TextureLoader
{
public void Load(AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == TextureFilter.Linear)
texture.Smooth = true;
if (page.uWrap == TextureWrap.Repeat && page.vWrap == TextureWrap.Repeat)
texture.Repeated = true;
page.rendererObject = texture;
}
public void Unload(object texture)
{
((SFML.Graphics.Texture)texture).Dispose();
}
}
private readonly static TextureLoader textureLoader = new();
private static readonly Animation EmptyAnimation = new(EMPTY_ANIMATION, [], 0);
private readonly Atlas atlas;
@@ -70,7 +50,8 @@ namespace SpineViewer.Spine.Implementations.SpineObject
public SpineObject21(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try { atlas = new Atlas(AtlasPath, textureLoader); }
catch (Exception ex) { throw new InvalidDataException($"Failed to load atlas '{atlasPath}'", ex); }
try
{
// 先尝试二进制文件
@@ -90,6 +71,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}");
}
}
@@ -116,7 +98,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
atlas.Dispose();
atlas?.Dispose();
}
public override string FileVersion { get => skeletonData.Version; }
@@ -240,10 +222,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject
tmpSkeleton.Update(0);
tmpSkeleton.UpdateWorldTransform();
// 按 10 帧每秒计算边框
// 按 100 帧每秒计算边框
var bounds = getCurrentBounds();
float[] _ = [];
for (float tick = 0, delta = 0.1f; tick < maxDuration; tick += delta)
for (float tick = 0, delta = 0.01f; tick < maxDuration; tick += delta)
{
tmpSkeleton.GetBounds(out var x, out var y, out var w, out var h);
bounds = bounds.Union(new(x, y, w, h));
@@ -278,7 +260,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
SFML.Graphics.Texture texture;
float[] worldVertices = worldVerticesBuffer; // 顶点世界坐标, 连续的 [x0, y0, x1, y1, ...] 坐标值
int worldVerticesCount; // 等于顶点数组的长度除以 2
//int worldVerticesCount; // 等于顶点数组的长度除以 2
int[] worldTriangleIndices; // 三角形索引, 从顶点坐标数组取的时候要乘以 2, 最大值是 worldVerticesCount - 1
int worldTriangleIndicesLength; // 三角形索引数组长度
float[] uvs; // 纹理坐标
@@ -292,7 +274,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
texture = (SFML.Graphics.Texture)((AtlasRegion)regionAttachment.RendererObject).page.rendererObject;
regionAttachment.ComputeWorldVertices(slot.Bone, worldVertices);
worldVerticesCount = 4;
//worldVerticesCount = 4;
worldTriangleIndices = [0, 1, 2, 2, 3, 0];
worldTriangleIndicesLength = 6;
uvs = regionAttachment.UVs;
@@ -308,7 +290,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
if (meshAttachment.Vertices.Length > worldVertices.Length)
worldVertices = worldVerticesBuffer = new float[meshAttachment.Vertices.Length * 2];
meshAttachment.ComputeWorldVertices(slot, worldVertices);
worldVerticesCount = meshAttachment.Vertices.Length / 2;
//worldVerticesCount = meshAttachment.Vertices.Length / 2;
worldTriangleIndices = meshAttachment.Triangles;
worldTriangleIndicesLength = meshAttachment.Triangles.Length;
uvs = meshAttachment.UVs;
@@ -317,6 +299,22 @@ namespace SpineViewer.Spine.Implementations.SpineObject
tintB *= meshAttachment.B;
tintA *= meshAttachment.A;
}
else if (attachment is SkinnedMeshAttachment skinnedMeshAttachment)
{
texture = (SFML.Graphics.Texture)((AtlasRegion)skinnedMeshAttachment.RendererObject).page.rendererObject;
if (skinnedMeshAttachment.UVs.Length > worldVertices.Length)
worldVertices = worldVerticesBuffer = new float[skinnedMeshAttachment.UVs.Length * 2];
skinnedMeshAttachment.ComputeWorldVertices(slot, worldVertices);
//worldVerticesCount = skinnedMeshAttachment.Vertices.Length / 2;
worldTriangleIndices = skinnedMeshAttachment.Triangles;
worldTriangleIndicesLength = skinnedMeshAttachment.Triangles.Length;
uvs = skinnedMeshAttachment.UVs;
tintR *= skinnedMeshAttachment.R;
tintG *= skinnedMeshAttachment.G;
tintB *= skinnedMeshAttachment.B;
tintA *= skinnedMeshAttachment.A;
}
// 2.1.x 不支持剪裁
//else if (attachment is ClippingAttachment clippingAttachment)
//{
@@ -450,6 +448,37 @@ namespace SpineViewer.Spine.Implementations.SpineObject
vt.Position.Y = worldVerticesBuffer[idx2 + 1];
lineVertices.Append(vt); lineVertices.Append(vt);
vt.Position.X = worldVerticesBuffer[idx0];
vt.Position.Y = worldVerticesBuffer[idx0 + 1];
lineVertices.Append(vt);
}
}
else if (slot.Attachment is SkinnedMeshAttachment skinnedMeshAttachment)
{
if (skinnedMeshAttachment.UVs.Length > worldVerticesBuffer.Length)
worldVerticesBuffer = new float[skinnedMeshAttachment.UVs.Length * 2];
skinnedMeshAttachment.ComputeWorldVertices(slot, worldVerticesBuffer);
var triangleIndices = skinnedMeshAttachment.Triangles;
for (int i = 0; i < triangleIndices.Length; i += 3)
{
var idx0 = triangleIndices[i] * 2;
var idx1 = triangleIndices[i + 1] * 2;
var idx2 = triangleIndices[i + 2] * 2;
vt.Position.X = worldVerticesBuffer[idx0];
vt.Position.Y = worldVerticesBuffer[idx0 + 1];
lineVertices.Append(vt);
vt.Position.X = worldVerticesBuffer[idx1];
vt.Position.Y = worldVerticesBuffer[idx1 + 1];
lineVertices.Append(vt); lineVertices.Append(vt);
vt.Position.X = worldVerticesBuffer[idx2];
vt.Position.Y = worldVerticesBuffer[idx2 + 1];
lineVertices.Append(vt); lineVertices.Append(vt);
vt.Position.X = worldVerticesBuffer[idx0];
vt.Position.Y = worldVerticesBuffer[idx0 + 1];
lineVertices.Append(vt);
@@ -472,6 +501,34 @@ namespace SpineViewer.Spine.Implementations.SpineObject
var hullLength = (meshAttachment.HullLength >> 1) << 1;
if (debugMeshHulls && hullLength > 2)
{
vt.Position.X = worldVerticesBuffer[0];
vt.Position.Y = worldVerticesBuffer[1];
lineVertices.Append(vt);
for (int i = 2; i < hullLength; i += 2)
{
vt.Position.X = worldVerticesBuffer[i];
vt.Position.Y = worldVerticesBuffer[i + 1];
lineVertices.Append(vt);
lineVertices.Append(vt);
}
vt.Position.X = worldVerticesBuffer[0];
vt.Position.Y = worldVerticesBuffer[1];
lineVertices.Append(vt);
}
}
else if (slot.Attachment is SkinnedMeshAttachment skinnedMeshAttachment)
{
if (skinnedMeshAttachment.UVs.Length > worldVerticesBuffer.Length)
worldVerticesBuffer = new float[skinnedMeshAttachment.UVs.Length * 2];
skinnedMeshAttachment.ComputeWorldVertices(slot, worldVerticesBuffer);
var hullLength = (skinnedMeshAttachment.HullLength >> 1) << 1;
if (debugMeshHulls && hullLength > 2)
{
vt.Position.X = worldVerticesBuffer[0];

View File

@@ -29,26 +29,6 @@ namespace SpineViewer.Spine.Implementations.SpineObject
};
}
private class TextureLoader : SpineRuntime36.TextureLoader
{
public void Load(AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == TextureFilter.Linear)
texture.Smooth = true;
if (page.uWrap == TextureWrap.Repeat && page.vWrap == TextureWrap.Repeat)
texture.Repeated = true;
page.rendererObject = texture;
}
public void Unload(object texture)
{
((SFML.Graphics.Texture)texture).Dispose();
}
}
private static readonly TextureLoader textureLoader = new();
private static readonly Animation EmptyAnimation = new(EMPTY_ANIMATION, [], 0);
private readonly Atlas atlas;
@@ -69,7 +49,8 @@ namespace SpineViewer.Spine.Implementations.SpineObject
public SpineObject36(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try { atlas = new Atlas(AtlasPath, textureLoader); }
catch (Exception ex) { throw new InvalidDataException($"Failed to load atlas '{atlasPath}'", ex); }
try
{
// 先尝试二进制文件
@@ -89,6 +70,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}");
}
}
@@ -115,7 +97,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
atlas.Dispose();
atlas?.Dispose();
}
public override string FileVersion { get => skeletonData.Version; }
@@ -240,10 +222,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject
tmpSkeleton.Update(0);
tmpSkeleton.UpdateWorldTransform();
// 按 10 帧每秒计算边框
// 按 100 帧每秒计算边框
var bounds = getCurrentBounds();
float[] _ = [];
for (float tick = 0, delta = 0.1f; tick < maxDuration; tick += delta)
for (float tick = 0, delta = 0.01f; tick < maxDuration; tick += delta)
{
tmpSkeleton.GetBounds(out var x, out var y, out var w, out var h, ref _);
bounds = bounds.Union(new(x, y, w, h));

View File

@@ -26,26 +26,6 @@ namespace SpineViewer.Spine.Implementations.SpineObject
};
}
private class TextureLoader : SpineRuntime37.TextureLoader
{
public void Load(AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == TextureFilter.Linear)
texture.Smooth = true;
if (page.uWrap == TextureWrap.Repeat && page.vWrap == TextureWrap.Repeat)
texture.Repeated = true;
page.rendererObject = texture;
}
public void Unload(object texture)
{
((SFML.Graphics.Texture)texture).Dispose();
}
}
private static readonly TextureLoader textureLoader = new();
private static readonly Animation EmptyAnimation = new(EMPTY_ANIMATION, [], 0);
private readonly Atlas atlas;
@@ -66,7 +46,8 @@ namespace SpineViewer.Spine.Implementations.SpineObject
public SpineObject37(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try { atlas = new Atlas(AtlasPath, textureLoader); }
catch (Exception ex) { throw new InvalidDataException($"Failed to load atlas '{atlasPath}'", ex); }
try
{
// 先尝试二进制文件
@@ -86,6 +67,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}");
}
}
@@ -112,7 +94,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
atlas.Dispose();
atlas?.Dispose();
}
public override string FileVersion { get => skeletonData.Version; }
@@ -237,10 +219,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject
tmpSkeleton.Update(0);
tmpSkeleton.UpdateWorldTransform();
// 按 10 帧每秒计算边框
// 按 100 帧每秒计算边框
var bounds = getCurrentBounds();
float[] _ = [];
for (float tick = 0, delta = 0.1f; tick < maxDuration; tick += delta)
for (float tick = 0, delta = 0.01f; tick < maxDuration; tick += delta)
{
tmpSkeleton.GetBounds(out var x, out var y, out var w, out var h, ref _);
bounds = bounds.Union(new(x, y, w, h));

View File

@@ -30,29 +30,6 @@ namespace SpineViewer.Spine.Implementations.SpineObject
};
}
private class TextureLoader : SpineRuntime38.TextureLoader
{
public void Load(AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == TextureFilter.Linear)
texture.Smooth = true;
if (page.uWrap == TextureWrap.Repeat && page.vWrap == TextureWrap.Repeat)
texture.Repeated = true;
page.rendererObject = texture;
// 似乎是不需要设置的, 因为存在某些 png 和 atlas 大小不同的情况, 一般是有一些缩放, 如果设置了反而渲染异常
// page.width = (int)texture.Size.X;
// page.height = (int)texture.Size.Y;
}
public void Unload(object texture)
{
((SFML.Graphics.Texture)texture).Dispose();
}
}
private static readonly TextureLoader textureLoader = new();
private static readonly Animation EmptyAnimation = new(EMPTY_ANIMATION, [], 0);
private readonly Atlas atlas;
@@ -73,7 +50,8 @@ namespace SpineViewer.Spine.Implementations.SpineObject
public SpineObject38(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try { atlas = new Atlas(AtlasPath, textureLoader); }
catch (Exception ex) { throw new InvalidDataException($"Failed to load atlas '{atlasPath}'", ex); }
try
{
// 先尝试二进制文件
@@ -93,6 +71,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch (Exception ex)
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}", ex);
}
}
@@ -119,7 +98,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
atlas.Dispose();
atlas?.Dispose();
}
public override string FileVersion { get => skeletonData.Version; }
@@ -238,10 +217,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject
tmpSkeleton.Update(0);
tmpSkeleton.UpdateWorldTransform();
// 按 10 帧每秒计算边框
// 按 100 帧每秒计算边框
var bounds = getCurrentBounds();
float[] _ = [];
for (float tick = 0, delta = 0.1f; tick < maxDuration; tick += delta)
for (float tick = 0, delta = 0.01f; tick < maxDuration; tick += delta)
{
tmpSkeleton.GetBounds(out var x, out var y, out var w, out var h, ref _);
bounds = bounds.Union(new(x, y, w, h));

View File

@@ -28,26 +28,6 @@ namespace SpineViewer.Spine.Implementations.SpineObject
};
}
private class TextureLoader : SpineRuntime40.TextureLoader
{
public void Load(AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == TextureFilter.Linear)
texture.Smooth = true;
if (page.uWrap == TextureWrap.Repeat && page.vWrap == TextureWrap.Repeat)
texture.Repeated = true;
page.rendererObject = texture;
}
public void Unload(object texture)
{
((SFML.Graphics.Texture)texture).Dispose();
}
}
private static readonly TextureLoader textureLoader = new();
private static readonly Animation EmptyAnimation = new(EMPTY_ANIMATION, [], 0);
private readonly Atlas atlas;
@@ -68,7 +48,8 @@ namespace SpineViewer.Spine.Implementations.SpineObject
public SpineObject40(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try { atlas = new Atlas(AtlasPath, textureLoader); }
catch (Exception ex) { throw new InvalidDataException($"Failed to load atlas '{atlasPath}'", ex); }
try
{
// 先尝试二进制文件
@@ -88,6 +69,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}");
}
}
@@ -115,7 +97,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
atlas.Dispose();
atlas?.Dispose();
}
public override string FileVersion { get => skeletonData.Version; }
@@ -234,10 +216,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject
tmpSkeleton.Update(0);
tmpSkeleton.UpdateWorldTransform();
// 按 10 帧每秒计算边框
// 按 100 帧每秒计算边框
var bounds = getCurrentBounds();
float[] _ = [];
for (float tick = 0, delta = 0.1f; tick < maxDuration; tick += delta)
for (float tick = 0, delta = 0.01f; tick < maxDuration; tick += delta)
{
tmpSkeleton.GetBounds(out var x, out var y, out var w, out var h, ref _);
bounds = bounds.Union(new(x, y, w, h));

View File

@@ -28,26 +28,6 @@ namespace SpineViewer.Spine.Implementations.SpineObject
};
}
private class TextureLoader : SpineRuntime41.TextureLoader
{
public void Load(AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == TextureFilter.Linear)
texture.Smooth = true;
if (page.uWrap == TextureWrap.Repeat && page.vWrap == TextureWrap.Repeat)
texture.Repeated = true;
page.rendererObject = texture;
}
public void Unload(object texture)
{
((SFML.Graphics.Texture)texture).Dispose();
}
}
private static TextureLoader textureLoader = new();
private static readonly Animation EmptyAnimation = new(EMPTY_ANIMATION, [], 0);
private readonly Atlas atlas;
@@ -68,7 +48,8 @@ namespace SpineViewer.Spine.Implementations.SpineObject
public SpineObject41(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try { atlas = new Atlas(AtlasPath, textureLoader); }
catch (Exception ex) { throw new InvalidDataException($"Failed to load atlas '{atlasPath}'", ex); }
try
{
// 先尝试二进制文件
@@ -88,6 +69,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}");
}
}
@@ -115,7 +97,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
atlas.Dispose();
atlas?.Dispose();
}
public override string FileVersion { get => skeletonData.Version; }
@@ -234,10 +216,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject
//tmpSkeleton.Update(0);
tmpSkeleton.UpdateWorldTransform();
// 按 10 帧每秒计算边框
// 按 100 帧每秒计算边框
var bounds = getCurrentBounds();
float[] _ = [];
for (float tick = 0, delta = 0.1f; tick < maxDuration; tick += delta)
for (float tick = 0, delta = 0.01f; tick < maxDuration; tick += delta)
{
tmpSkeleton.GetBounds(out var x, out var y, out var w, out var h, ref _);
bounds = bounds.Union(new(x, y, w, h));

View File

@@ -28,26 +28,6 @@ namespace SpineViewer.Spine.Implementations.SpineObject
};
}
private class TextureLoader : SpineRuntime42.TextureLoader
{
public void Load(AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == TextureFilter.Linear)
texture.Smooth = true;
if (page.uWrap == TextureWrap.Repeat && page.vWrap == TextureWrap.Repeat)
texture.Repeated = true;
page.rendererObject = texture;
}
public void Unload(object texture)
{
((SFML.Graphics.Texture)texture).Dispose();
}
}
private static readonly TextureLoader textureLoader = new();
private static readonly Animation EmptyAnimation = new(EMPTY_ANIMATION, [], 0);
private readonly Atlas atlas;
@@ -68,7 +48,8 @@ namespace SpineViewer.Spine.Implementations.SpineObject
public SpineObject42(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try { atlas = new Atlas(AtlasPath, textureLoader); }
catch (Exception ex) { throw new InvalidDataException($"Failed to load atlas '{atlasPath}'", ex); }
try
{
// 先尝试二进制文件
@@ -88,6 +69,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}");
}
}
@@ -115,7 +97,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
atlas.Dispose();
atlas?.Dispose();
}
public override string FileVersion { get => skeletonData.Version; }
@@ -234,10 +216,10 @@ namespace SpineViewer.Spine.Implementations.SpineObject
tmpSkeleton.Update(0);
tmpSkeleton.UpdateWorldTransform(Skeleton.Physics.Update);
// 按 10 帧每秒计算边框
// 按 100 帧每秒计算边框
var bounds = getCurrentBounds();
float[] _ = [];
for (float tick = 0, delta = 0.1f; tick < maxDuration; tick += delta)
for (float tick = 0, delta = 0.01f; tick < maxDuration; tick += delta)
{
tmpSkeleton.GetBounds(out var x, out var y, out var w, out var h, ref _);
bounds = bounds.Union(new(x, y, w, h));

View File

@@ -57,7 +57,7 @@ namespace SpineViewer.Spine.SpineExporter
var noteSuffix = FileNameNoteSuffix;
if (!string.IsNullOrWhiteSpace(noteSuffix)) noteSuffix = $"_{noteSuffix}";
var filename = $"ffmpeg_{timestamp}_{FPS:f0}{noteSuffix}{Suffix}";
var filename = $"ffmpeg_{timestamp}_{Guid.NewGuid().ToString()[..6]}_{FPS:f0}{noteSuffix}{Suffix}";
// 导出单个时必定提供输出文件夹
var savePath = Path.Combine(OutputDir, filename);
@@ -86,7 +86,7 @@ namespace SpineViewer.Spine.SpineExporter
{
if (worker?.CancellationPending == true) break; // 取消的日志在 GetFrames 里输出
var filename = $"{spine.Name}_{timestamp}_{FPS:f0}{noteSuffix}{Suffix}";
var filename = $"{spine.Name}_{timestamp}_{spine.ID[..6]}_{FPS:f0}{noteSuffix}{Suffix}";
// 如果提供了输出文件夹, 则全部导出到输出文件夹, 否则导出到各自的文件夹下
var savePath = Path.Combine(OutputDir ?? spine.AssetsDir, filename);

View File

@@ -47,7 +47,7 @@ namespace SpineViewer.Spine.SpineExporter
protected override void ExportSingle(SpineObject[] spinesToRender, BackgroundWorker? worker = null)
{
// 导出单个时必定提供输出文件夹
var filename = $"frame_{timestamp}{ImageFormat.GetSuffix()}";
var filename = $"frame_{timestamp}_{Guid.NewGuid().ToString()[..6]}{ImageFormat.GetSuffix()}";
var savePath = Path.Combine(OutputDir, filename);
worker?.ReportProgress(0, $"{Properties.Resources.process} 0/1");
@@ -78,7 +78,7 @@ namespace SpineViewer.Spine.SpineExporter
var spine = spinesToRender[i];
// 逐个导出时如果提供了输出文件夹, 则全部导出到输出文件夹, 否则输出到各自的文件夹
var filename = $"{spine.Name}_{timestamp}{ImageFormat.GetSuffix()}";
var filename = $"{spine.Name}_{timestamp}_{spine.ID[..6]}{ImageFormat.GetSuffix()}";
var savePath = Path.Combine(OutputDir ?? spine.AssetsDir, filename);
try

View File

@@ -22,14 +22,16 @@ namespace SpineViewer.Spine.SpineExporter
protected override void ExportSingle(SpineObject[] spinesToRender, BackgroundWorker? worker = null)
{
var uniqueSuffix = Guid.NewGuid().ToString()[..6];
// 导出单个时必定提供输出文件夹,
var saveDir = Path.Combine(OutputDir, $"frames_{timestamp}_{FPS:f0}");
var saveDir = Path.Combine(OutputDir, $"frames_{timestamp}_{uniqueSuffix}_{FPS:f0}");
Directory.CreateDirectory(saveDir);
int frameIdx = 0;
foreach (var frame in GetFrames(spinesToRender, worker))
{
var filename = $"frames_{timestamp}_{FPS:f0}_{frameIdx:d6}{Suffix}";
var filename = $"frames_{timestamp}_{uniqueSuffix}_{FPS:f0}_{frameIdx:d6}{Suffix}";
var savePath = Path.Combine(saveDir, filename);
try
@@ -56,14 +58,14 @@ namespace SpineViewer.Spine.SpineExporter
if (worker?.CancellationPending == true) break; // 取消的日志在 GetFrames 里输出
// 如果提供了输出文件夹, 则全部导出到输出文件夹, 否则导出到各自的文件夹下
var subDir = $"{spine.Name}_{timestamp}_{FPS:f0}";
var subDir = $"{spine.Name}_{timestamp}_{spine.ID[..6]}_{FPS:f0}";
var saveDir = Path.Combine(OutputDir ?? spine.AssetsDir, subDir);
Directory.CreateDirectory(saveDir);
int frameIdx = 0;
foreach (var frame in GetFrames(spine, worker))
{
var filename = $"{spine.Name}_{timestamp}_{FPS:f0}_{frameIdx:d6}{Suffix}";
var filename = $"{spine.Name}_{timestamp}_{spine.ID[..6]}_{FPS:f0}_{frameIdx:d6}{Suffix}";
var savePath = Path.Combine(saveDir, filename);
try

View File

@@ -30,15 +30,6 @@ namespace SpineViewer.Spine.SpineExporter
/// </summary>
public bool KeepLast { get; set; } = true;
public override string? Validate()
{
if (base.Validate() is string error)
return error;
if (IsExportSingle && Duration < 0)
return Properties.Resources.negativeDuration;
return null;
}
/// <summary>
/// 生成单个模型的帧序列
/// </summary>
@@ -93,8 +84,16 @@ namespace SpineViewer.Spine.SpineExporter
/// </summary>
protected IEnumerable<SFMLImageVideoFrame> GetFrames(SpineObject[] spinesToRender, BackgroundWorker? worker = null)
{
// 导出单个时必须根据 Duration 决定导出时长
// 导出单个时取所有模型的所有轨道时长最大值
var duration = Duration;
if (duration < 0)
{
duration = spinesToRender.Select(
sp => sp.GetTrackIndices().Select(
i => sp.GetAnimationDuration(sp.GetAnimation(i))
).DefaultIfEmpty(0).Max()
).Max();
}
float delta = 1f / FPS;
int total = (int)(duration * FPS); // 完整帧的数量

View File

@@ -32,6 +32,12 @@ namespace SpineViewer.Spine
/// </summary>
protected static readonly Size PreviewResolution = new(256, 256);
/// <summary>
/// 纹理加载器
/// </summary>
public static TextureLoader TextureLoader => textureLoader;
protected readonly static TextureLoader textureLoader = new();
/// <summary>
/// 创建特定版本的 Spine
/// </summary>

View File

@@ -0,0 +1,287 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SpineViewer.Spine
{
/// <summary>
/// 实现不同版本的 TextureLoader
/// </summary>
public class TextureLoader :
SpineRuntime21.TextureLoader,
SpineRuntime36.TextureLoader,
SpineRuntime37.TextureLoader,
SpineRuntime38.TextureLoader,
SpineRuntime40.TextureLoader,
SpineRuntime41.TextureLoader,
SpineRuntime42.TextureLoader
{
/// <summary>
/// 强制启用 Smooth
/// </summary>
public bool ForceSmooth { get; set; } = false;
/// <summary>
/// 强制启用 Repeated
/// </summary>
public bool ForceRepeated { get; set; } = false;
/// <summary>
/// 强制启用 Mipmap
/// </summary>
public bool ForceMipmap { get; set; } = false;
public void Load(SpineRuntime21.AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == SpineRuntime21.TextureFilter.Linear)
{
texture.Smooth = true;
}
if (page.uWrap == SpineRuntime21.TextureWrap.Repeat && page.vWrap == SpineRuntime21.TextureWrap.Repeat)
{
texture.Repeated = true;
}
switch (page.minFilter)
{
case SpineRuntime21.TextureFilter.Linear:
texture.Smooth = true;
break;
case SpineRuntime21.TextureFilter.MipMap:
case SpineRuntime21.TextureFilter.MipMapNearestNearest:
texture.GenerateMipmap();
break;
case SpineRuntime21.TextureFilter.MipMapLinearNearest:
case SpineRuntime21.TextureFilter.MipMapNearestLinear:
case SpineRuntime21.TextureFilter.MipMapLinearLinear:
texture.Smooth = true;
texture.GenerateMipmap();
break;
}
if (ForceSmooth) texture.Smooth = true;
if (ForceRepeated) texture.Repeated = true;
if (ForceMipmap) texture.GenerateMipmap();
page.rendererObject = texture;
}
public void Load(SpineRuntime36.AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == SpineRuntime36.TextureFilter.Linear)
{
texture.Smooth = true;
}
if (page.uWrap == SpineRuntime36.TextureWrap.Repeat && page.vWrap == SpineRuntime36.TextureWrap.Repeat)
{
texture.Repeated = true;
}
switch (page.minFilter)
{
case SpineRuntime36.TextureFilter.Linear:
texture.Smooth = true;
break;
case SpineRuntime36.TextureFilter.MipMap:
case SpineRuntime36.TextureFilter.MipMapNearestNearest:
texture.GenerateMipmap();
break;
case SpineRuntime36.TextureFilter.MipMapLinearNearest:
case SpineRuntime36.TextureFilter.MipMapNearestLinear:
case SpineRuntime36.TextureFilter.MipMapLinearLinear:
texture.Smooth = true;
texture.GenerateMipmap();
break;
}
if (ForceSmooth) texture.Smooth = true;
if (ForceRepeated) texture.Repeated = true;
if (ForceMipmap) texture.GenerateMipmap();
page.rendererObject = texture;
}
public void Load(SpineRuntime37.AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == SpineRuntime37.TextureFilter.Linear)
{
texture.Smooth = true;
}
if (page.uWrap == SpineRuntime37.TextureWrap.Repeat && page.vWrap == SpineRuntime37.TextureWrap.Repeat)
{
texture.Repeated = true;
}
switch (page.minFilter)
{
case SpineRuntime37.TextureFilter.Linear:
texture.Smooth = true;
break;
case SpineRuntime37.TextureFilter.MipMap:
case SpineRuntime37.TextureFilter.MipMapNearestNearest:
texture.GenerateMipmap();
break;
case SpineRuntime37.TextureFilter.MipMapLinearNearest:
case SpineRuntime37.TextureFilter.MipMapNearestLinear:
case SpineRuntime37.TextureFilter.MipMapLinearLinear:
texture.Smooth = true;
texture.GenerateMipmap();
break;
}
if (ForceSmooth) texture.Smooth = true;
if (ForceRepeated) texture.Repeated = true;
if (ForceMipmap) texture.GenerateMipmap();
page.rendererObject = texture;
}
public void Load(SpineRuntime38.AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == SpineRuntime38.TextureFilter.Linear)
{
texture.Smooth = true;
}
if (page.uWrap == SpineRuntime38.TextureWrap.Repeat && page.vWrap == SpineRuntime38.TextureWrap.Repeat)
{
texture.Repeated = true;
}
switch (page.minFilter)
{
case SpineRuntime38.TextureFilter.Linear:
texture.Smooth = true;
break;
case SpineRuntime38.TextureFilter.MipMap:
case SpineRuntime38.TextureFilter.MipMapNearestNearest:
texture.GenerateMipmap();
break;
case SpineRuntime38.TextureFilter.MipMapLinearNearest:
case SpineRuntime38.TextureFilter.MipMapNearestLinear:
case SpineRuntime38.TextureFilter.MipMapLinearLinear:
texture.Smooth = true;
texture.GenerateMipmap();
break;
}
if (ForceSmooth) texture.Smooth = true;
if (ForceRepeated) texture.Repeated = true;
if (ForceMipmap) texture.GenerateMipmap();
page.rendererObject = texture;
}
public void Load(SpineRuntime40.AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == SpineRuntime40.TextureFilter.Linear)
{
texture.Smooth = true;
}
if (page.uWrap == SpineRuntime40.TextureWrap.Repeat && page.vWrap == SpineRuntime40.TextureWrap.Repeat)
{
texture.Repeated = true;
}
switch (page.minFilter)
{
case SpineRuntime40.TextureFilter.Linear:
texture.Smooth = true;
break;
case SpineRuntime40.TextureFilter.MipMap:
case SpineRuntime40.TextureFilter.MipMapNearestNearest:
texture.GenerateMipmap();
break;
case SpineRuntime40.TextureFilter.MipMapLinearNearest:
case SpineRuntime40.TextureFilter.MipMapNearestLinear:
case SpineRuntime40.TextureFilter.MipMapLinearLinear:
texture.Smooth = true;
texture.GenerateMipmap();
break;
}
if (ForceSmooth) texture.Smooth = true;
if (ForceRepeated) texture.Repeated = true;
if (ForceMipmap) texture.GenerateMipmap();
page.rendererObject = texture;
}
public void Load(SpineRuntime41.AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == SpineRuntime41.TextureFilter.Linear)
{
texture.Smooth = true;
}
if (page.uWrap == SpineRuntime41.TextureWrap.Repeat && page.vWrap == SpineRuntime41.TextureWrap.Repeat)
{
texture.Repeated = true;
}
switch (page.minFilter)
{
case SpineRuntime41.TextureFilter.Linear:
texture.Smooth = true;
break;
case SpineRuntime41.TextureFilter.MipMap:
case SpineRuntime41.TextureFilter.MipMapNearestNearest:
texture.GenerateMipmap();
break;
case SpineRuntime41.TextureFilter.MipMapLinearNearest:
case SpineRuntime41.TextureFilter.MipMapNearestLinear:
case SpineRuntime41.TextureFilter.MipMapLinearLinear:
texture.Smooth = true;
texture.GenerateMipmap();
break;
}
if (ForceSmooth) texture.Smooth = true;
if (ForceRepeated) texture.Repeated = true;
if (ForceMipmap) texture.GenerateMipmap();
page.rendererObject = texture;
}
public void Load(SpineRuntime42.AtlasPage page, string path)
{
var texture = new SFML.Graphics.Texture(path);
if (page.magFilter == SpineRuntime42.TextureFilter.Linear)
{
texture.Smooth = true;
}
if (page.uWrap == SpineRuntime42.TextureWrap.Repeat && page.vWrap == SpineRuntime42.TextureWrap.Repeat)
{
texture.Repeated = true;
}
switch (page.minFilter)
{
case SpineRuntime42.TextureFilter.Linear:
texture.Smooth = true;
break;
case SpineRuntime42.TextureFilter.MipMap:
case SpineRuntime42.TextureFilter.MipMapNearestNearest:
texture.GenerateMipmap();
break;
case SpineRuntime42.TextureFilter.MipMapLinearNearest:
case SpineRuntime42.TextureFilter.MipMapNearestLinear:
case SpineRuntime42.TextureFilter.MipMapLinearLinear:
texture.Smooth = true;
texture.GenerateMipmap();
break;
}
if (ForceSmooth) texture.Smooth = true;
if (ForceRepeated) texture.Repeated = true;
if (ForceMipmap) texture.GenerateMipmap();
page.rendererObject = texture;
// 似乎是不需要设置的, 因为存在某些 png 和 atlas 大小不同的情况, 一般是有一些缩放, 如果设置了反而渲染异常
// page.width = (int)texture.Size.X;
// page.height = (int)texture.Size.Y;
}
public void Unload(object texture) => ((SFML.Graphics.Texture)texture).Dispose();
}
}

View File

@@ -7,7 +7,7 @@
<TargetFramework>net8.0-windows</TargetFramework>
<BaseOutputPath>$(SolutionDir)out</BaseOutputPath>
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
<Version>0.12.9</Version>
<Version>0.12.17</Version>
<OutputType>WinExe</OutputType>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>appicon.ico</ApplicationIcon>