diff --git a/SpineViewer/Spine/Implementations/Spine/Spine21.cs b/SpineViewer/Spine/Implementations/Spine/Spine21.cs
index 818de4a..16b042a 100644
--- a/SpineViewer/Spine/Implementations/Spine/Spine21.cs
+++ b/SpineViewer/Spine/Implementations/Spine/Spine21.cs
@@ -47,7 +47,7 @@ namespace SpineViewer.Spine.Implementations.Spine
// 2.1.x 不支持剪裁
//private SkeletonClipping clipping = new();
- public Spine21(string skelPath, string? atlasPath = null) : base(skelPath, atlasPath)
+ public Spine21(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try
@@ -76,12 +76,12 @@ namespace SpineViewer.Spine.Implementations.Spine
foreach (var skin in skeletonData.Skins)
skinNames.Add(skin.Name);
- animationStateData = new AnimationStateData(skeletonData);
- skeleton = new Skeleton(skeletonData);
- animationState = new AnimationState(animationStateData);
-
foreach (var anime in skeletonData.Animations)
animationNames.Add(anime.Name);
+
+ skeleton = new Skeleton(skeletonData);
+ animationStateData = new AnimationStateData(skeletonData);
+ animationState = new AnimationState(animationStateData);
}
protected override void Dispose(bool disposing)
diff --git a/SpineViewer/Spine/Implementations/Spine/Spine36.cs b/SpineViewer/Spine/Implementations/Spine/Spine36.cs
index c9ab7b8..05124aa 100644
--- a/SpineViewer/Spine/Implementations/Spine/Spine36.cs
+++ b/SpineViewer/Spine/Implementations/Spine/Spine36.cs
@@ -46,7 +46,7 @@ namespace SpineViewer.Spine.Implementations.Spine
private SkeletonClipping clipping = new();
- public Spine36(string skelPath, string? atlasPath = null) : base(skelPath, atlasPath)
+ public Spine36(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try
@@ -75,12 +75,12 @@ namespace SpineViewer.Spine.Implementations.Spine
foreach (var skin in skeletonData.Skins)
skinNames.Add(skin.Name);
- animationStateData = new AnimationStateData(skeletonData);
- skeleton = new Skeleton(skeletonData);
- animationState = new AnimationState(animationStateData);
-
foreach (var anime in skeletonData.Animations)
animationNames.Add(anime.Name);
+
+ skeleton = new Skeleton(skeletonData);
+ animationStateData = new AnimationStateData(skeletonData);
+ animationState = new AnimationState(animationStateData);
}
protected override void Dispose(bool disposing)
diff --git a/SpineViewer/Spine/Implementations/Spine/Spine37.cs b/SpineViewer/Spine/Implementations/Spine/Spine37.cs
index 8ac850b..2c3837b 100644
--- a/SpineViewer/Spine/Implementations/Spine/Spine37.cs
+++ b/SpineViewer/Spine/Implementations/Spine/Spine37.cs
@@ -44,7 +44,7 @@ namespace SpineViewer.Spine.Implementations.Spine
private SkeletonClipping clipping = new();
- public Spine37(string skelPath, string? atlasPath = null) : base(skelPath, atlasPath)
+ public Spine37(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try
@@ -73,12 +73,12 @@ namespace SpineViewer.Spine.Implementations.Spine
foreach (var skin in skeletonData.Skins)
skinNames.Add(skin.Name);
- animationStateData = new AnimationStateData(skeletonData);
- skeleton = new Skeleton(skeletonData);
- animationState = new AnimationState(animationStateData);
-
foreach (var anime in skeletonData.Animations)
animationNames.Add(anime.Name);
+
+ skeleton = new Skeleton(skeletonData);
+ animationStateData = new AnimationStateData(skeletonData);
+ animationState = new AnimationState(animationStateData);
}
protected override void Dispose(bool disposing)
diff --git a/SpineViewer/Spine/Implementations/Spine/Spine38.cs b/SpineViewer/Spine/Implementations/Spine/Spine38.cs
index 1af6b81..5209e3b 100644
--- a/SpineViewer/Spine/Implementations/Spine/Spine38.cs
+++ b/SpineViewer/Spine/Implementations/Spine/Spine38.cs
@@ -50,7 +50,7 @@ namespace SpineViewer.Spine.Implementations.Spine
private SkeletonClipping clipping = new();
- public Spine38(string skelPath, string? atlasPath = null) : base(skelPath, atlasPath)
+ public Spine38(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try
@@ -79,12 +79,12 @@ namespace SpineViewer.Spine.Implementations.Spine
foreach (var skin in skeletonData.Skins)
skinNames.Add(skin.Name);
- animationStateData = new AnimationStateData(skeletonData);
- skeleton = new Skeleton(skeletonData);
- animationState = new AnimationState(animationStateData);
-
foreach (var anime in skeletonData.Animations)
animationNames.Add(anime.Name);
+
+ skeleton = new Skeleton(skeletonData);
+ animationStateData = new AnimationStateData(skeletonData);
+ animationState = new AnimationState(animationStateData);
}
protected override void Dispose(bool disposing)
diff --git a/SpineViewer/Spine/Implementations/Spine/Spine40.cs b/SpineViewer/Spine/Implementations/Spine/Spine40.cs
index 1542e0f..a43561b 100644
--- a/SpineViewer/Spine/Implementations/Spine/Spine40.cs
+++ b/SpineViewer/Spine/Implementations/Spine/Spine40.cs
@@ -46,7 +46,7 @@ namespace SpineViewer.Spine.Implementations.Spine
private SkeletonClipping clipping = new();
- public Spine40(string skelPath, string? atlasPath = null) : base(skelPath, atlasPath)
+ public Spine40(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try
@@ -75,12 +75,12 @@ namespace SpineViewer.Spine.Implementations.Spine
foreach (var skin in skeletonData.Skins)
skinNames.Add(skin.Name);
- animationStateData = new AnimationStateData(skeletonData);
- skeleton = new Skeleton(skeletonData);
- animationState = new AnimationState(animationStateData);
-
foreach (var anime in skeletonData.Animations)
animationNames.Add(anime.Name);
+
+ skeleton = new Skeleton(skeletonData);
+ animationStateData = new AnimationStateData(skeletonData);
+ animationState = new AnimationState(animationStateData);
}
protected override void Dispose(bool disposing)
diff --git a/SpineViewer/Spine/Implementations/Spine/Spine41.cs b/SpineViewer/Spine/Implementations/Spine/Spine41.cs
index 129fde7..701413f 100644
--- a/SpineViewer/Spine/Implementations/Spine/Spine41.cs
+++ b/SpineViewer/Spine/Implementations/Spine/Spine41.cs
@@ -46,7 +46,7 @@ namespace SpineViewer.Spine.Implementations.Spine
private SkeletonClipping clipping = new();
- public Spine41(string skelPath, string? atlasPath = null) : base(skelPath, atlasPath)
+ public Spine41(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try
@@ -75,12 +75,12 @@ namespace SpineViewer.Spine.Implementations.Spine
foreach (var skin in skeletonData.Skins)
skinNames.Add(skin.Name);
- animationStateData = new AnimationStateData(skeletonData);
- skeleton = new Skeleton(skeletonData);
- animationState = new AnimationState(animationStateData);
-
foreach (var anime in skeletonData.Animations)
animationNames.Add(anime.Name);
+
+ skeleton = new Skeleton(skeletonData);
+ animationStateData = new AnimationStateData(skeletonData);
+ animationState = new AnimationState(animationStateData);
}
protected override void Dispose(bool disposing)
diff --git a/SpineViewer/Spine/Implementations/Spine/Spine42.cs b/SpineViewer/Spine/Implementations/Spine/Spine42.cs
index b1a46e7..0717ec0 100644
--- a/SpineViewer/Spine/Implementations/Spine/Spine42.cs
+++ b/SpineViewer/Spine/Implementations/Spine/Spine42.cs
@@ -46,7 +46,7 @@ namespace SpineViewer.Spine.Implementations.Spine
private SkeletonClipping clipping = new();
- public Spine42(string skelPath, string? atlasPath = null) : base(skelPath, atlasPath)
+ public Spine42(string skelPath, string atlasPath) : base(skelPath, atlasPath)
{
atlas = new Atlas(AtlasPath, textureLoader);
try
@@ -75,12 +75,12 @@ namespace SpineViewer.Spine.Implementations.Spine
foreach (var skin in skeletonData.Skins)
skinNames.Add(skin.Name);
- animationStateData = new AnimationStateData(skeletonData);
- skeleton = new Skeleton(skeletonData);
- animationState = new AnimationState(animationStateData);
-
foreach (var anime in skeletonData.Animations)
animationNames.Add(anime.Name);
+
+ skeleton = new Skeleton(skeletonData);
+ animationStateData = new AnimationStateData(skeletonData);
+ animationState = new AnimationState(animationStateData);
}
protected override void Dispose(bool disposing)
diff --git a/SpineViewer/Spine/Spine.cs b/SpineViewer/Spine/Spine.cs
index 44ec418..ce3f7ee 100644
--- a/SpineViewer/Spine/Spine.cs
+++ b/SpineViewer/Spine/Spine.cs
@@ -26,23 +26,22 @@ namespace SpineViewer.Spine
///
/// 空动画标记
///
- public const string EMPTY_ANIMATION = "";
+ protected const string EMPTY_ANIMATION = "";
///
/// 预览图宽
///
- public const uint PREVIEW_WIDTH = 256;
+ protected const uint PREVIEW_WIDTH = 256;
///
/// 预览图高
///
- public const uint PREVIEW_HEIGHT = 256;
+ protected const uint PREVIEW_HEIGHT = 256;
///
/// 缩放最小值
///
- public const float SCALE_MIN = 0.001f;
-
+ protected const float SCALE_MIN = 0.001f;
///
/// 创建特定版本的 Spine
@@ -50,10 +49,31 @@ namespace SpineViewer.Spine
public static Spine New(SpineVersion version, string skelPath, string? atlasPath = null)
{
if (version == SpineVersion.Auto) version = SpineHelper.GetVersion(skelPath);
- var spine = New(version, [skelPath, atlasPath]);
+ atlasPath ??= Path.ChangeExtension(skelPath, ".atlas");
+ return New(version, [skelPath, atlasPath]).PostInit();
+ }
- // 统一初始化
- spine.initBounds = spine.Bounds;
+ ///
+ /// 构造函数
+ ///
+ public Spine(string skelPath, string atlasPath)
+ {
+ Version = GetType().GetCustomAttribute().ImplementationKey;
+ AssetsDir = Directory.GetParent(skelPath).FullName;
+ SkelPath = Path.GetFullPath(skelPath);
+ AtlasPath = Path.GetFullPath(atlasPath);
+ Name = Path.GetFileNameWithoutExtension(skelPath);
+ }
+
+ ///
+ /// 构造函数之后的初始化工作
+ ///
+ private Spine PostInit()
+ {
+ SkinNames = skinNames.AsReadOnly();
+ AnimationNames = animationNames.AsReadOnly();
+
+ InitBounds = Bounds;
// XXX: tex 没办法在这里主动 Dispose
// 批量添加在获取预览图的时候极大概率会和预览线程死锁
@@ -61,9 +81,9 @@ namespace SpineViewer.Spine
// 除此之外, 似乎还和 tex 的 Dispose 有关
// 如果不对 tex 进行 Dispose, 那么不管是否 Draw 都正常不会死锁
var tex = new SFML.Graphics.RenderTexture(PREVIEW_WIDTH, PREVIEW_HEIGHT);
- tex.SetView(spine.InitBounds.GetView(PREVIEW_WIDTH, PREVIEW_HEIGHT));
+ tex.SetView(InitBounds.GetView(PREVIEW_WIDTH, PREVIEW_HEIGHT));
tex.Clear(SFML.Graphics.Color.Transparent);
- tex.Draw(spine);
+ tex.Draw(this);
tex.Display();
using (var img = tex.Texture.CopyToImage())
@@ -73,50 +93,27 @@ namespace SpineViewer.Spine
// 必须重复构造一个副本才能摆脱对流的依赖, 否则之后使用会报错
using var stream = new MemoryStream(imgBuffer);
using var bitmap = new Bitmap(stream);
- spine.preview = new Bitmap(bitmap);
+ Preview = new Bitmap(bitmap);
}
}
// 取最后一个作为初始, 尽可能去显示非默认的内容
- spine.Skin = spine.SkinNames.Last();
- spine.Track0Animation = spine.AnimationNames.Last();
+ Skin = SkinNames.Last();
+ Track0Animation = AnimationNames.Last();
- return spine;
- }
-
- ///
- /// 构造函数
- ///
- public Spine(string skelPath, string? atlasPath = null)
- {
- // 获取子类类型
- var type = GetType();
- var attr = type.GetCustomAttribute();
- if (attr is null)
- {
- throw new InvalidOperationException($"Class {type.Name} has no SpineImplementationAttribute");
- }
-
- atlasPath ??= Path.ChangeExtension(skelPath, ".atlas");
-
- // 设置 Version
- Version = attr.ImplementationKey;
- AssetsDir = Directory.GetParent(skelPath).FullName;
- SkelPath = Path.GetFullPath(skelPath);
- AtlasPath = Path.GetFullPath(atlasPath);
- Name = Path.GetFileNameWithoutExtension(skelPath);
+ return this;
}
~Spine() { Dispose(false); }
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); }
- protected virtual void Dispose(bool disposing) { preview?.Dispose(); }
+ protected virtual void Dispose(bool disposing) { Preview?.Dispose(); }
#region 属性 | [0] 基本信息
///
/// 获取所属版本
///
- [TypeConverter(typeof(VersionConverter))]
+ [TypeConverter(typeof(SpineVersionConverter))]
[Category("[0] 基本信息"), DisplayName("运行时版本")]
public SpineVersion Version { get; }
@@ -202,8 +199,7 @@ namespace SpineViewer.Spine
///
/// 包含的所有皮肤名称
///
- [Browsable(false)]
- public ReadOnlyCollection SkinNames { get => skinNames.AsReadOnly(); }
+ public ReadOnlyCollection SkinNames { get; private set; }
protected List skinNames = [];
///
@@ -216,8 +212,7 @@ namespace SpineViewer.Spine
///
/// 包含的所有动画名称
///
- [Browsable(false)]
- public ReadOnlyCollection AnimationNames { get => animationNames.AsReadOnly(); }
+ public ReadOnlyCollection AnimationNames { get; private set; }
protected List animationNames = [EMPTY_ANIMATION];
///
@@ -243,16 +238,6 @@ namespace SpineViewer.Spine
[Browsable(false)]
public bool IsDebug { get; set; } = false;
- ///
- /// 包围盒颜色
- ///
- protected static readonly SFML.Graphics.Color BoundsColor = new(120, 200, 0);
-
- ///
- /// 包围盒顶点数组
- ///
- protected readonly SFML.Graphics.VertexArray boundsVertices = new(SFML.Graphics.PrimitiveType.LineStrip, 5);
-
///
/// 显示纹理
///
@@ -268,7 +253,7 @@ namespace SpineViewer.Spine
///
/// 显示骨骼
///
- [Category("[4] 调试"), DisplayName("显示骨骼")]
+ [Category("[4] 调试"), DisplayName("显示骨架")]
public bool DebugBones { get; set; } = false;
#endregion
@@ -294,15 +279,13 @@ namespace SpineViewer.Spine
/// 初始状态下的骨骼包围盒
///
[Browsable(false)]
- public RectangleF InitBounds { get => initBounds; }
- private RectangleF initBounds;
+ public RectangleF InitBounds { get; private set; }
///
/// 骨骼预览图
///
[Browsable(false)]
- public Image Preview { get => preview; }
- private Image preview;
+ public Image Preview { get; private set; }
///
/// 获取动画时长, 如果动画不存在则返回 0
@@ -326,6 +309,16 @@ namespace SpineViewer.Spine
///
protected readonly SFML.Graphics.VertexArray vertexArray = new(SFML.Graphics.PrimitiveType.Triangles);
+ ///
+ /// 包围盒颜色
+ ///
+ protected static readonly SFML.Graphics.Color BoundsColor = new(120, 200, 0);
+
+ ///
+ /// 包围盒顶点数组
+ ///
+ protected readonly SFML.Graphics.VertexArray boundsVertices = new(SFML.Graphics.PrimitiveType.LineStrip, 5);
+
///
/// SFML.Graphics.Drawable 接口实现
///
diff --git a/SpineViewer/Spine/TypeConverter.cs b/SpineViewer/Spine/TypeConverter.cs
index fad151e..e0968fc 100644
--- a/SpineViewer/Spine/TypeConverter.cs
+++ b/SpineViewer/Spine/TypeConverter.cs
@@ -9,9 +9,9 @@ using System.Threading.Tasks;
namespace SpineViewer.Spine
{
- public class VersionConverter : EnumConverter
+ public class SpineVersionConverter : EnumConverter
{
- public VersionConverter() : base(typeof(SpineVersion)) { }
+ public SpineVersionConverter() : base(typeof(SpineVersion)) { }
public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type? destinationType)
{