Compare commits

...

6 Commits

Author SHA1 Message Date
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
9 changed files with 115 additions and 18 deletions

View File

@@ -1,5 +1,13 @@
# CHANGELOG
## v0.12.12
- 修复 2.1 版本遗漏的 SkinnedMeshAttachment 附件渲染
## v0.12.11
- 修复可能的闪退错误
## v0.12.10
- 增加纹理全局加载选项

View File

@@ -50,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
{
// 先尝试二进制文件
@@ -70,6 +71,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}");
}
}
@@ -96,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; }
@@ -258,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; // 纹理坐标
@@ -272,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;
@@ -288,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;
@@ -297,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)
//{
@@ -430,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);
@@ -452,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

@@ -49,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
{
// 先尝试二进制文件
@@ -69,6 +70,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}");
}
}
@@ -95,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; }

View File

@@ -46,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
{
// 先尝试二进制文件
@@ -66,6 +67,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}");
}
}
@@ -92,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; }

View File

@@ -50,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
{
// 先尝试二进制文件
@@ -70,6 +71,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch (Exception ex)
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}", ex);
}
}
@@ -96,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; }

View File

@@ -48,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
{
// 先尝试二进制文件
@@ -68,6 +69,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}");
}
}
@@ -95,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; }

View File

@@ -48,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
{
// 先尝试二进制文件
@@ -68,6 +69,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}");
}
}
@@ -95,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; }

View File

@@ -48,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
{
// 先尝试二进制文件
@@ -68,6 +69,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
catch
{
// 都不行就报错
atlas.Dispose();
throw new InvalidDataException($"Unknown skeleton file format {SkelPath}");
}
}
@@ -95,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; }

View File

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