diff --git a/SpineViewer/Controls/SpineViewPropertyGrid.cs b/SpineViewer/Controls/SpineViewPropertyGrid.cs index 2d35140..38e2397 100644 --- a/SpineViewer/Controls/SpineViewPropertyGrid.cs +++ b/SpineViewer/Controls/SpineViewPropertyGrid.cs @@ -85,7 +85,7 @@ namespace SpineViewer.Controls var spine = selectedSpines[0].Skin.Spine; - if (spine.SkinNames.Count <= 0) + if (spine.SkinNames.Length <= 0) { MessagePopup.Info("没有可用的皮肤"); return; diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs index 2aa7368..c1e564a 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs @@ -1,6 +1,8 @@ using System; using System.Collections; +using System.Collections.Frozen; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.IO; using System.Linq; @@ -87,11 +89,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - foreach (var skin in skeletonData.Skins) - skinNames.Add(skin.Name); - - foreach (var anime in skeletonData.Animations) - animationNames.Add(anime.Name); + 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) + { + _slotAttachmentNames[skeletonData.Slots[k.Key].Name].Add(v.Name); + } + } + SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); + AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器 animationStateData = new AnimationStateData(skeletonData); @@ -197,7 +205,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject { if (name == EMPTY_ANIMATION) animationState.SetAnimation(track, EmptyAnimation, false); - else if (animationNames.Contains(name)) + else if (AnimationNames.Contains(name)) animationState.SetAnimation(track, name, true); } diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs index ccc42e5..3c48fe7 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs @@ -1,6 +1,8 @@ using System; using System.Collections; +using System.Collections.Frozen; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.IO; using System.Linq; @@ -86,11 +88,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - foreach (var skin in skeletonData.Skins) - skinNames.Add(skin.Name); - - foreach (var anime in skeletonData.Animations) - animationNames.Add(anime.Name); + 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) + { + _slotAttachmentNames[skeletonData.Slots.Items[k.slotIndex].Name].Add(v.Name); + } + } + SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); + AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器 animationStateData = new AnimationStateData(skeletonData); @@ -196,7 +204,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject { if (name == EMPTY_ANIMATION) animationState.SetAnimation(track, EmptyAnimation, false); - else if (animationNames.Contains(name)) + else if (AnimationNames.Contains(name)) animationState.SetAnimation(track, name, true); } diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs index 1c4d8b9..71c1562 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Frozen; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -83,11 +85,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - foreach (var skin in skeletonData.Skins) - skinNames.Add(skin.Name); - - foreach (var anime in skeletonData.Animations) - animationNames.Add(anime.Name); + 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) + { + _slotAttachmentNames[skeletonData.Slots.Items[k.slotIndex].Name].Add(v.Name); + } + } + SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); + AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器 animationStateData = new AnimationStateData(skeletonData); @@ -167,7 +175,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject { if (name == EMPTY_ANIMATION) animationState.SetAnimation(track, EmptyAnimation, false); - else if (animationNames.Contains(name)) + else if (AnimationNames.Contains(name)) animationState.SetAnimation(track, name, true); } diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs index 5c3b2ed..a0da77f 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Frozen; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.IO; using System.Linq; @@ -90,11 +92,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - foreach (var skin in skeletonData.Skins) - skinNames.Add(skin.Name); - - foreach (var anime in skeletonData.Animations) - animationNames.Add(anime.Name); + 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) + { + _slotAttachmentNames[skeletonData.Slots.Items[k.SlotIndex].Name].Add(v.Name); + } + } + SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); + AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器 animationStateData = new AnimationStateData(skeletonData); @@ -172,7 +180,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject { if (name == EMPTY_ANIMATION) animationState.SetAnimation(track, EmptyAnimation, false); - else if (animationNames.Contains(name)) + else if (AnimationNames.Contains(name)) animationState.SetAnimation(track, name, true); } diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs index e2fb80e..73c1c9e 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Frozen; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.IO; using System.Linq; @@ -85,11 +87,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - foreach (var skin in skeletonData.Skins) - skinNames.Add(skin.Name); - - foreach (var anime in skeletonData.Animations) - animationNames.Add(anime.Name); + 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); + } + } + SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); + AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器 animationStateData = new AnimationStateData(skeletonData); @@ -167,7 +175,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject { if (name == EMPTY_ANIMATION) animationState.SetAnimation(track, EmptyAnimation, false); - else if (animationNames.Contains(name)) + else if (AnimationNames.Contains(name)) animationState.SetAnimation(track, name, true); } diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs index 20a6339..93e662b 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Frozen; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.IO; using System.Linq; @@ -85,11 +87,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - foreach (var skin in skeletonData.Skins) - skinNames.Add(skin.Name); - - foreach (var anime in skeletonData.Animations) - animationNames.Add(anime.Name); + 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); + } + } + SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); + AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器 animationStateData = new AnimationStateData(skeletonData); @@ -167,7 +175,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject { if (name == EMPTY_ANIMATION) animationState.SetAnimation(track, EmptyAnimation, false); - else if (animationNames.Contains(name)) + else if (AnimationNames.Contains(name)) animationState.SetAnimation(track, name, true); } diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject42.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject42.cs index 21a8a9c..c931e35 100644 --- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject42.cs +++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject42.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Frozen; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.IO; using System.Linq; @@ -85,11 +87,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject } } - foreach (var skin in skeletonData.Skins) - skinNames.Add(skin.Name); - - foreach (var anime in skeletonData.Animations) - animationNames.Add(anime.Name); + 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); + } + } + SlotAttachmentNames = _slotAttachmentNames.ToFrozenDictionary(item => item.Key, item => item.Value.ToImmutableArray()); + SkinNames = skeletonData.Skins.Select(v => v.Name).Where(v => v != "default").ToImmutableArray(); + AnimationNames = skeletonData.Animations.Select(v => v.Name).ToImmutableArray(); skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器 animationStateData = new AnimationStateData(skeletonData); @@ -167,7 +175,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject { if (name == EMPTY_ANIMATION) animationState.SetAnimation(track, EmptyAnimation, false); - else if (animationNames.Contains(name)) + else if (AnimationNames.Contains(name)) animationState.SetAnimation(track, name, true); } diff --git a/SpineViewer/Spine/SpineObject.cs b/SpineViewer/Spine/SpineObject.cs index ee3ce0f..4b92d7e 100644 --- a/SpineViewer/Spine/SpineObject.cs +++ b/SpineViewer/Spine/SpineObject.cs @@ -6,6 +6,8 @@ using NLog; using System.Xml.Linq; using SpineViewer.Extensions; using SpineViewer.Utils; +using System.Collections.Immutable; +using System.Collections.Frozen; namespace SpineViewer.Spine { @@ -14,6 +16,11 @@ namespace SpineViewer.Spine /// public abstract class SpineObject : ImplementationResolver, SFML.Graphics.Drawable, IDisposable { + /// + /// 空附件标记 + /// + protected const string EMPTY_ATTACHMENT = ""; + /// /// 空动画标记 /// @@ -65,9 +72,6 @@ namespace SpineViewer.Spine /// private SpineObject PostInit() { - SkinNames = skinNames.AsReadOnly(); - AnimationNames = animationNames.AsReadOnly(); - // 必须 Update 一次否则包围盒还没有值 update(0); @@ -201,18 +205,6 @@ namespace SpineViewer.Spine } protected abstract bool flipY { get; set; } - /// - /// 包含的所有皮肤名称 - /// - public ReadOnlyCollection SkinNames { get; private set; } - protected readonly List skinNames = []; - - /// - /// 包含的所有动画名称 - /// - public ReadOnlyCollection AnimationNames { get; private set; } - protected readonly List animationNames = [EMPTY_ANIMATION]; - /// /// 是否被选中 /// @@ -333,6 +325,21 @@ namespace SpineViewer.Spine } protected bool debugClippings = false; + /// + /// 所有槽位下可用的附件名 + /// + public FrozenDictionary> SlotAttachmentNames { get; protected set; } + + /// + /// 包含的所有皮肤名称 (不含 default 默认皮肤) + /// + public ImmutableArray SkinNames { get; protected set; } + + /// + /// 包含的所有动画名称 + /// + public ImmutableArray AnimationNames { get; protected set; } + /// /// 获取已加载的皮肤列表快照, 允许出现重复值 /// @@ -344,7 +351,7 @@ namespace SpineViewer.Spine /// public void LoadSkin(string name) { - if (!skinNames.Contains(name)) return; + if (!SkinNames.Contains(name)) return; lock (_lock) { loadedSkins.Add(name); @@ -372,7 +379,7 @@ namespace SpineViewer.Spine { lock (_lock) { - if (idx < 0 || idx >= loadedSkins.Count || !skinNames.Contains(name)) return; + if (idx < 0 || idx >= loadedSkins.Count || !SkinNames.Contains(name)) return; loadedSkins[idx] = name; reloadSkins(); } @@ -576,4 +583,4 @@ namespace SpineViewer.Spine #endregion } -} \ No newline at end of file +}