diff --git a/SpineViewer/Controls/SpineViewPropertyGrid.Designer.cs b/SpineViewer/Controls/SpineViewPropertyGrid.Designer.cs
index 6c45a72..8074406 100644
--- a/SpineViewer/Controls/SpineViewPropertyGrid.Designer.cs
+++ b/SpineViewer/Controls/SpineViewPropertyGrid.Designer.cs
@@ -40,6 +40,8 @@
propertyGrid_Skin = new PropertyGrid();
contextMenuStrip_Skin = new ContextMenuStrip(components);
toolStripMenuItem_ReloadSkins = new ToolStripMenuItem();
+ tabPage_Slot = new TabPage();
+ propertyGrid_Slot = new PropertyGrid();
tabPage_Animation = new TabPage();
propertyGrid_Animation = new PropertyGrid();
contextMenuStrip_Animation = new ContextMenuStrip(components);
@@ -53,6 +55,7 @@
tabPage_Transform.SuspendLayout();
tabPage_Skin.SuspendLayout();
contextMenuStrip_Skin.SuspendLayout();
+ tabPage_Slot.SuspendLayout();
tabPage_Animation.SuspendLayout();
contextMenuStrip_Animation.SuspendLayout();
tabPage_Debug.SuspendLayout();
@@ -65,6 +68,7 @@
tabControl.Controls.Add(tabPage_Render);
tabControl.Controls.Add(tabPage_Transform);
tabControl.Controls.Add(tabPage_Skin);
+ tabControl.Controls.Add(tabPage_Slot);
tabControl.Controls.Add(tabPage_Animation);
tabControl.Controls.Add(tabPage_Debug);
tabControl.Dock = DockStyle.Fill;
@@ -181,6 +185,28 @@
toolStripMenuItem_ReloadSkins.Text = "重新加载所选皮肤";
toolStripMenuItem_ReloadSkins.Click += toolStripMenuItem_ReloadSkins_Click;
//
+ // tabPage_Slot
+ //
+ tabPage_Slot.BackColor = SystemColors.Control;
+ tabPage_Slot.Controls.Add(propertyGrid_Slot);
+ tabPage_Slot.Location = new Point(4, 4);
+ tabPage_Slot.Margin = new Padding(0);
+ tabPage_Slot.Name = "tabPage_Slot";
+ tabPage_Slot.Size = new Size(364, 370);
+ tabPage_Slot.TabIndex = 6;
+ tabPage_Slot.Text = "槽位";
+ //
+ // propertyGrid_Slot
+ //
+ propertyGrid_Slot.Dock = DockStyle.Fill;
+ propertyGrid_Slot.HelpVisible = false;
+ propertyGrid_Slot.Location = new Point(0, 0);
+ propertyGrid_Slot.Name = "propertyGrid_Slot";
+ propertyGrid_Slot.PropertySort = PropertySort.Alphabetical;
+ propertyGrid_Slot.Size = new Size(364, 370);
+ propertyGrid_Slot.TabIndex = 2;
+ propertyGrid_Slot.ToolbarVisible = false;
+ //
// tabPage_Animation
//
tabPage_Animation.BackColor = SystemColors.Control;
@@ -260,6 +286,7 @@
tabPage_Transform.ResumeLayout(false);
tabPage_Skin.ResumeLayout(false);
contextMenuStrip_Skin.ResumeLayout(false);
+ tabPage_Slot.ResumeLayout(false);
tabPage_Animation.ResumeLayout(false);
contextMenuStrip_Animation.ResumeLayout(false);
tabPage_Debug.ResumeLayout(false);
@@ -286,5 +313,7 @@
private ToolStripMenuItem toolStripMenuItem_RemoveAnimation;
private TabPage tabPage_Debug;
private PropertyGrid propertyGrid_Debug;
+ private TabPage tabPage_Slot;
+ private PropertyGrid propertyGrid_Slot;
}
}
diff --git a/SpineViewer/Controls/SpineViewPropertyGrid.cs b/SpineViewer/Controls/SpineViewPropertyGrid.cs
index 85ddec4..1ea47bf 100644
--- a/SpineViewer/Controls/SpineViewPropertyGrid.cs
+++ b/SpineViewer/Controls/SpineViewPropertyGrid.cs
@@ -34,6 +34,7 @@ namespace SpineViewer.Controls
propertyGrid_Render.SelectedObject = null;
propertyGrid_Transform.SelectedObject = null;
propertyGrid_Skin.SelectedObject = null;
+ propertyGrid_Slot.SelectedObject = null;
propertyGrid_Animation.SelectedObject = null;
propertyGrid_Debug.SelectedObject = null;
}
@@ -44,6 +45,7 @@ namespace SpineViewer.Controls
propertyGrid_Render.SelectedObjects = value.Select(e => e.Render).ToArray();
propertyGrid_Transform.SelectedObjects = value.Select(e => e.Transform).ToArray();
propertyGrid_Skin.SelectedObjects = value.Select(e => e.Skin).ToArray();
+ propertyGrid_Slot.SelectedObjects = value.Select(e => e.Slot).ToArray();
propertyGrid_Animation.SelectedObjects = value.Select(e => e.Animation).ToArray();
propertyGrid_Debug.SelectedObjects = value.Select(e => e.Debug).ToArray();
}
diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs
index e700783..adaceed 100644
--- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs
+++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject21.cs
@@ -106,7 +106,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
}
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();
+ AnimationNames = [EMPTY_ANIMATION, .. skeletonData.Animations.Select(v => v.Name)];
skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData);
@@ -187,7 +187,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
set => skeleton.FlipY = value;
}
- protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT;
+ protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment?.Name ?? EMPTY_ATTACHMENT;
protected override void setSlotAttachment(string slot, string name)
{
diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs
index 4277aeb..bcbdc37 100644
--- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs
+++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject36.cs
@@ -105,7 +105,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
}
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();
+ AnimationNames = [EMPTY_ANIMATION, .. skeletonData.Animations.Select(v => v.Name)];
skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData);
@@ -186,7 +186,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
set => skeleton.FlipY = value;
}
- protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT;
+ protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment?.Name ?? EMPTY_ATTACHMENT;
protected override void setSlotAttachment(string slot, string name)
{
diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs
index 5efcb26..d7e6dbf 100644
--- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs
+++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject37.cs
@@ -102,7 +102,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
}
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();
+ AnimationNames = [EMPTY_ANIMATION, .. skeletonData.Animations.Select(v => v.Name)];
skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData);
@@ -157,7 +157,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
}
}
- protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT;
+ protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment?.Name ?? EMPTY_ATTACHMENT;
protected override void setSlotAttachment(string slot, string name)
{
diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs
index 2153dbd..7bdd895 100644
--- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs
+++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject38.cs
@@ -109,7 +109,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
}
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();
+ AnimationNames = [EMPTY_ANIMATION, .. skeletonData.Animations.Select(v => v.Name)];
skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData);
@@ -164,7 +164,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
}
}
- protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT;
+ protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment?.Name ?? EMPTY_ATTACHMENT;
protected override void setSlotAttachment(string slot, string name)
{
diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs
index b869411..740ca99 100644
--- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs
+++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject40.cs
@@ -105,7 +105,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
}
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();
+ AnimationNames = [EMPTY_ANIMATION, .. skeletonData.Animations.Select(v => v.Name)];
skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData);
@@ -160,7 +160,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
}
}
- protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT;
+ protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment?.Name ?? EMPTY_ATTACHMENT;
protected override void setSlotAttachment(string slot, string name)
{
diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs
index 8ca2136..ff10359 100644
--- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs
+++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject41.cs
@@ -105,7 +105,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
}
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();
+ AnimationNames = [EMPTY_ANIMATION, .. skeletonData.Animations.Select(v => v.Name)];
skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData);
@@ -160,7 +160,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
}
}
- protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT;
+ protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment?.Name ?? EMPTY_ATTACHMENT;
protected override void setSlotAttachment(string slot, string name)
{
diff --git a/SpineViewer/Spine/Implementations/SpineObject/SpineObject42.cs b/SpineViewer/Spine/Implementations/SpineObject/SpineObject42.cs
index fa84fad..06f3e7a 100644
--- a/SpineViewer/Spine/Implementations/SpineObject/SpineObject42.cs
+++ b/SpineViewer/Spine/Implementations/SpineObject/SpineObject42.cs
@@ -105,7 +105,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
}
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();
+ AnimationNames = [EMPTY_ANIMATION, .. skeletonData.Animations.Select(v => v.Name)];
skeleton = new Skeleton(skeletonData) { Skin = new(Guid.NewGuid().ToString()) }; // 挂载一个空皮肤当作容器
animationStateData = new AnimationStateData(skeletonData);
@@ -160,7 +160,7 @@ namespace SpineViewer.Spine.Implementations.SpineObject
}
}
- protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment.Name ?? EMPTY_ATTACHMENT;
+ protected override string getSlotAttachment(string slot) => skeleton.FindSlot(slot)?.Attachment?.Name ?? EMPTY_ATTACHMENT;
protected override void setSlotAttachment(string slot, string name)
{
diff --git a/SpineViewer/Spine/SpineView/SpineObjectProperty.cs b/SpineViewer/Spine/SpineView/SpineObjectProperty.cs
index 9ffae04..767985a 100644
--- a/SpineViewer/Spine/SpineView/SpineObjectProperty.cs
+++ b/SpineViewer/Spine/SpineView/SpineObjectProperty.cs
@@ -27,6 +27,10 @@ namespace SpineViewer.Spine.SpineView
[DisplayName("皮肤")]
public SpineSkinProperty Skin { get; } = new(spine);
+ [TypeConverter(typeof(ExpandableObjectConverter))]
+ [DisplayName("皮肤")]
+ public SpineSlotProperty Slot { get; } = new(spine);
+
[TypeConverter(typeof(ExpandableObjectConverter))]
[DisplayName("动画")]
public SpineAnimationProperty Animation { get; } = new(spine);
diff --git a/SpineViewer/Spine/SpineView/SpineSlotProperty.cs b/SpineViewer/Spine/SpineView/SpineSlotProperty.cs
new file mode 100644
index 0000000..5e4f29a
--- /dev/null
+++ b/SpineViewer/Spine/SpineView/SpineSlotProperty.cs
@@ -0,0 +1,177 @@
+using SpineViewer.Spine;
+using SpineViewer.Utils;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SpineViewer.Spine.SpineView
+{
+ ///
+ /// 用于在 PropertyGrid 上显示槽位附件加载情况包装类
+ ///
+ public class SpineSlotProperty(SpineObject spine) : ICustomTypeDescriptor
+ {
+ [Browsable(false)]
+ public SpineObject Spine { get; } = spine;
+
+ ///
+ /// 显示所有槽位集合
+ ///
+ public override string ToString() => $"[{string.Join(", ", Spine.SlotAttachmentNames.Keys)}]";
+
+ public override bool Equals(object? obj)
+ {
+ if (obj is SpineAnimationProperty prop) return ToString() == prop.ToString();
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode() => HashCode.Combine(typeof(SpineAnimationProperty).FullName.GetHashCode(), ToString().GetHashCode());
+
+ #region ICustomTypeDescriptor 接口实现
+
+ // XXX: 必须实现 ICustomTypeDescriptor 接口, 不能继承 CustomTypeDescriptor, 似乎继承下来的东西会有问题, 导致某些调用不正确
+
+ ///
+ /// 属性描述符缓存
+ ///
+ private static readonly Dictionary pdCache = [];
+
+ public AttributeCollection GetAttributes() => TypeDescriptor.GetAttributes(this, true);
+ public string? GetClassName() => TypeDescriptor.GetClassName(this, true);
+ public string? GetComponentName() => TypeDescriptor.GetComponentName(this, true);
+ public TypeConverter? GetConverter() => TypeDescriptor.GetConverter(this, true);
+ public EventDescriptor? GetDefaultEvent() => TypeDescriptor.GetDefaultEvent(this, true);
+ public PropertyDescriptor? GetDefaultProperty() => TypeDescriptor.GetDefaultProperty(this, true);
+ public object? GetEditor(Type editorBaseType) => TypeDescriptor.GetEditor(this, editorBaseType, true);
+ public EventDescriptorCollection GetEvents() => TypeDescriptor.GetEvents(this, true);
+ public EventDescriptorCollection GetEvents(Attribute[]? attributes) => TypeDescriptor.GetEvents(this, attributes, true);
+ public object? GetPropertyOwner(PropertyDescriptor? pd) => this;
+ public PropertyDescriptorCollection GetProperties() => GetProperties(null);
+ public PropertyDescriptorCollection GetProperties(Attribute[]? attributes)
+ {
+ var props = new PropertyDescriptorCollection(TypeDescriptor.GetProperties(this, attributes, true).Cast().ToArray());
+ foreach (var slotName in Spine.SlotAttachmentNames.Keys)
+ {
+ if (!pdCache.TryGetValue(slotName, out var pd))
+ pdCache[slotName] = pd =new SlotPropertyDescriptor(slotName, [new DisplayNameAttribute($"{slotName}")]);
+ props.Add(pd);
+ }
+ return props;
+ }
+
+ ///
+ /// 槽位属性描述符, 实现对属性的读取和赋值
+ ///
+ internal class SlotPropertyDescriptor(string name, Attribute[]? attributes) : PropertyDescriptor($"Slot_{name}", attributes)
+ {
+ public string SlotName { get; } = name;
+
+ public override Type ComponentType => typeof(SpineSlotProperty);
+ public override bool IsReadOnly => false;
+ public override Type PropertyType => typeof(SlotProperty);
+ public override bool CanResetValue(object component) => false;
+ public override void ResetValue(object component) { }
+ public override bool ShouldSerializeValue(object component) => false;
+
+ ///
+ /// 得到一个轨道包装类, 允许用户查看或者修改具体的属性值, 这个地方决定了在面板上看到的是一个对象及其属性
+ ///
+ public override object? GetValue(object? component)
+ {
+ if (component is SpineSlotProperty slots)
+ return slots.Spine.GetSlotAttachment(SlotName);
+ return null;
+ }
+
+ ///
+ /// 允许通过字符串赋值修改该轨道的动画, 这里决定了当其他地方的调用 (比如 Converter) 通过 value 来设置属性值的时候应该怎么处理
+ ///
+ public override void SetValue(object? component, object? value)
+ {
+ if (component is SpineSlotProperty slots)
+ {
+ if (value is string s)
+ slots.Spine.SetSlotAttachment(SlotName, s);
+ }
+ }
+ }
+
+ #endregion
+ }
+
+ ///
+ /// 对 .Slot_{name} 属性的包装类
+ ///
+ [TypeConverter(typeof(SlotPropertyConverter))]
+ public class SlotProperty(SpineObject spine, string name)
+ {
+ private readonly SpineObject spine = spine;
+
+ [Browsable(false)]
+ public string Name { get; } = name;
+
+ ///
+ /// 实现了默认的转为字符串的方式
+ ///
+ public override string ToString() => spine.GetSlotAttachment(Name);
+
+ ///
+ /// 影响了属性面板的判断, 当动画名称相同的时候认为两个对象是相同的, 这样属性面板可以在多选的时候正确显示相同取值的内容
+ ///
+ public override bool Equals(object? obj)
+ {
+ if (obj is SlotProperty) return ToString() == obj.ToString();
+ return base.Equals(obj);
+ }
+
+ ///
+ /// 哈希码需要和 Equals 行为类似
+ ///
+ public override int GetHashCode() => HashCode.Combine(typeof(SlotProperty).FullName.GetHashCode(), ToString().GetHashCode());
+ }
+
+ ///
+ /// 轨道索引包装类转换器, 实现字符串和包装类的互相转换, 并且提供标准值列表对属性进行设置, 同时还提供在面板上显示包装类属性的能力
+ ///
+ public class SlotPropertyConverter : StringConverter
+ {
+ // NOTE: 可以不用实现 ConvertTo/ConvertFrom, 因为属性实现了与字符串之间的互转
+ // ToString 实现了 ConvertTo
+ // SetValue 实现了从字符串设置属性
+
+ public override bool GetStandardValuesSupported(ITypeDescriptorContext? context) => true;
+
+ public override bool GetStandardValuesExclusive(ITypeDescriptorContext? context) => true;
+
+ public override StandardValuesCollection? GetStandardValues(ITypeDescriptorContext? context)
+ {
+ if (context?.PropertyDescriptor is SpineSlotProperty.SlotPropertyDescriptor pd)
+ {
+ if (context?.Instance is SpineSlotProperty slots)
+ {
+ if (slots.Spine.SlotAttachmentNames.TryGetValue(pd.SlotName, out var names))
+ return new StandardValuesCollection(names);
+ }
+ else if (context?.Instance is object[] instances && instances.All(x => x is SpineSlotProperty))
+ {
+ // XXX: 这里不知道为啥总是会得到 object[] 类型而不是具体的类型
+ var spinesSlots = instances.Cast().ToArray();
+ if (spinesSlots.Length > 0)
+ {
+ IEnumerable common = [];
+ foreach (var t in spinesSlots)
+ {
+ if (t.Spine.SlotAttachmentNames.TryGetValue(pd.SlotName, out var names))
+ common = common.Union(names);
+ }
+ return new StandardValuesCollection(common.ToArray());
+ }
+ }
+ }
+ return base.GetStandardValues(context);
+ }
+ }
+}