重构并增加HitTest
This commit is contained in:
25
Spine/Interfaces/Attachments/IAttachment.cs
Normal file
25
Spine/Interfaces/Attachments/IAttachment.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Spine.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces.Attachments
|
||||
{
|
||||
public interface IAttachment
|
||||
{
|
||||
/// <summary>
|
||||
/// 附件的唯一名字
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 计算世界顶点数组
|
||||
/// </summary>
|
||||
/// <param name="slot">装载的插槽</param>
|
||||
/// <param name="worldVertices">顶点缓冲数组, 如果大小不足会重分配到合适的大小, 实际长度需要通过返回值获取</param>
|
||||
/// <returns><paramref name="worldVertices"/> 的实际长度, 顶点数是长度除以 2</returns>
|
||||
public int ComputeWorldVertices(ISlot slot, ref float[] worldVertices);
|
||||
}
|
||||
}
|
||||
13
Spine/Interfaces/Attachments/IBoundingBoxAttachment.cs
Normal file
13
Spine/Interfaces/Attachments/IBoundingBoxAttachment.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces.Attachments
|
||||
{
|
||||
public interface IBoundingBoxAttachment : IAttachment
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
13
Spine/Interfaces/Attachments/IClippingAttachment.cs
Normal file
13
Spine/Interfaces/Attachments/IClippingAttachment.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces.Attachments
|
||||
{
|
||||
public interface IClippingAttachment : IAttachment
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
52
Spine/Interfaces/Attachments/IMeshAttachment.cs
Normal file
52
Spine/Interfaces/Attachments/IMeshAttachment.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Spine.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces.Attachments
|
||||
{
|
||||
public interface IMeshAttachment : IAttachment
|
||||
{
|
||||
/// <summary>
|
||||
/// R
|
||||
/// </summary>
|
||||
public float R { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// G
|
||||
/// </summary>
|
||||
public float G { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// B
|
||||
/// </summary>
|
||||
public float B { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A
|
||||
/// </summary>
|
||||
public float A { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用于渲染的纹理对象
|
||||
/// </summary>
|
||||
public SFML.Graphics.Texture RendererObject { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 顶点纹理坐标, 每个坐标有 u 和 v 两个数, 有效长度和 <see cref="IAttachment.ComputeWorldVertices(ISlot, ref float[])"/> 返回值一致
|
||||
/// </summary>
|
||||
public float[] UVs { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 三角形索引顶点数组, 每 3 个为一组, 指向顶点的下标 (不是顶点坐标数组下标)
|
||||
/// </summary>
|
||||
public int[] Triangles { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 边缘顶点数组长度
|
||||
/// </summary>
|
||||
public int HullLength { get; }
|
||||
}
|
||||
}
|
||||
13
Spine/Interfaces/Attachments/IPathAttachment.cs
Normal file
13
Spine/Interfaces/Attachments/IPathAttachment.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces.Attachments
|
||||
{
|
||||
public interface IPathAttachment : IAttachment
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
13
Spine/Interfaces/Attachments/IPointAttachment.cs
Normal file
13
Spine/Interfaces/Attachments/IPointAttachment.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces.Attachments
|
||||
{
|
||||
public interface IPointAttachment : IAttachment
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
52
Spine/Interfaces/Attachments/IRegionAttachment.cs
Normal file
52
Spine/Interfaces/Attachments/IRegionAttachment.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Spine.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces.Attachments
|
||||
{
|
||||
public interface IRegionAttachment : IAttachment
|
||||
{
|
||||
/// <summary>
|
||||
/// 总是将 Region 附件矩形区域切分成两个这样的三角形
|
||||
/// </summary>
|
||||
private static readonly int[] _trangles = [0, 1, 2, 2, 3, 0];
|
||||
|
||||
/// <summary>
|
||||
/// R
|
||||
/// </summary>
|
||||
public float R { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// G
|
||||
/// </summary>
|
||||
public float G { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// B
|
||||
/// </summary>
|
||||
public float B { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A
|
||||
/// </summary>
|
||||
public float A { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用于渲染的纹理对象
|
||||
/// </summary>
|
||||
public SFML.Graphics.Texture RendererObject { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 顶点纹理坐标, 每个坐标有 u 和 v 两个数, 有效长度和 <see cref="IAttachment.ComputeWorldVertices(ISlot, ref float[])"/> 返回值一致
|
||||
/// </summary>
|
||||
public float[] UVs { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 三角形索引顶点数组, 每 3 个为一组, 指向顶点的下标 (不是顶点坐标数组下标)
|
||||
/// </summary>
|
||||
public int[] Triangles => _trangles;
|
||||
}
|
||||
}
|
||||
52
Spine/Interfaces/Attachments/ISkinnedMeshAttachment.cs
Normal file
52
Spine/Interfaces/Attachments/ISkinnedMeshAttachment.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Spine.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces.Attachments
|
||||
{
|
||||
public interface ISkinnedMeshAttachment : IAttachment
|
||||
{
|
||||
/// <summary>
|
||||
/// R
|
||||
/// </summary>
|
||||
public float R { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// G
|
||||
/// </summary>
|
||||
public float G { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// B
|
||||
/// </summary>
|
||||
public float B { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A
|
||||
/// </summary>
|
||||
public float A { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用于渲染的纹理对象
|
||||
/// </summary>
|
||||
public SFML.Graphics.Texture RendererObject { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 顶点纹理坐标, 每个坐标有 u 和 v 两个数, 有效长度和 <see cref="IAttachment.ComputeWorldVertices(ISlot, ref float[])"/> 返回值一致
|
||||
/// </summary>
|
||||
public float[] UVs { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 三角形索引顶点数组, 每 3 个为一组, 指向顶点的下标 (不是顶点坐标数组下标)
|
||||
/// </summary>
|
||||
public int[] Triangles { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 边缘顶点数组长度
|
||||
/// </summary>
|
||||
public int HullLength { get; }
|
||||
}
|
||||
}
|
||||
21
Spine/Interfaces/IAnimation.cs
Normal file
21
Spine/Interfaces/IAnimation.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces
|
||||
{
|
||||
public interface IAnimation
|
||||
{
|
||||
/// <summary>
|
||||
/// 动画名称
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 动画时长
|
||||
/// </summary>
|
||||
public float Duration { get; }
|
||||
}
|
||||
}
|
||||
112
Spine/Interfaces/IAnimationState.cs
Normal file
112
Spine/Interfaces/IAnimationState.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces
|
||||
{
|
||||
public interface IAnimationState
|
||||
{
|
||||
/// <summary>
|
||||
/// 事件方法签名
|
||||
/// </summary>
|
||||
/// <param name="trackEntry"></param>
|
||||
public delegate void TrackEntryDelegate(ITrackEntry trackEntry);
|
||||
|
||||
/// <summary>
|
||||
/// Start 事件
|
||||
/// </summary>
|
||||
public event TrackEntryDelegate? Start;
|
||||
|
||||
/// <summary>
|
||||
/// Interrupt 事件
|
||||
/// </summary>
|
||||
public event TrackEntryDelegate? Interrupt;
|
||||
|
||||
/// <summary>
|
||||
/// End 事件
|
||||
/// </summary>
|
||||
public event TrackEntryDelegate? End;
|
||||
|
||||
/// <summary>
|
||||
/// Complete 事件
|
||||
/// </summary>
|
||||
public event TrackEntryDelegate? Complete;
|
||||
|
||||
/// <summary>
|
||||
/// Dispose 事件
|
||||
/// </summary>
|
||||
public event TrackEntryDelegate? Dispose;
|
||||
|
||||
/// <summary>
|
||||
/// 速度因子
|
||||
/// </summary>
|
||||
public float TimeScale { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 遍历所有的轨道, 可能存在 null
|
||||
/// </summary>
|
||||
public IEnumerable<ITrackEntry?> IterTracks();
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
public void Update(float delta);
|
||||
|
||||
/// <summary>
|
||||
/// 将动画应用到骨骼上
|
||||
/// </summary>
|
||||
public void Apply(ISkeleton skeleton);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定轨道当前播放条目, 可能返回 null
|
||||
/// </summary>
|
||||
public ITrackEntry? GetCurrent(int index);
|
||||
|
||||
/// <summary>
|
||||
/// 清除指定轨道
|
||||
/// </summary>
|
||||
public void ClearTrack(int index);
|
||||
|
||||
/// <summary>
|
||||
/// 清除所有轨道
|
||||
/// </summary>
|
||||
public void ClearTracks();
|
||||
|
||||
/// <summary>
|
||||
/// 使用动画名设置轨道动画
|
||||
/// </summary>
|
||||
public ITrackEntry SetAnimation(int trackIndex, string animationName, bool loop);
|
||||
|
||||
/// <summary>
|
||||
/// 使用动画对象设置轨道动画
|
||||
/// </summary>
|
||||
public ITrackEntry SetAnimation(int trackIndex, IAnimation animation, bool loop);
|
||||
|
||||
/// <summary>
|
||||
/// 设置轨道空动画
|
||||
/// </summary>
|
||||
public ITrackEntry SetEmptyAnimation(int trackIndex, float mixDuration);
|
||||
|
||||
/// <summary>
|
||||
/// 设置所有轨道空动画
|
||||
/// </summary>
|
||||
public void SetEmptyAnimations(float mixDuration);
|
||||
|
||||
/// <summary>
|
||||
/// 在指定轨道后添加动画
|
||||
/// </summary>
|
||||
public ITrackEntry AddAnimation(int trackIndex, string animationName, bool loop, float delay);
|
||||
|
||||
/// <summary>
|
||||
/// 在指定轨道后添加动画
|
||||
/// </summary>
|
||||
public ITrackEntry AddAnimation(int trackIndex, IAnimation animation, bool loop, float delay);
|
||||
|
||||
/// <summary>
|
||||
/// 在指定轨道后添加空动画
|
||||
/// </summary>
|
||||
public ITrackEntry AddEmptyAnimation(int trackIndex, float mixDuration, float delay);
|
||||
}
|
||||
}
|
||||
66
Spine/Interfaces/IBone.cs
Normal file
66
Spine/Interfaces/IBone.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces
|
||||
{
|
||||
public interface IBone
|
||||
{
|
||||
/// <summary>
|
||||
/// 骨骼唯一名字
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 骨骼索引
|
||||
/// </summary>
|
||||
public int Index { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否激活
|
||||
/// </summary>
|
||||
public bool Active { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 父骨骼
|
||||
/// </summary>
|
||||
public IBone? Parent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 骨骼长度
|
||||
/// </summary>
|
||||
public float Length { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 世界坐标 X
|
||||
/// </summary>
|
||||
public float WorldX { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 世界坐标 Y
|
||||
/// </summary>
|
||||
public float WorldY { get; }
|
||||
|
||||
/// <summary>
|
||||
/// <c>Cos(theta)</c>
|
||||
/// </summary>
|
||||
public float A { get; }
|
||||
|
||||
/// <summary>
|
||||
/// <c>-Sin(theta)</c>
|
||||
/// </summary>
|
||||
public float B { get; }
|
||||
|
||||
/// <summary>
|
||||
/// <c>Sin(theta)</c>
|
||||
/// </summary>
|
||||
public float C { get; }
|
||||
|
||||
/// <summary>
|
||||
/// <c>Cos(theta)</c>
|
||||
/// </summary>
|
||||
public float D { get; }
|
||||
}
|
||||
}
|
||||
118
Spine/Interfaces/ISkeleton.cs
Normal file
118
Spine/Interfaces/ISkeleton.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces
|
||||
{
|
||||
public interface ISkeleton
|
||||
{
|
||||
/// <summary>
|
||||
/// 物理约束
|
||||
/// </summary>
|
||||
public enum Physics { None, Reset, Update, Pose }
|
||||
|
||||
/// <summary>
|
||||
/// R
|
||||
/// </summary>
|
||||
public float R { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// G
|
||||
/// </summary>
|
||||
public float G { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// B
|
||||
/// </summary>
|
||||
public float B { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A
|
||||
/// </summary>
|
||||
public float A { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 横坐标
|
||||
/// </summary>
|
||||
public float X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 纵坐标
|
||||
/// </summary>
|
||||
public float Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 水平缩放, 负数时会翻转
|
||||
/// </summary>
|
||||
public float ScaleX { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 垂直缩放, 负数时会翻转
|
||||
/// </summary>
|
||||
public float ScaleY { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有骨骼按顺序
|
||||
/// </summary>
|
||||
public ImmutableArray<IBone> Bones { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有骨骼按名称
|
||||
/// </summary>
|
||||
public FrozenDictionary<string, IBone> BonesByName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有插槽按顺序
|
||||
/// </summary>
|
||||
public ImmutableArray<ISlot> Slots { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有插槽按名称
|
||||
/// </summary>
|
||||
public FrozenDictionary<string, ISlot> SlotsByName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 皮肤, 可以设置 null 值清除皮肤
|
||||
/// </summary>
|
||||
public ISkin? Skin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 遍历渲染时槽顺序
|
||||
/// </summary>
|
||||
public IEnumerable<ISlot> IterDrawOrder();
|
||||
|
||||
/// <summary>
|
||||
/// 更新附件约束等的缓存
|
||||
/// </summary>
|
||||
public void UpdateCache();
|
||||
|
||||
/// <summary>
|
||||
/// 更新变换
|
||||
/// </summary>
|
||||
public void UpdateWorldTransform(Physics physics);
|
||||
|
||||
/// <summary>
|
||||
/// 重置所有参数至初始值
|
||||
/// </summary>
|
||||
public void SetToSetupPose();
|
||||
|
||||
/// <summary>
|
||||
/// 重置所有骨骼参数至初始值
|
||||
/// </summary>
|
||||
public void SetBonesToSetupPose();
|
||||
|
||||
/// <summary>
|
||||
/// 重置所有插槽参数至初始值
|
||||
/// </summary>
|
||||
public void SetSlotsToSetupPose();
|
||||
|
||||
/// <summary>
|
||||
/// 更新时间
|
||||
/// </summary>
|
||||
public void Update(float delta);
|
||||
}
|
||||
}
|
||||
62
Spine/Interfaces/ISkeletonClipping.cs
Normal file
62
Spine/Interfaces/ISkeletonClipping.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using Spine.Interfaces.Attachments;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces
|
||||
{
|
||||
public interface ISkeletonClipping
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否正处于裁剪
|
||||
/// </summary>
|
||||
public bool IsClipping { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 裁剪后的顶点数组
|
||||
/// </summary>
|
||||
public float[] ClippedVertices { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 裁剪后的顶点数组 <see cref="ClippedVertices"/> 长度
|
||||
/// </summary>
|
||||
public int ClippedVerticesLength { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 裁剪后的三角形索引数组
|
||||
/// </summary>
|
||||
public int[] ClippedTriangles { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 裁剪后的三角形索引数组 <see cref="ClippedTriangles"/> 长度
|
||||
/// </summary>
|
||||
public int ClippedTrianglesLength { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 裁剪后的 UV 数组
|
||||
/// </summary>
|
||||
public float[] ClippedUVs { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 进行裁剪, 裁剪后的结果通过属性获取
|
||||
/// </summary>
|
||||
public void ClipTriangles(float[] vertices, int verticesLength, int[] triangles, int trianglesLength, float[] uvs);
|
||||
|
||||
/// <summary>
|
||||
/// 开始裁剪
|
||||
/// </summary>
|
||||
public void ClipStart(ISlot slot, IClippingAttachment clippingAttachment);
|
||||
|
||||
/// <summary>
|
||||
/// 判断输入插槽是否需要结束裁剪并结束裁剪
|
||||
/// </summary>
|
||||
public void ClipEnd(ISlot slot);
|
||||
|
||||
/// <summary>
|
||||
/// 结束裁剪
|
||||
/// </summary>
|
||||
public void ClipEnd();
|
||||
}
|
||||
}
|
||||
26
Spine/Interfaces/ISkin.cs
Normal file
26
Spine/Interfaces/ISkin.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces
|
||||
{
|
||||
public interface ISkin
|
||||
{
|
||||
/// <summary>
|
||||
/// 皮肤名字
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 添加其他皮肤
|
||||
/// </summary>
|
||||
public void AddSkin(ISkin skin);
|
||||
|
||||
/// <summary>
|
||||
/// 清空皮肤内容
|
||||
/// </summary>
|
||||
public void Clear();
|
||||
}
|
||||
}
|
||||
63
Spine/Interfaces/ISlot.cs
Normal file
63
Spine/Interfaces/ISlot.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Spine.Interfaces.Attachments;
|
||||
|
||||
namespace Spine.Interfaces
|
||||
{
|
||||
public interface ISlot
|
||||
{
|
||||
/// <summary>
|
||||
/// 插槽唯一名字
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 插槽唯一索引
|
||||
/// </summary>
|
||||
public int Index { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 混合模式
|
||||
/// </summary>
|
||||
public SFML.Graphics.BlendMode Blend { get; }
|
||||
|
||||
/// <summary>
|
||||
/// R
|
||||
/// </summary>
|
||||
public float R { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// G
|
||||
/// </summary>
|
||||
public float G { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// B
|
||||
/// </summary>
|
||||
public float B { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A
|
||||
/// </summary>
|
||||
public float A { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 所在骨骼
|
||||
/// </summary>
|
||||
public IBone Bone { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 使用的附件, 可以设置为 null 清空附件
|
||||
/// </summary>
|
||||
public IAttachment? Attachment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否已禁用渲染该插槽
|
||||
/// </summary>
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
52
Spine/Interfaces/ISpineObjectData.cs
Normal file
52
Spine/Interfaces/ISpineObjectData.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Spine.Interfaces.Attachments;
|
||||
using System;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// 对 SkeletonData 和 AnimationStateData 的访问封装
|
||||
/// </summary>
|
||||
public interface ISpineObjectData
|
||||
{
|
||||
/// <summary>
|
||||
/// skel 文件版本
|
||||
/// </summary>
|
||||
public string SkeletonVersion { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有皮肤
|
||||
/// </summary>
|
||||
public ImmutableArray<ISkin> Skins { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有皮肤按名称
|
||||
/// </summary>
|
||||
public FrozenDictionary<string, ISkin> SkinsByName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有皮肤中所有插槽的可用附件集合, 并不保证所有插槽均在此处有键
|
||||
/// </summary>
|
||||
public FrozenDictionary<string, FrozenDictionary<string, IAttachment>> SlotAttachments { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有动画
|
||||
/// </summary>
|
||||
public ImmutableArray<IAnimation> Animations { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 所有动画按名称
|
||||
/// </summary>
|
||||
public FrozenDictionary<string, IAnimation> AnimationsByName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认的动画过渡时长
|
||||
/// </summary>
|
||||
public float DefaultMix { get; set; }
|
||||
}
|
||||
}
|
||||
77
Spine/Interfaces/ITrackEntry.cs
Normal file
77
Spine/Interfaces/ITrackEntry.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces
|
||||
{
|
||||
public interface ITrackEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Start 事件
|
||||
/// </summary>
|
||||
public event IAnimationState.TrackEntryDelegate? Start;
|
||||
|
||||
/// <summary>
|
||||
/// Interrupt 事件
|
||||
/// </summary>
|
||||
public event IAnimationState.TrackEntryDelegate? Interrupt;
|
||||
|
||||
/// <summary>
|
||||
/// End 事件
|
||||
/// </summary>
|
||||
public event IAnimationState.TrackEntryDelegate? End;
|
||||
|
||||
/// <summary>
|
||||
/// Complete 事件
|
||||
/// </summary>
|
||||
public event IAnimationState.TrackEntryDelegate? Complete;
|
||||
|
||||
/// <summary>
|
||||
/// Dispose 事件
|
||||
/// </summary>
|
||||
public event IAnimationState.TrackEntryDelegate? Dispose;
|
||||
|
||||
/// <summary>
|
||||
/// 所在轨道序号
|
||||
/// </summary>
|
||||
public int TrackIndex { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 播放的动画
|
||||
/// </summary>
|
||||
public IAnimation Animation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 下一个条目, 形成播放链表
|
||||
/// </summary>
|
||||
public ITrackEntry? Next { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 动画是否循环
|
||||
/// </summary>
|
||||
public bool Loop { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 轨道当前时间
|
||||
/// </summary>
|
||||
public float TrackTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 速度因子
|
||||
/// </summary>
|
||||
public float TimeScale { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 多轨道的 Alpha 混合
|
||||
/// </summary>
|
||||
public float Alpha { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 过渡到下一个条目的时长
|
||||
/// </summary>
|
||||
public float MixDuration { get; set; }
|
||||
}
|
||||
}
|
||||
122
Spine/Interfaces/SpineExtension.cs
Normal file
122
Spine/Interfaces/SpineExtension.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using Spine.Interfaces.Attachments;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Interfaces
|
||||
{
|
||||
public static class SpineExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前状态包围盒
|
||||
/// </summary>
|
||||
public static void GetBounds(this ISlot self, out float x, out float y, out float w, out float h)
|
||||
{
|
||||
float[] vertices = new float[8];
|
||||
int verticesLength = 0;
|
||||
var attachment = self.Attachment;
|
||||
switch (attachment)
|
||||
{
|
||||
case IRegionAttachment:
|
||||
case IMeshAttachment:
|
||||
verticesLength = attachment.ComputeWorldVertices(self, ref vertices);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (verticesLength > 0)
|
||||
{
|
||||
float minX = int.MaxValue;
|
||||
float minY = int.MaxValue;
|
||||
float maxX = int.MinValue;
|
||||
float maxY = int.MinValue;
|
||||
for (int ii = 0; ii + 1 < verticesLength; ii += 2)
|
||||
{
|
||||
float vx = vertices[ii];
|
||||
float vy = vertices[ii + 1];
|
||||
minX = Math.Min(minX, vx);
|
||||
minY = Math.Min(minY, vy);
|
||||
maxX = Math.Max(maxX, vx);
|
||||
maxY = Math.Max(maxY, vy);
|
||||
}
|
||||
x = minX;
|
||||
y = minY;
|
||||
w = maxX - minX;
|
||||
h = maxY - minY;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = self.Bone.WorldX;
|
||||
y = self.Bone.WorldY;
|
||||
w = 0;
|
||||
h = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 命中测试, 当插槽全透明或者处于禁用或者骨骼处于未激活则无法命中
|
||||
/// </summary>
|
||||
public static bool HitTest(this ISlot self, float x, float y)
|
||||
{
|
||||
if (self.A <= 0 || !self.Bone.Active || self.Disabled)
|
||||
return false;
|
||||
|
||||
self.GetBounds(out var bx, out var by, out var bw, out var bh);
|
||||
return x >= bx && x <= (bx + bw) && y >= by && y <= (by + bh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前状态包围盒
|
||||
/// </summary>
|
||||
public static void GetBounds(this ISkeleton self, out float x, out float y, out float w, out float h)
|
||||
{
|
||||
float minX = int.MaxValue;
|
||||
float minY = int.MaxValue;
|
||||
float maxX = int.MinValue;
|
||||
float maxY = int.MinValue;
|
||||
foreach (var slot in self.IterDrawOrder())
|
||||
{
|
||||
if (slot.A <= 0 || !slot.Bone.Active || slot.Disabled)
|
||||
continue;
|
||||
|
||||
float[] vertices = new float[8];
|
||||
int verticesLength = 0;
|
||||
var attachment = slot.Attachment;
|
||||
switch (attachment)
|
||||
{
|
||||
case IRegionAttachment:
|
||||
case IMeshAttachment:
|
||||
verticesLength = attachment.ComputeWorldVertices(slot, ref vertices);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (int ii = 0; ii + 1 < verticesLength; ii += 2)
|
||||
{
|
||||
float vx = vertices[ii];
|
||||
float vy = vertices[ii + 1];
|
||||
minX = Math.Min(minX, vx);
|
||||
minY = Math.Min(minY, vy);
|
||||
maxX = Math.Max(maxX, vx);
|
||||
maxY = Math.Max(maxY, vy);
|
||||
}
|
||||
}
|
||||
x = minX;
|
||||
y = minY;
|
||||
w = maxX - minX;
|
||||
h = maxY - minY;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 逐插槽的命中测试, 不会计算处于禁用或者骨骼未激活的插槽, 比整体包围盒稍微精确一些
|
||||
/// </summary>
|
||||
public static bool HitTest(this ISkeleton self, float x, float y)
|
||||
{
|
||||
return self.IterDrawOrder().Any(st => st.HitTest(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
117
Spine/Interfaces/SpineObjectData.cs
Normal file
117
Spine/Interfaces/SpineObjectData.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using Spine.Implementations;
|
||||
using Spine.Interfaces.Attachments;
|
||||
|
||||
namespace Spine.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// 应当继承该类实现多版本, 子类需要提供签名为 <c><see cref="new(string, string)"/></c> 的构造函数
|
||||
/// </summary>
|
||||
public abstract class SpineObjectData :
|
||||
Utils.ImplementationResolver<SpineObjectData, Utils.SpineImplementationAttribute, string>,
|
||||
ISpineObjectData,
|
||||
IDisposable
|
||||
{
|
||||
protected static readonly Logger _logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
/// <summary>
|
||||
/// 构建版本对象
|
||||
/// </summary>
|
||||
public static SpineObjectData New(SpineVersion version, string skelPath, string atlasPath, TextureLoader textureLoader)
|
||||
=> CreateInstance(version.Tag, skelPath, atlasPath, textureLoader);
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数, 继承的子类应当实现一个相同签名的构造函数
|
||||
/// </summary>
|
||||
public SpineObjectData(string skelPath, string atlasPath, TextureLoader textureLoader) { }
|
||||
|
||||
public abstract string SkeletonVersion { get; }
|
||||
|
||||
public abstract ImmutableArray<ISkin> Skins { get; }
|
||||
|
||||
public abstract FrozenDictionary<string, ISkin> SkinsByName { get; }
|
||||
|
||||
public abstract FrozenDictionary<string, FrozenDictionary<string, IAttachment>> SlotAttachments { get; }
|
||||
|
||||
public abstract ImmutableArray<IAnimation> Animations { get; }
|
||||
|
||||
public abstract FrozenDictionary<string, IAnimation> AnimationsByName { get; }
|
||||
|
||||
public abstract float DefaultMix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 释放纹理资源
|
||||
/// </summary>
|
||||
protected abstract void DisposeAtlas();
|
||||
|
||||
/// <summary>
|
||||
/// 创建 skeleton
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public abstract ISkeleton CreateSkeleton();
|
||||
|
||||
/// <summary>
|
||||
/// 创建 animationState
|
||||
/// </summary>
|
||||
public abstract IAnimationState CreateAnimationState();
|
||||
|
||||
/// <summary>
|
||||
/// 创建 skeletonClipping
|
||||
/// </summary>
|
||||
public abstract ISkeletonClipping CreateSkeletonClipping();
|
||||
|
||||
/// <summary>
|
||||
/// 创建空皮肤
|
||||
/// </summary>
|
||||
public abstract ISkin CreateSkin(string name);
|
||||
|
||||
#region IDispose 接口实现
|
||||
|
||||
/// <summary>
|
||||
/// 引用计数, 初始为 1, 每调用一次 Dispose 会减 1, 由于可能被多个实例同时引用, 因此直到小于等于 0 才会真正释放资源
|
||||
/// </summary>
|
||||
private int _refCount = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 增加引用计数, 当使用同一份数据创建实例副本时, 调用方负责使用该方法增加引用计数, 并且使用 Dispose 或者 Finalize 减少引用计数, 初始为 1
|
||||
/// </summary>
|
||||
public void IncRef() => _refCount++;
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_refCount <= 0) return;
|
||||
|
||||
_refCount--;
|
||||
if (_refCount <= 0)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
DisposeAtlas();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~SpineObjectData()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
if (_refCount <= 0)
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user