增加SlotAttachmentNames

This commit is contained in:
ww-rm
2025-04-18 19:31:33 +08:00
parent 6b9017d535
commit 0b0d036f08
9 changed files with 124 additions and 61 deletions

View File

@@ -85,7 +85,7 @@ namespace SpineViewer.Controls
var spine = selectedSpines[0].Skin.Spine; var spine = selectedSpines[0].Skin.Spine;
if (spine.SkinNames.Count <= 0) if (spine.SkinNames.Length <= 0)
{ {
MessagePopup.Info("没有可用的皮肤"); MessagePopup.Info("没有可用的皮肤");
return; return;

View File

@@ -1,6 +1,8 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Frozen;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -87,11 +89,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject
} }
} }
foreach (var skin in skeletonData.Skins) var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List<string>() { EMPTY_ATTACHMENT });
skinNames.Add(skin.Name); foreach (var sk in skeletonData.Skins)
{
foreach (var anime in skeletonData.Animations) foreach (var (k, v) in sk.Attachments)
animationNames.Add(anime.Name); {
_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()) }; // 挂载一个空皮肤当作容器 skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData); animationStateData = new AnimationStateData(skeletonData);
@@ -197,7 +205,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
{ {
if (name == EMPTY_ANIMATION) if (name == EMPTY_ANIMATION)
animationState.SetAnimation(track, EmptyAnimation, false); animationState.SetAnimation(track, EmptyAnimation, false);
else if (animationNames.Contains(name)) else if (AnimationNames.Contains(name))
animationState.SetAnimation(track, name, true); animationState.SetAnimation(track, name, true);
} }

View File

@@ -1,6 +1,8 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Frozen;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -86,11 +88,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject
} }
} }
foreach (var skin in skeletonData.Skins) var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List<string>() { EMPTY_ATTACHMENT });
skinNames.Add(skin.Name); foreach (var sk in skeletonData.Skins)
{
foreach (var anime in skeletonData.Animations) foreach (var (k, v) in sk.Attachments)
animationNames.Add(anime.Name); {
_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()) }; // 挂载一个空皮肤当作容器 skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData); animationStateData = new AnimationStateData(skeletonData);
@@ -196,7 +204,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
{ {
if (name == EMPTY_ANIMATION) if (name == EMPTY_ANIMATION)
animationState.SetAnimation(track, EmptyAnimation, false); animationState.SetAnimation(track, EmptyAnimation, false);
else if (animationNames.Contains(name)) else if (AnimationNames.Contains(name))
animationState.SetAnimation(track, name, true); animationState.SetAnimation(track, name, true);
} }

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Frozen;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -83,11 +85,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject
} }
} }
foreach (var skin in skeletonData.Skins) var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List<string>() { EMPTY_ATTACHMENT });
skinNames.Add(skin.Name); foreach (var sk in skeletonData.Skins)
{
foreach (var anime in skeletonData.Animations) foreach (var (k, v) in sk.Attachments)
animationNames.Add(anime.Name); {
_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()) }; // 挂载一个空皮肤当作容器 skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData); animationStateData = new AnimationStateData(skeletonData);
@@ -167,7 +175,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
{ {
if (name == EMPTY_ANIMATION) if (name == EMPTY_ANIMATION)
animationState.SetAnimation(track, EmptyAnimation, false); animationState.SetAnimation(track, EmptyAnimation, false);
else if (animationNames.Contains(name)) else if (AnimationNames.Contains(name))
animationState.SetAnimation(track, name, true); animationState.SetAnimation(track, name, true);
} }

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Frozen;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -90,11 +92,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject
} }
} }
foreach (var skin in skeletonData.Skins) var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List<string>() { EMPTY_ATTACHMENT });
skinNames.Add(skin.Name); foreach (var sk in skeletonData.Skins)
{
foreach (var anime in skeletonData.Animations) foreach (var (k, v) in sk.Attachments)
animationNames.Add(anime.Name); {
_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()) }; // 挂载一个空皮肤当作容器 skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData); animationStateData = new AnimationStateData(skeletonData);
@@ -172,7 +180,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
{ {
if (name == EMPTY_ANIMATION) if (name == EMPTY_ANIMATION)
animationState.SetAnimation(track, EmptyAnimation, false); animationState.SetAnimation(track, EmptyAnimation, false);
else if (animationNames.Contains(name)) else if (AnimationNames.Contains(name))
animationState.SetAnimation(track, name, true); animationState.SetAnimation(track, name, true);
} }

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Frozen;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -85,11 +87,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject
} }
} }
foreach (var skin in skeletonData.Skins) var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List<string>() { EMPTY_ATTACHMENT });
skinNames.Add(skin.Name); foreach (var sk in skeletonData.Skins)
{
foreach (var anime in skeletonData.Animations) foreach (var e in sk.Attachments)
animationNames.Add(anime.Name); {
_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()) }; // 挂载一个空皮肤当作容器 skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData); animationStateData = new AnimationStateData(skeletonData);
@@ -167,7 +175,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
{ {
if (name == EMPTY_ANIMATION) if (name == EMPTY_ANIMATION)
animationState.SetAnimation(track, EmptyAnimation, false); animationState.SetAnimation(track, EmptyAnimation, false);
else if (animationNames.Contains(name)) else if (AnimationNames.Contains(name))
animationState.SetAnimation(track, name, true); animationState.SetAnimation(track, name, true);
} }

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Frozen;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -85,11 +87,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject
} }
} }
foreach (var skin in skeletonData.Skins) var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List<string>() { EMPTY_ATTACHMENT });
skinNames.Add(skin.Name); foreach (var sk in skeletonData.Skins)
{
foreach (var anime in skeletonData.Animations) foreach (var e in sk.Attachments)
animationNames.Add(anime.Name); {
_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()) }; // 挂载一个空皮肤当作容器 skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData); animationStateData = new AnimationStateData(skeletonData);
@@ -167,7 +175,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
{ {
if (name == EMPTY_ANIMATION) if (name == EMPTY_ANIMATION)
animationState.SetAnimation(track, EmptyAnimation, false); animationState.SetAnimation(track, EmptyAnimation, false);
else if (animationNames.Contains(name)) else if (AnimationNames.Contains(name))
animationState.SetAnimation(track, name, true); animationState.SetAnimation(track, name, true);
} }

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Frozen;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -85,11 +87,17 @@ namespace SpineViewer.Spine.Implementations.SpineObject
} }
} }
foreach (var skin in skeletonData.Skins) var _slotAttachmentNames = skeletonData.Slots.ToDictionary(v => v.Name, v => new List<string>() { EMPTY_ATTACHMENT });
skinNames.Add(skin.Name); foreach (var sk in skeletonData.Skins)
{
foreach (var anime in skeletonData.Animations) foreach (var e in sk.Attachments)
animationNames.Add(anime.Name); {
_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()) }; // 挂载一个空皮肤当作容器 skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData); animationStateData = new AnimationStateData(skeletonData);
@@ -167,7 +175,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
{ {
if (name == EMPTY_ANIMATION) if (name == EMPTY_ANIMATION)
animationState.SetAnimation(track, EmptyAnimation, false); animationState.SetAnimation(track, EmptyAnimation, false);
else if (animationNames.Contains(name)) else if (AnimationNames.Contains(name))
animationState.SetAnimation(track, name, true); animationState.SetAnimation(track, name, true);
} }

View File

@@ -6,6 +6,8 @@ using NLog;
using System.Xml.Linq; using System.Xml.Linq;
using SpineViewer.Extensions; using SpineViewer.Extensions;
using SpineViewer.Utils; using SpineViewer.Utils;
using System.Collections.Immutable;
using System.Collections.Frozen;
namespace SpineViewer.Spine namespace SpineViewer.Spine
{ {
@@ -14,6 +16,11 @@ namespace SpineViewer.Spine
/// </summary> /// </summary>
public abstract class SpineObject : ImplementationResolver<SpineObject, SpineImplementationAttribute, SpineVersion>, SFML.Graphics.Drawable, IDisposable public abstract class SpineObject : ImplementationResolver<SpineObject, SpineImplementationAttribute, SpineVersion>, SFML.Graphics.Drawable, IDisposable
{ {
/// <summary>
/// 空附件标记
/// </summary>
protected const string EMPTY_ATTACHMENT = "<Empty>";
/// <summary> /// <summary>
/// 空动画标记 /// 空动画标记
/// </summary> /// </summary>
@@ -65,9 +72,6 @@ namespace SpineViewer.Spine
/// </summary> /// </summary>
private SpineObject PostInit() private SpineObject PostInit()
{ {
SkinNames = skinNames.AsReadOnly();
AnimationNames = animationNames.AsReadOnly();
// 必须 Update 一次否则包围盒还没有值 // 必须 Update 一次否则包围盒还没有值
update(0); update(0);
@@ -201,18 +205,6 @@ namespace SpineViewer.Spine
} }
protected abstract bool flipY { get; set; } protected abstract bool flipY { get; set; }
/// <summary>
/// 包含的所有皮肤名称
/// </summary>
public ReadOnlyCollection<string> SkinNames { get; private set; }
protected readonly List<string> skinNames = [];
/// <summary>
/// 包含的所有动画名称
/// </summary>
public ReadOnlyCollection<string> AnimationNames { get; private set; }
protected readonly List<string> animationNames = [EMPTY_ANIMATION];
/// <summary> /// <summary>
/// 是否被选中 /// 是否被选中
/// </summary> /// </summary>
@@ -333,6 +325,21 @@ namespace SpineViewer.Spine
} }
protected bool debugClippings = false; protected bool debugClippings = false;
/// <summary>
/// 所有槽位下可用的附件名
/// </summary>
public FrozenDictionary<string, ImmutableArray<string>> SlotAttachmentNames { get; protected set; }
/// <summary>
/// 包含的所有皮肤名称 (不含 default 默认皮肤)
/// </summary>
public ImmutableArray<string> SkinNames { get; protected set; }
/// <summary>
/// 包含的所有动画名称
/// </summary>
public ImmutableArray<string> AnimationNames { get; protected set; }
/// <summary> /// <summary>
/// 获取已加载的皮肤列表快照, 允许出现重复值 /// 获取已加载的皮肤列表快照, 允许出现重复值
/// </summary> /// </summary>
@@ -344,7 +351,7 @@ namespace SpineViewer.Spine
/// </summary> /// </summary>
public void LoadSkin(string name) public void LoadSkin(string name)
{ {
if (!skinNames.Contains(name)) return; if (!SkinNames.Contains(name)) return;
lock (_lock) lock (_lock)
{ {
loadedSkins.Add(name); loadedSkins.Add(name);
@@ -372,7 +379,7 @@ namespace SpineViewer.Spine
{ {
lock (_lock) 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; loadedSkins[idx] = name;
reloadSkins(); reloadSkins();
} }
@@ -576,4 +583,4 @@ namespace SpineViewer.Spine
#endregion #endregion
} }
} }