重构并增加HitTest
This commit is contained in:
23
Spine/Implementations/V34/Animation34.cs
Normal file
23
Spine/Implementations/V34/Animation34.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Spine.Interfaces;
|
||||
using SpineRuntime34;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Implementations.V34
|
||||
{
|
||||
internal sealed class Animation34(Animation innerObject) : IAnimation
|
||||
{
|
||||
private readonly Animation _o = innerObject;
|
||||
|
||||
public Animation InnerObject => _o;
|
||||
|
||||
public string Name => _o.Name;
|
||||
|
||||
public float Duration => _o.Duration;
|
||||
|
||||
public override string ToString() => _o.ToString();
|
||||
}
|
||||
}
|
||||
180
Spine/Implementations/V34/AnimationState34.cs
Normal file
180
Spine/Implementations/V34/AnimationState34.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Spine.Interfaces;
|
||||
using SpineRuntime34;
|
||||
|
||||
namespace Spine.Implementations.V34
|
||||
{
|
||||
internal sealed class AnimationState34(AnimationState innerObject, SpineObjectData34 data) : IAnimationState
|
||||
{
|
||||
private readonly AnimationState _o = innerObject;
|
||||
private readonly SpineObjectData34 _data = data;
|
||||
|
||||
private readonly Dictionary<TrackEntry, TrackEntry34> _trackEntryPool = [];
|
||||
|
||||
private readonly Dictionary<IAnimationState.TrackEntryDelegate, AnimationState.TrackEntryDelegate> _eventMapping = [];
|
||||
private readonly Dictionary<IAnimationState.TrackEntryDelegate, int> _eventCount = [];
|
||||
|
||||
public AnimationState InnerObject => _o;
|
||||
|
||||
#pragma warning disable CS0067
|
||||
|
||||
// NOTE: 3.4 以下没有这两个事件
|
||||
public event IAnimationState.TrackEntryDelegate? Interrupt;
|
||||
public event IAnimationState.TrackEntryDelegate? Dispose;
|
||||
|
||||
#pragma warning restore CS0067
|
||||
|
||||
|
||||
public event IAnimationState.TrackEntryDelegate? Start
|
||||
{
|
||||
add
|
||||
{
|
||||
if (value is null) return;
|
||||
if (!_eventMapping.TryGetValue(value, out var f))
|
||||
{
|
||||
_eventMapping[value] = f = (t) => value(GetTrackEntry(t));
|
||||
_eventCount[value] = 0;
|
||||
}
|
||||
_o.Start += f;
|
||||
_eventCount[value]++;
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (value is null) return;
|
||||
if (_eventMapping.TryGetValue(value, out var f))
|
||||
{
|
||||
_o.Start -= f;
|
||||
_eventCount[value]--;
|
||||
if (_eventCount[value] <= 0)
|
||||
{
|
||||
_eventMapping.Remove(value);
|
||||
_eventCount.Remove(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event IAnimationState.TrackEntryDelegate? End
|
||||
{
|
||||
add
|
||||
{
|
||||
if (value is null) return;
|
||||
if (!_eventMapping.TryGetValue(value, out var f))
|
||||
{
|
||||
_eventMapping[value] = f = (t) => value(GetTrackEntry(t));
|
||||
_eventCount[value] = 0;
|
||||
}
|
||||
_o.End += f;
|
||||
_eventCount[value]++;
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (value is null) return;
|
||||
if (_eventMapping.TryGetValue(value, out var f))
|
||||
{
|
||||
_o.End -= f;
|
||||
_eventCount[value]--;
|
||||
if (_eventCount[value] <= 0)
|
||||
{
|
||||
_eventMapping.Remove(value);
|
||||
_eventCount.Remove(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event IAnimationState.TrackEntryDelegate? Complete
|
||||
{
|
||||
add
|
||||
{
|
||||
if (value is null) return;
|
||||
if (!_eventMapping.TryGetValue(value, out var f))
|
||||
{
|
||||
_eventMapping[value] = f = (t) => value(GetTrackEntry(t));
|
||||
_eventCount[value] = 0;
|
||||
}
|
||||
_o.Complete += f;
|
||||
_eventCount[value]++;
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (value is null) return;
|
||||
if (_eventMapping.TryGetValue(value, out var f))
|
||||
{
|
||||
_o.Complete -= f;
|
||||
_eventCount[value]--;
|
||||
if (_eventCount[value] <= 0)
|
||||
{
|
||||
_eventMapping.Remove(value);
|
||||
_eventCount.Remove(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float TimeScale { get => _o.TimeScale; set => _o.TimeScale = value; }
|
||||
|
||||
public void Update(float delta) => _o.Update(delta);
|
||||
|
||||
public void Apply(ISkeleton skeleton)
|
||||
{
|
||||
if (skeleton is Skeleton34 skel)
|
||||
{
|
||||
_o.Apply(skel.InnerObject);
|
||||
return;
|
||||
}
|
||||
throw new ArgumentException($"Received {skeleton.GetType().Name}", nameof(skeleton));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取 <see cref="ITrackEntry"/> 对象, 不存在则创建
|
||||
/// </summary>
|
||||
public ITrackEntry GetTrackEntry(TrackEntry trackEntry)
|
||||
{
|
||||
if (!_trackEntryPool.TryGetValue(trackEntry, out var tr))
|
||||
_trackEntryPool[trackEntry] = tr = new(trackEntry, this, _data);
|
||||
return tr;
|
||||
}
|
||||
|
||||
public IEnumerable<ITrackEntry?> IterTracks() => _o.Tracks.Select(t => t is null ? null : GetTrackEntry(t));
|
||||
|
||||
public ITrackEntry? GetCurrent(int index) { var t = _o.GetCurrent(index); return t is null ? null : GetTrackEntry(t); }
|
||||
|
||||
public void ClearTrack(int index) => _o.ClearTrack(index);
|
||||
|
||||
public void ClearTracks() => _o.ClearTracks();
|
||||
|
||||
public ITrackEntry SetAnimation(int trackIndex, string animationName, bool loop)
|
||||
=> GetTrackEntry(_o.SetAnimation(trackIndex, animationName, loop));
|
||||
|
||||
public ITrackEntry SetAnimation(int trackIndex, IAnimation animation, bool loop)
|
||||
{
|
||||
if (animation is Animation34 anime)
|
||||
return GetTrackEntry(_o.SetAnimation(trackIndex, anime.InnerObject, loop));
|
||||
throw new ArgumentException($"Received {animation.GetType().Name}", nameof(animation));
|
||||
}
|
||||
|
||||
public ITrackEntry SetEmptyAnimation(int trackIndex, float mixDuration) => GetTrackEntry(_o.SetEmptyAnimation(trackIndex, mixDuration));
|
||||
|
||||
public void SetEmptyAnimations(float mixDuration) => _o.SetEmptyAnimations(mixDuration);
|
||||
|
||||
public ITrackEntry AddAnimation(int trackIndex, string animationName, bool loop, float delay)
|
||||
=> GetTrackEntry(_o.AddAnimation(trackIndex, animationName, loop, delay));
|
||||
|
||||
public ITrackEntry AddAnimation(int trackIndex, IAnimation animation, bool loop, float delay)
|
||||
{
|
||||
if (animation is Animation34 anime)
|
||||
return GetTrackEntry(_o.AddAnimation(trackIndex, anime.InnerObject, loop, delay));
|
||||
throw new ArgumentException($"Received {animation.GetType().Name}", nameof(animation));
|
||||
}
|
||||
|
||||
public ITrackEntry AddEmptyAnimation(int trackIndex, float mixDuration, float delay)
|
||||
=> GetTrackEntry(_o.AddEmptyAnimation(trackIndex, mixDuration, delay));
|
||||
|
||||
public override string ToString() => _o.ToString();
|
||||
}
|
||||
}
|
||||
24
Spine/Implementations/V34/Attachments/Attachment34.cs
Normal file
24
Spine/Implementations/V34/Attachments/Attachment34.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Spine.Interfaces;
|
||||
using Spine.Interfaces.Attachments;
|
||||
using SpineRuntime34;
|
||||
|
||||
namespace Spine.Implementations.V34.Attachments
|
||||
{
|
||||
internal abstract class Attachment34(Attachment innerObject) : IAttachment
|
||||
{
|
||||
private readonly Attachment _o = innerObject;
|
||||
|
||||
public virtual Attachment InnerObject => _o;
|
||||
|
||||
public string Name => _o.Name;
|
||||
|
||||
public abstract int ComputeWorldVertices(ISlot slot, ref float[] worldVertices);
|
||||
|
||||
public override string ToString() => _o.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Spine.Implementations.V34;
|
||||
using Spine.Interfaces;
|
||||
using Spine.Interfaces.Attachments;
|
||||
using SpineRuntime34;
|
||||
|
||||
namespace Spine.Implementations.V34.Attachments
|
||||
{
|
||||
internal sealed class BoundingBoxAttachment34(BoundingBoxAttachment innerObject) :
|
||||
Attachment34(innerObject),
|
||||
IBoundingBoxAttachment
|
||||
{
|
||||
private readonly BoundingBoxAttachment _o = innerObject;
|
||||
|
||||
public override BoundingBoxAttachment InnerObject => _o;
|
||||
|
||||
public override int ComputeWorldVertices(ISlot slot, ref float[] worldVertices)
|
||||
{
|
||||
if (slot is Slot34 st)
|
||||
{
|
||||
var length = _o.WorldVerticesLength;
|
||||
if (worldVertices.Length < length) worldVertices = new float[length];
|
||||
_o.ComputeWorldVertices(st.InnerObject, worldVertices);
|
||||
return length;
|
||||
}
|
||||
throw new ArgumentException($"Invalid slot type. Expected {nameof(Slot34)}, but received {slot.GetType().Name}", nameof(slot));
|
||||
}
|
||||
}
|
||||
}
|
||||
46
Spine/Implementations/V34/Attachments/MeshAttachment34.cs
Normal file
46
Spine/Implementations/V34/Attachments/MeshAttachment34.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Spine.Implementations.V34;
|
||||
using Spine.Interfaces;
|
||||
using Spine.Interfaces.Attachments;
|
||||
using SpineRuntime34;
|
||||
|
||||
namespace Spine.Implementations.V34.Attachments
|
||||
{
|
||||
internal sealed class MeshAttachment34(MeshAttachment innerObject) :
|
||||
Attachment34(innerObject),
|
||||
IMeshAttachment
|
||||
{
|
||||
private readonly MeshAttachment _o = innerObject;
|
||||
|
||||
public override MeshAttachment InnerObject => _o;
|
||||
|
||||
public override int ComputeWorldVertices(ISlot slot, ref float[] worldVertices)
|
||||
{
|
||||
if (slot is Slot34 st)
|
||||
{
|
||||
var length = _o.WorldVerticesLength;
|
||||
if (worldVertices.Length < length) worldVertices = new float[length];
|
||||
_o.ComputeWorldVertices(st.InnerObject, worldVertices);
|
||||
return length;
|
||||
}
|
||||
throw new ArgumentException($"Invalid slot type. Expected {nameof(Slot34)}, but received {slot.GetType().Name}", nameof(slot));
|
||||
}
|
||||
|
||||
public float R { get => _o.R; set => _o.R = value; }
|
||||
public float G { get => _o.G; set => _o.G = value; }
|
||||
public float B { get => _o.B; set => _o.B = value; }
|
||||
public float A { get => _o.A; set => _o.A = value; }
|
||||
|
||||
public SFML.Graphics.Texture RendererObject => (SFML.Graphics.Texture)((AtlasRegion)_o.RendererObject).page.rendererObject;
|
||||
|
||||
public float[] UVs => _o.UVs;
|
||||
|
||||
public int[] Triangles => _o.Triangles;
|
||||
|
||||
public int HullLength => _o.HullLength;
|
||||
}
|
||||
}
|
||||
33
Spine/Implementations/V34/Attachments/PathAttachment34.cs
Normal file
33
Spine/Implementations/V34/Attachments/PathAttachment34.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Spine.Implementations.V34;
|
||||
using Spine.Interfaces;
|
||||
using Spine.Interfaces.Attachments;
|
||||
using SpineRuntime34;
|
||||
|
||||
namespace Spine.Implementations.V34.Attachments
|
||||
{
|
||||
internal sealed class PathAttachment34(PathAttachment innerObject) :
|
||||
Attachment34(innerObject),
|
||||
IPathAttachment
|
||||
{
|
||||
private readonly PathAttachment _o = innerObject;
|
||||
|
||||
public override PathAttachment InnerObject => _o;
|
||||
|
||||
public override int ComputeWorldVertices(ISlot slot, ref float[] worldVertices)
|
||||
{
|
||||
if (slot is Slot34 st)
|
||||
{
|
||||
var length = _o.WorldVerticesLength;
|
||||
if (worldVertices.Length < length) worldVertices = new float[length];
|
||||
_o.ComputeWorldVertices(st.InnerObject, worldVertices);
|
||||
return length;
|
||||
}
|
||||
throw new ArgumentException($"Invalid slot type. Expected {nameof(Slot34)}, but received {slot.GetType().Name}", nameof(slot));
|
||||
}
|
||||
}
|
||||
}
|
||||
41
Spine/Implementations/V34/Attachments/RegionAttachment34.cs
Normal file
41
Spine/Implementations/V34/Attachments/RegionAttachment34.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Spine.Implementations.V34;
|
||||
using Spine.Interfaces;
|
||||
using Spine.Interfaces.Attachments;
|
||||
using SpineRuntime34;
|
||||
|
||||
namespace Spine.Implementations.V34.Attachments
|
||||
{
|
||||
internal sealed class RegionAttachment34(RegionAttachment innerObject) :
|
||||
Attachment34(innerObject),
|
||||
IRegionAttachment
|
||||
{
|
||||
private readonly RegionAttachment _o = innerObject;
|
||||
|
||||
public override RegionAttachment InnerObject => _o;
|
||||
|
||||
public override int ComputeWorldVertices(ISlot slot, ref float[] worldVertices)
|
||||
{
|
||||
if (slot is Slot34 st)
|
||||
{
|
||||
if (worldVertices.Length < 8) worldVertices = new float[8];
|
||||
_o.ComputeWorldVertices(st.InnerObject.Bone, worldVertices);
|
||||
return 8;
|
||||
}
|
||||
throw new ArgumentException($"Invalid slot type. Expected {nameof(Slot34)}, but received {slot.GetType().Name}", nameof(slot));
|
||||
}
|
||||
|
||||
public float R { get => _o.R; set => _o.R = value; }
|
||||
public float G { get => _o.G; set => _o.G = value; }
|
||||
public float B { get => _o.B; set => _o.B = value; }
|
||||
public float A { get => _o.A; set => _o.A = value; }
|
||||
|
||||
public SFML.Graphics.Texture RendererObject => (SFML.Graphics.Texture)((AtlasRegion)_o.RendererObject).page.rendererObject;
|
||||
|
||||
public float[] UVs => _o.UVs;
|
||||
}
|
||||
}
|
||||
33
Spine/Implementations/V34/Bone34.cs
Normal file
33
Spine/Implementations/V34/Bone34.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Spine.Interfaces;
|
||||
using SpineRuntime34;
|
||||
|
||||
namespace Spine.Implementations.V34
|
||||
{
|
||||
internal sealed class Bone34(Bone innerObject, Bone34? parent = null) : IBone
|
||||
{
|
||||
private readonly Bone _o = innerObject;
|
||||
private readonly Bone34? _parent = parent;
|
||||
|
||||
public Bone InnerObject => _o;
|
||||
|
||||
public string Name => _o.Data.Name;
|
||||
public int Index => _o.Data.Index;
|
||||
|
||||
public IBone? Parent => _parent;
|
||||
public bool Active => true; // NOTE: 3.7 及以下没有 Active 属性, 此处总是返回 true
|
||||
public float Length => _o.Data.Length;
|
||||
public float WorldX => _o.WorldX;
|
||||
public float WorldY => _o.WorldY;
|
||||
public float A => _o.A;
|
||||
public float B => _o.B;
|
||||
public float C => _o.C;
|
||||
public float D => _o.D;
|
||||
|
||||
public override string ToString() => _o.ToString();
|
||||
}
|
||||
}
|
||||
100
Spine/Implementations/V34/Skeleton34.cs
Normal file
100
Spine/Implementations/V34/Skeleton34.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Immutable;
|
||||
using SpineRuntime34;
|
||||
using Spine.Interfaces;
|
||||
|
||||
namespace Spine.Implementations.V34
|
||||
{
|
||||
internal sealed class Skeleton34 : ISkeleton
|
||||
{
|
||||
private readonly Skeleton _o;
|
||||
private readonly SpineObjectData34 _data;
|
||||
|
||||
private readonly ImmutableArray<IBone> _bones;
|
||||
private readonly FrozenDictionary<string, IBone> _bonesByName;
|
||||
private readonly ImmutableArray<ISlot> _slots;
|
||||
private readonly FrozenDictionary<string, ISlot> _slotsByName;
|
||||
|
||||
private Skin34? _skin;
|
||||
|
||||
public Skeleton34(Skeleton innerObject, SpineObjectData34 data)
|
||||
{
|
||||
_o = innerObject;
|
||||
_data = data;
|
||||
|
||||
List<Bone34> bones = [];
|
||||
Dictionary<string, IBone> bonesByName = [];
|
||||
foreach (var b in _o.Bones)
|
||||
{
|
||||
var bone = new Bone34(b, b.Parent is null ? null : bones[b.Parent.Data.Index]);
|
||||
bones.Add(bone);
|
||||
bonesByName[bone.Name] = bone;
|
||||
}
|
||||
_bones = bones.Cast<IBone>().ToImmutableArray();
|
||||
_bonesByName = bonesByName.ToFrozenDictionary();
|
||||
|
||||
List<Slot34> slots = [];
|
||||
Dictionary<string, ISlot> slotsByName = [];
|
||||
foreach (var s in _o.Slots)
|
||||
{
|
||||
var slot = new Slot34(s, _data, bones[s.Bone.Data.Index]);
|
||||
slots.Add(slot);
|
||||
slotsByName[slot.Name] = slot;
|
||||
}
|
||||
_slots = slots.Cast<ISlot>().ToImmutableArray();
|
||||
_slotsByName = slotsByName.ToFrozenDictionary();
|
||||
}
|
||||
|
||||
public Skeleton InnerObject => _o;
|
||||
|
||||
public float R { get => _o.R; set => _o.R = value; }
|
||||
public float G { get => _o.G; set => _o.G = value; }
|
||||
public float B { get => _o.B; set => _o.B = value; }
|
||||
public float A { get => _o.A; set => _o.A = value; }
|
||||
public float X { get => _o.X; set => _o.X = value; }
|
||||
public float Y { get => _o.Y; set => _o.Y = value; }
|
||||
public float ScaleX { get => _o.ScaleX; set => _o.ScaleX = value; }
|
||||
public float ScaleY { get => _o.ScaleY; set => _o.ScaleY = value; }
|
||||
|
||||
public ImmutableArray<IBone> Bones => _bones;
|
||||
public FrozenDictionary<string, IBone> BonesByName => _bonesByName;
|
||||
public ImmutableArray<ISlot> Slots => _slots;
|
||||
public FrozenDictionary<string, ISlot> SlotsByName => _slotsByName;
|
||||
|
||||
public ISkin? Skin
|
||||
{
|
||||
get => _skin;
|
||||
set
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
_o.Skin = null;
|
||||
_skin = null;
|
||||
return;
|
||||
}
|
||||
if (value is Skin34 sk)
|
||||
{
|
||||
_o.Skin = sk.InnerObject;
|
||||
_skin = sk;
|
||||
return;
|
||||
}
|
||||
throw new ArgumentException($"Received {value.GetType().Name}", nameof(value));
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ISlot> IterDrawOrder() => _o.DrawOrder.Select(s => _slots[s.Data.Index]);
|
||||
public void UpdateCache() => _o.UpdateCache();
|
||||
public void UpdateWorldTransform(ISkeleton.Physics physics) => _o.UpdateWorldTransform();
|
||||
public void SetToSetupPose() => _o.SetToSetupPose();
|
||||
public void SetBonesToSetupPose() => _o.SetBonesToSetupPose();
|
||||
public void SetSlotsToSetupPose() => _o.SetSlotsToSetupPose();
|
||||
public void Update(float delta) => _o.Update(delta);
|
||||
|
||||
public override string ToString() => _o.ToString();
|
||||
}
|
||||
}
|
||||
42
Spine/Implementations/V34/SkeletonClipping34.cs
Normal file
42
Spine/Implementations/V34/SkeletonClipping34.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Spine.Interfaces;
|
||||
using Spine.Interfaces.Attachments;
|
||||
using Spine.Utils;
|
||||
using SpineRuntime34;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Implementations.V34
|
||||
{
|
||||
internal sealed class SkeletonClipping34 : ISkeletonClipping
|
||||
{
|
||||
public bool IsClipping => false;
|
||||
|
||||
public float[] ClippedVertices { get; private set; } = [];
|
||||
|
||||
public int ClippedVerticesLength { get; private set; } = 0;
|
||||
|
||||
public int[] ClippedTriangles { get; private set; } = [];
|
||||
|
||||
public int ClippedTrianglesLength { get; private set; } = 0;
|
||||
|
||||
public float[] ClippedUVs { get; private set; } = [];
|
||||
|
||||
public void ClipEnd(ISlot slot) { }
|
||||
|
||||
public void ClipEnd() { }
|
||||
|
||||
public void ClipStart(ISlot slot, IClippingAttachment clippingAttachment) { }
|
||||
|
||||
public void ClipTriangles(float[] vertices, int verticesLength, int[] triangles, int trianglesLength, float[] uvs)
|
||||
{
|
||||
ClippedVertices = vertices.ToArray();
|
||||
ClippedVerticesLength = verticesLength;
|
||||
ClippedTriangles = triangles.ToArray();
|
||||
ClippedTrianglesLength = trianglesLength;
|
||||
ClippedUVs = uvs.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
45
Spine/Implementations/V34/Skin34.cs
Normal file
45
Spine/Implementations/V34/Skin34.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Spine.Interfaces;
|
||||
using SpineRuntime34;
|
||||
|
||||
namespace Spine.Implementations.V34
|
||||
{
|
||||
internal sealed class Skin34 : ISkin
|
||||
{
|
||||
private readonly Skin _o;
|
||||
|
||||
/// <summary>
|
||||
/// 使用指定名字创建空皮肤
|
||||
/// </summary>
|
||||
public Skin34(string name) => _o = new(name);
|
||||
|
||||
/// <summary>
|
||||
/// 包装已有皮肤对象
|
||||
/// </summary>
|
||||
public Skin34(Skin innerObject) => _o = innerObject;
|
||||
|
||||
public Skin InnerObject => _o;
|
||||
|
||||
public string Name => _o.Name;
|
||||
|
||||
public void AddSkin(ISkin skin)
|
||||
{
|
||||
if (skin is Skin34 sk)
|
||||
{
|
||||
// NOTE: 3.7 及以下不支持 AddSkin
|
||||
foreach (var (k, v) in sk._o.Attachments)
|
||||
_o.AddAttachment(k.slotIndex, k.name, v);
|
||||
return;
|
||||
}
|
||||
throw new ArgumentException($"Received {skin.GetType().Name}", nameof(skin));
|
||||
}
|
||||
|
||||
public void Clear() => _o.Attachments.Clear();
|
||||
|
||||
public override string ToString() => _o.ToString();
|
||||
}
|
||||
}
|
||||
81
Spine/Implementations/V34/Slot34.cs
Normal file
81
Spine/Implementations/V34/Slot34.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Spine.Utils;
|
||||
using SpineRuntime34;
|
||||
using Spine.Interfaces;
|
||||
using Spine.Interfaces.Attachments;
|
||||
|
||||
namespace Spine.Implementations.V34
|
||||
{
|
||||
internal sealed class Slot34 : ISlot
|
||||
{
|
||||
private readonly Slot _o;
|
||||
private readonly SpineObjectData34 _data;
|
||||
|
||||
private readonly Bone34 _bone;
|
||||
private readonly SFML.Graphics.BlendMode _blendMode;
|
||||
|
||||
public Slot34(Slot innerObject, SpineObjectData34 data, Bone34 bone)
|
||||
{
|
||||
_o = innerObject;
|
||||
_data = data;
|
||||
|
||||
_bone = bone;
|
||||
_blendMode = _o.Data.BlendMode switch
|
||||
{
|
||||
BlendMode.normal => SFMLBlendMode.NormalPma,
|
||||
BlendMode.additive => SFMLBlendMode.AdditivePma,
|
||||
BlendMode.multiply => SFMLBlendMode.MultiplyPma,
|
||||
BlendMode.screen => SFMLBlendMode.ScreenPma,
|
||||
_ => throw new NotImplementedException($"{_o.Data.BlendMode}"),
|
||||
};
|
||||
}
|
||||
|
||||
public Slot InnerObject => _o;
|
||||
|
||||
public string Name => _o.Data.Name;
|
||||
public int Index => _o.Data.Index;
|
||||
public SFML.Graphics.BlendMode Blend => _blendMode;
|
||||
|
||||
public float R { get => _o.R; set => _o.R = value; }
|
||||
public float G { get => _o.G; set => _o.G = value; }
|
||||
public float B { get => _o.B; set => _o.B = value; }
|
||||
public float A { get => _o.A; set => _o.A = value; }
|
||||
public IBone Bone => _bone;
|
||||
|
||||
public IAttachment? Attachment
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_o.Attachment is Attachment att)
|
||||
{
|
||||
return _data.SlotAttachments[Name][att.Name];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (value is null)
|
||||
{
|
||||
_o.Attachment = null;
|
||||
return;
|
||||
}
|
||||
if (value is Attachments.Attachment34 att)
|
||||
{
|
||||
_o.Attachment = att.InnerObject;
|
||||
return;
|
||||
}
|
||||
throw new ArgumentException($"Received {value.GetType().Name}", nameof(value));
|
||||
}
|
||||
}
|
||||
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
public override string ToString() => _o.ToString();
|
||||
}
|
||||
}
|
||||
146
Spine/Implementations/V34/SpineObjectData34.cs
Normal file
146
Spine/Implementations/V34/SpineObjectData34.cs
Normal file
@@ -0,0 +1,146 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Spine.Utils;
|
||||
using SpineRuntime34;
|
||||
using Spine.Implementations.V34.Attachments;
|
||||
using Spine.Interfaces;
|
||||
using Spine.Interfaces.Attachments;
|
||||
|
||||
namespace Spine.Implementations.V34
|
||||
{
|
||||
[SpineImplementation(3, 4)]
|
||||
internal sealed class SpineObjectData34 : SpineObjectData
|
||||
{
|
||||
private readonly Atlas _atlas;
|
||||
private readonly SkeletonData _skeletonData;
|
||||
private readonly AnimationStateData _animationStateData;
|
||||
|
||||
private readonly ImmutableArray<ISkin> _skins;
|
||||
private readonly FrozenDictionary<string, ISkin> _skinsByName;
|
||||
private readonly FrozenDictionary<string, FrozenDictionary<string, IAttachment>> _slotAttachments;
|
||||
private readonly ImmutableArray<IAnimation> _animations;
|
||||
private readonly FrozenDictionary<string, IAnimation> _animationsByName;
|
||||
|
||||
public SpineObjectData34(string skelPath, string atlasPath, TextureLoader textureLoader)
|
||||
: base(skelPath, atlasPath, textureLoader)
|
||||
{
|
||||
// 加载 atlas
|
||||
try
|
||||
{
|
||||
_atlas = new Atlas(atlasPath, textureLoader);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Trace(ex.ToString());
|
||||
throw new InvalidDataException($"Failed to load atlas '{atlasPath}'");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (Utf8Validator.IsUtf8(skelPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
_skeletonData = new SkeletonJson(_atlas).ReadSkeletonData(skelPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Trace(ex.ToString());
|
||||
_skeletonData = new SkeletonBinary(_atlas).ReadSkeletonData(skelPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
_skeletonData = new SkeletonBinary(_atlas).ReadSkeletonData(skelPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Trace(ex.ToString());
|
||||
_skeletonData = new SkeletonJson(_atlas).ReadSkeletonData(skelPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_atlas.Dispose();
|
||||
_logger.Trace(ex.ToString());
|
||||
throw new InvalidDataException($"Failed to load skeleton file {skelPath}");
|
||||
}
|
||||
|
||||
// 加载动画数据
|
||||
_animationStateData = new AnimationStateData(_skeletonData);
|
||||
|
||||
// 整理皮肤和附件
|
||||
Dictionary<string, Dictionary<string, IAttachment>> slotAttachments = [];
|
||||
List<ISkin> skins = [];
|
||||
Dictionary<string, ISkin> skinsByName = [];
|
||||
foreach (var s in _skeletonData.Skins)
|
||||
{
|
||||
var skin = new Skin34(s);
|
||||
skins.Add(skin);
|
||||
skinsByName[s.Name] = skin;
|
||||
foreach (var (k, att) in s.Attachments)
|
||||
{
|
||||
var slotName = _skeletonData.Slots.Items[k.slotIndex].Name;
|
||||
if (!slotAttachments.TryGetValue(slotName, out var attachments))
|
||||
slotAttachments[slotName] = attachments = [];
|
||||
|
||||
attachments[att.Name] = att switch
|
||||
{
|
||||
RegionAttachment regionAtt => new RegionAttachment34(regionAtt),
|
||||
MeshAttachment meshAtt => new MeshAttachment34(meshAtt),
|
||||
BoundingBoxAttachment bbAtt => new BoundingBoxAttachment34(bbAtt),
|
||||
PathAttachment pathAtt => new PathAttachment34(pathAtt),
|
||||
_ => throw new InvalidOperationException($"Unrecognized attachment type {att.GetType().FullName}")
|
||||
};
|
||||
}
|
||||
}
|
||||
_slotAttachments = slotAttachments.ToFrozenDictionary(it => it.Key, it => it.Value.ToFrozenDictionary());
|
||||
_skins = skins.ToImmutableArray();
|
||||
_skinsByName = skinsByName.ToFrozenDictionary();
|
||||
|
||||
// 整理所有动画数据
|
||||
List<IAnimation> animations = [];
|
||||
Dictionary<string, IAnimation> animationsByName = [];
|
||||
foreach (var a in _skeletonData.Animations)
|
||||
{
|
||||
var anime = new Animation34(a);
|
||||
animations.Add(anime);
|
||||
animationsByName[anime.Name] = anime;
|
||||
}
|
||||
_animations = animations.ToImmutableArray();
|
||||
_animationsByName = animationsByName.ToFrozenDictionary();
|
||||
}
|
||||
|
||||
public override string SkeletonVersion => _skeletonData.Version;
|
||||
|
||||
public override ImmutableArray<ISkin> Skins => _skins;
|
||||
|
||||
public override FrozenDictionary<string, ISkin> SkinsByName => _skinsByName;
|
||||
|
||||
public override FrozenDictionary<string, FrozenDictionary<string, IAttachment>> SlotAttachments => _slotAttachments;
|
||||
|
||||
public override float DefaultMix { get => _animationStateData.DefaultMix; set => _animationStateData.DefaultMix = value; }
|
||||
|
||||
public override ImmutableArray<IAnimation> Animations => _animations;
|
||||
|
||||
public override FrozenDictionary<string, IAnimation> AnimationsByName => _animationsByName;
|
||||
|
||||
protected override void DisposeAtlas() => _atlas.Dispose();
|
||||
|
||||
public override ISkeleton CreateSkeleton() => new Skeleton34(new(_skeletonData), this);
|
||||
|
||||
public override IAnimationState CreateAnimationState() => new AnimationState34(new(_animationStateData), this);
|
||||
|
||||
public override ISkeletonClipping CreateSkeletonClipping() => new SkeletonClipping34();
|
||||
|
||||
public override ISkin CreateSkin(string name) => new Skin34(name);
|
||||
}
|
||||
}
|
||||
135
Spine/Implementations/V34/TrackEntry34.cs
Normal file
135
Spine/Implementations/V34/TrackEntry34.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using Spine.Interfaces;
|
||||
using SpineRuntime34;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Spine.Implementations.V34
|
||||
{
|
||||
internal sealed class TrackEntry34(TrackEntry innerObject, AnimationState34 animationState, SpineObjectData34 data): ITrackEntry
|
||||
{
|
||||
private readonly TrackEntry _o = innerObject;
|
||||
private readonly AnimationState34 _animationState = animationState;
|
||||
private readonly SpineObjectData34 _data = data;
|
||||
|
||||
private readonly Dictionary<IAnimationState.TrackEntryDelegate, AnimationState.TrackEntryDelegate> _eventMapping = [];
|
||||
private readonly Dictionary<IAnimationState.TrackEntryDelegate, int> _eventCount = [];
|
||||
|
||||
public TrackEntry InnerObject => _o;
|
||||
|
||||
#pragma warning disable CS0067
|
||||
|
||||
// 3.4 及以下没有这两个事件
|
||||
public event IAnimationState.TrackEntryDelegate? Interrupt;
|
||||
public event IAnimationState.TrackEntryDelegate? Dispose;
|
||||
|
||||
#pragma warning restore CS0067
|
||||
|
||||
public event IAnimationState.TrackEntryDelegate? Start
|
||||
{
|
||||
add
|
||||
{
|
||||
if (value is null) return;
|
||||
if (!_eventMapping.TryGetValue(value, out var f))
|
||||
{
|
||||
_eventMapping[value] = f = (t) => value(_animationState.GetTrackEntry(t));
|
||||
_eventCount[value] = 0;
|
||||
}
|
||||
_o.Start += f;
|
||||
_eventCount[value]++;
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (value is null) return;
|
||||
if (_eventMapping.TryGetValue(value, out var f))
|
||||
{
|
||||
_o.Start -= f;
|
||||
_eventCount[value]--;
|
||||
if (_eventCount[value] <= 0)
|
||||
{
|
||||
_eventMapping.Remove(value);
|
||||
_eventCount.Remove(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event IAnimationState.TrackEntryDelegate? End
|
||||
{
|
||||
add
|
||||
{
|
||||
if (value is null) return;
|
||||
if (!_eventMapping.TryGetValue(value, out var f))
|
||||
{
|
||||
_eventMapping[value] = f = (t) => value(_animationState.GetTrackEntry(t));
|
||||
_eventCount[value] = 0;
|
||||
}
|
||||
_o.End += f;
|
||||
_eventCount[value]++;
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (value is null) return;
|
||||
if (_eventMapping.TryGetValue(value, out var f))
|
||||
{
|
||||
_o.End -= f;
|
||||
_eventCount[value]--;
|
||||
if (_eventCount[value] <= 0)
|
||||
{
|
||||
_eventMapping.Remove(value);
|
||||
_eventCount.Remove(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event IAnimationState.TrackEntryDelegate? Complete
|
||||
{
|
||||
add
|
||||
{
|
||||
if (value is null) return;
|
||||
if (!_eventMapping.TryGetValue(value, out var f))
|
||||
{
|
||||
_eventMapping[value] = f = (t) => value(_animationState.GetTrackEntry(t));
|
||||
_eventCount[value] = 0;
|
||||
}
|
||||
_o.Complete += f;
|
||||
_eventCount[value]++;
|
||||
}
|
||||
remove
|
||||
{
|
||||
if (value is null) return;
|
||||
if (_eventMapping.TryGetValue(value, out var f))
|
||||
{
|
||||
_o.Complete -= f;
|
||||
_eventCount[value]--;
|
||||
if (_eventCount[value] <= 0)
|
||||
{
|
||||
_eventMapping.Remove(value);
|
||||
_eventCount.Remove(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int TrackIndex { get => _o.TrackIndex; }
|
||||
|
||||
public IAnimation Animation { get => _data.AnimationsByName[_o.Animation.Name]; }
|
||||
|
||||
public ITrackEntry? Next { get { var t = _o.Next; return t is null ? null : _animationState.GetTrackEntry(t); } }
|
||||
|
||||
public bool Loop { get => _o.Loop; set => _o.Loop = value; }
|
||||
|
||||
public float TrackTime { get => _o.Time; set => _o.Time = value; }
|
||||
|
||||
public float TimeScale { get => _o.TimeScale; set => _o.TimeScale = value; }
|
||||
|
||||
public float Alpha { get => _o.Mix; set => _o.Mix = value; }
|
||||
|
||||
public float MixDuration { get => _o.MixDuration; set => _o.MixDuration = value; }
|
||||
|
||||
public override string ToString() => _o.ToString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user