diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs index 2b52fe9..e700783 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs @@ -63,6 +63,11 @@ namespace SpineViewer.Spine.Implementations.SpineObject // 2.1.x 不支持剪裁 //private SkeletonClipping clipping = new(); + /// + /// 所有槽位在所有皮肤中可用的附件集合 + /// + private readonly Dictionary> slotAttachments = []; + public SpineObject21(string skelPath, string atlasPath) : base(skelPath, atlasPath) { atlas = new Atlas(AtlasPath, textureLoader); @@ -89,15 +94,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List() { EMPTY_ATTACHMENT }); foreach (var sk in skeletonData.Skins) { - foreach (var (k, v) in sk.Attachments) + foreach (var (k, att) in sk.Attachments) { - _slotAttachmentNames[skeletonData.Slots[k.Key].Name].Add(v.Name); + var slotName = skeletonData.Slots[k.Key].Name; + if (!slotAttachments.TryGetValue(slotName, out var attachments)) + slotAttachments[slotName] = attachments = new() { [EMPTY_ATTACHMENT] = null }; + attachments[att.Name] = att; } } - SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SlotAttachmentNames = slotAttachments.ToFrozenDictionary(item => item.Key, item => item.Value.Keys.ToImmutableArray()); SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); @@ -180,6 +187,16 @@ namespace SpineViewer.Spine.Implementations.SpineObject set => skeleton.FlipY = value; } + protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT; + + protected override void setSlotAttachment(string slot, string name) + { + if (slotAttachments.TryGetValue(slot, out var attachments) + && attachments.TryGetValue(name, out var att) + && skeleton.FindSlot(slot) is Slot s) + s.Attachment = att; + } + protected override void addSkin(string name) { if (skeletonData.FindSkin(name) is Skin sk) diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs index d9bacac..4277aeb 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs @@ -62,6 +62,11 @@ namespace SpineViewer.Spine.Implementations.SpineObject private readonly SkeletonClipping clipping = new(); + /// + /// 所有槽位在所有皮肤中可用的附件集合 + /// + private readonly Dictionary> slotAttachments = []; + public SpineObject36(string skelPath, string atlasPath) : base(skelPath, atlasPath) { atlas = new Atlas(AtlasPath, textureLoader); @@ -88,15 +93,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List() { EMPTY_ATTACHMENT }); foreach (var sk in skeletonData.Skins) { - foreach (var (k, v) in sk.Attachments) + foreach (var (k, att) in sk.Attachments) { - _slotAttachmentNames[skeletonData.Slots.Items[k.slotIndex].Name].Add(v.Name); + var slotName = skeletonData.Slots.Items[k.slotIndex].Name; + if (!slotAttachments.TryGetValue(slotName, out var attachments)) + slotAttachments[slotName] = attachments = new() { [EMPTY_ATTACHMENT] = null }; + attachments[att.Name] = att; } } - SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SlotAttachmentNames = slotAttachments.ToFrozenDictionary(item => item.Key, item => item.Value.Keys.ToImmutableArray()); SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); @@ -179,6 +186,16 @@ namespace SpineViewer.Spine.Implementations.SpineObject set => skeleton.FlipY = value; } + protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT; + + protected override void setSlotAttachment(string slot, string name) + { + if (slotAttachments.TryGetValue(slot, out var attachments) + && attachments.TryGetValue(name, out var att) + && skeleton.FindSlot(slot) is Slot s) + s.Attachment = att; + } + protected override void addSkin(string name) { if (skeletonData.FindSkin(name) is Skin sk) diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs index c432c01..5efcb26 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs @@ -59,6 +59,11 @@ namespace SpineViewer.Spine.Implementations.SpineObject private readonly SkeletonClipping clipping = new(); + /// + /// 所有槽位在所有皮肤中可用的附件集合 + /// + private readonly Dictionary> slotAttachments = []; + public SpineObject37(string skelPath, string atlasPath) : base(skelPath, atlasPath) { atlas = new Atlas(AtlasPath, textureLoader); @@ -85,15 +90,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List() { EMPTY_ATTACHMENT }); foreach (var sk in skeletonData.Skins) { - foreach (var (k, v) in sk.Attachments) + foreach (var (k, att) in sk.Attachments) { - _slotAttachmentNames[skeletonData.Slots.Items[k.slotIndex].Name].Add(v.Name); + var slotName = skeletonData.Slots.Items[k.slotIndex].Name; + if (!slotAttachments.TryGetValue(slotName, out var attachments)) + slotAttachments[slotName] = attachments = new() { [EMPTY_ATTACHMENT] = null }; + attachments[att.Name] = att; } } - SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SlotAttachmentNames = slotAttachments.ToFrozenDictionary(item => item.Key, item => item.Value.Keys.ToImmutableArray()); SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); @@ -150,6 +157,16 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } + protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT; + + protected override void setSlotAttachment(string slot, string name) + { + if (slotAttachments.TryGetValue(slot, out var attachments) + && attachments.TryGetValue(name, out var att) + && skeleton.FindSlot(slot) is Slot s) + s.Attachment = att; + } + protected override void addSkin(string name) { if (skeletonData.FindSkin(name) is Skin sk) diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs index 30e5fbe..2153dbd 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs @@ -66,6 +66,11 @@ namespace SpineViewer.Spine.Implementations.SpineObject private readonly SkeletonClipping clipping = new(); + /// + /// 所有槽位在所有皮肤中可用的附件集合 + /// + private readonly Dictionary> slotAttachments = []; + public SpineObject38(string skelPath, string atlasPath) : base(skelPath, atlasPath) { atlas = new Atlas(AtlasPath, textureLoader); @@ -92,15 +97,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List() { EMPTY_ATTACHMENT }); foreach (var sk in skeletonData.Skins) { - foreach (var (k, v) in sk.Attachments) + foreach (var (k, att) in sk.Attachments) { - _slotAttachmentNames[skeletonData.Slots.Items[k.SlotIndex].Name].Add(v.Name); + var slotName = skeletonData.Slots.Items[k.SlotIndex].Name; + if (!slotAttachments.TryGetValue(slotName, out var attachments)) + slotAttachments[slotName] = attachments = new() { [EMPTY_ATTACHMENT] = null }; + attachments[att.Name] = att; } } - SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SlotAttachmentNames = slotAttachments.ToFrozenDictionary(item => item.Key, item => item.Value.Keys.ToImmutableArray()); SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); @@ -157,6 +164,16 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } + protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT; + + protected override void setSlotAttachment(string slot, string name) + { + if (slotAttachments.TryGetValue(slot, out var attachments) + && attachments.TryGetValue(name, out var att) + && skeleton.FindSlot(slot) is Slot s) + s.Attachment = att; + } + protected override void addSkin(string name) { if (skeletonData.FindSkin(name) is Skin sk) diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs index cedfb5f..b869411 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs @@ -61,6 +61,11 @@ namespace SpineViewer.Spine.Implementations.SpineObject private readonly SkeletonClipping clipping = new(); + /// + /// 所有槽位在所有皮肤中可用的附件集合 + /// + private readonly Dictionary> slotAttachments = []; + public SpineObject40(string skelPath, string atlasPath) : base(skelPath, atlasPath) { atlas = new Atlas(AtlasPath, textureLoader); @@ -87,15 +92,18 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List() { EMPTY_ATTACHMENT }); foreach (var sk in skeletonData.Skins) { foreach (var e in sk.Attachments) { - _slotAttachmentNames[skeletonData.Slots.Items[e.SlotIndex].Name].Add(e.Attachment.Name); + var slotName = skeletonData.Slots.Items[e.SlotIndex].Name; + var att = e.Attachment; + if (!slotAttachments.TryGetValue(slotName, out var attachments)) + slotAttachments[slotName] = attachments = new() { [EMPTY_ATTACHMENT] = null }; + attachments[att.Name] = att; } } - SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SlotAttachmentNames = slotAttachments.ToFrozenDictionary(item => item.Key, item => item.Value.Keys.ToImmutableArray()); SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); @@ -152,6 +160,16 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } + protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT; + + protected override void setSlotAttachment(string slot, string name) + { + if (slotAttachments.TryGetValue(slot, out var attachments) + && attachments.TryGetValue(name, out var att) + && skeleton.FindSlot(slot) is Slot s) + s.Attachment = att; + } + protected override void addSkin(string name) { if (skeletonData.FindSkin(name) is Skin sk) diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs index 6c5e757..8ca2136 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs @@ -61,6 +61,11 @@ namespace SpineViewer.Spine.Implementations.SpineObject private readonly SkeletonClipping clipping = new(); + /// + /// 所有槽位在所有皮肤中可用的附件集合 + /// + private readonly Dictionary> slotAttachments = []; + public SpineObject41(string skelPath, string atlasPath) : base(skelPath, atlasPath) { atlas = new Atlas(AtlasPath, textureLoader); @@ -87,15 +92,18 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List() { EMPTY_ATTACHMENT }); foreach (var sk in skeletonData.Skins) { foreach (var e in sk.Attachments) { - _slotAttachmentNames[skeletonData.Slots.Items[e.SlotIndex].Name].Add(e.Attachment.Name); + var slotName = skeletonData.Slots.Items[e.SlotIndex].Name; + var att = e.Attachment; + if (!slotAttachments.TryGetValue(slotName, out var attachments)) + slotAttachments[slotName] = attachments = new() { [EMPTY_ATTACHMENT] = null }; + attachments[att.Name] = att; } } - SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SlotAttachmentNames = slotAttachments.ToFrozenDictionary(item => item.Key, item => item.Value.Keys.ToImmutableArray()); SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); @@ -152,6 +160,16 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } + protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT; + + protected override void setSlotAttachment(string slot, string name) + { + if (slotAttachments.TryGetValue(slot, out var attachments) + && attachments.TryGetValue(name, out var att) + && skeleton.FindSlot(slot) is Slot s) + s.Attachment = att; + } + protected override void addSkin(string name) { if (skeletonData.FindSkin(name) is Skin sk) diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject42.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject42.cs index 455036a..fa84fad 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject42.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject42.cs @@ -61,6 +61,11 @@ namespace SpineViewer.Spine.Implementations.SpineObject private readonly SkeletonClipping clipping = new(); + /// + /// 所有槽位在所有皮肤中可用的附件集合 + /// + private readonly Dictionary> slotAttachments = []; + public SpineObject42(string skelPath, string atlasPath) : base(skelPath, atlasPath) { atlas = new Atlas(AtlasPath, textureLoader); @@ -87,15 +92,18 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List() { EMPTY_ATTACHMENT }); foreach (var sk in skeletonData.Skins) { foreach (var e in sk.Attachments) { - _slotAttachmentNames[skeletonData.Slots.Items[e.SlotIndex].Name].Add(e.Attachment.Name); + var slotName = skeletonData.Slots.Items[e.SlotIndex].Name; + var att = e.Attachment; + if (!slotAttachments.TryGetValue(slotName, out var attachments)) + slotAttachments[slotName] = attachments = new() { [EMPTY_ATTACHMENT] = null }; + attachments[att.Name] = att; } } - SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SlotAttachmentNames = slotAttachments.ToFrozenDictionary(item => item.Key, item => item.Value.Keys.ToImmutableArray()); SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); @@ -152,6 +160,16 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } + protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT; + + protected override void setSlotAttachment(string slot, string name) + { + if (slotAttachments.TryGetValue(slot, out var attachments) + && attachments.TryGetValue(name, out var att) + && skeleton.FindSlot(slot) is Slot s) + s.Attachment = att; + } + protected override void addSkin(string name) { if (skeletonData.FindSkin(name) is Skin sk) diff --git a/SpineViewer/Spine/SpineObject.cs b/SpineViewer/Spine/SpineObject.cs index 7eae6d8..4b670cc 100644 --- a/SpineViewer/Spine/SpineObject.cs +++ b/SpineViewer/Spine/SpineObject.cs @@ -339,6 +339,18 @@ namespace SpineViewer.Spine /// public ImmutableArray AnimationNames { get; protected set; } + /// + /// 获取某个槽位当前加载的附件 + /// + public string GetSlotAttachment(string slot) { lock (_lock) return getSlotAttachment(slot); } + protected abstract string getSlotAttachment(string slot); + + /// + /// 设置某个槽位当前加载的附件 + /// + public void SetSlotAttachment(string slot, string name) { lock (_lock) setSlotAttachment(slot, name); } + protected abstract void setSlotAttachment(string slot, string name); + /// /// 皮肤的加载情况记录表 ///