Ah. Attachments are stored at the SkeletonData level and shared across all instances. This is so that if you have multiple of that skeleton, it doesn't need to instantiate all the data that doesn't need to be unique anyway.
For VertexAttachments, deformations are temporarily stored in slot.AttachmentVertices
which is at the skeleton level (unique to each Skeleton instance). I forget how its contents are encoded. I'll get back to you on that.
edit: For non-weighted meshes, slot.AttachmentVertices is encoded similar to the vertices on the MeshAttachment itself. Just ensure that its size is exactly the same size as the vertex array of the MeshAttachment. AttachmentVertices is an ExposedList<float> so you have to get its .Items
to get to the float[]
.
// For non-weighted meshes.
int verticesLength = meshAttachment.worldVerticesLength;
var slotVertices = slot.AttachmentVertices;
if (slotVertices.Capacity < verticesLength) slotVertices.Capacity = verticesLength;
slotVertices.Count = verticesLength;
floar[] vertices = slotVertices.Items;
//... loop
vertices[i*2] = x;
But in all other cases, you would probably have to clone both the (default) skin of that skeleton, and clone the attachment you are trying to modify so both can exist per skeleton.
If you are using Unity, there are cloning extension methods you can access through using Spine.Unity.Modules.AttachmentTools
. Not sure yet if the cloning methods on the base runtime will make it into 3.7 release. A lot of this API is part of a "skins and attachments" improvement we have planned. Spine-Unity is currently the only runtime that has something that can be used in the meantime.
In Unity, the code would look like this:
void CloneSkinCloneAttachmentExample (Spine.Unity.SkeletonAnimation skeletonAnimation) {
var skeleton = skeletonAnimation.Skeleton;
Spine.Skin defaultSkin = skeleton.Data.DefaultSkin;
Spine.Skin activeSkin = skeleton.Skin;
// Clone skin. Combine both default skin and active skin.
var newSkin = defaultSkin.GetClone();
activeSkin.CopyTo(newSkin, true, false, false);
// Find, clone and reassign the target attachment.
int slotIndex = skeleton.FindSlotIndex("slot name");
string keyName = "attachment name";
Spine.Attachment attachmentToClone = newSkin.GetAttachment(slotIndex, keyName);
Spine.Attachment clonedAttachment = attachmentToClone.GetClone(cloneMeshesAsLinked: false);
newSkin.SetAttachment(slotIndex, keyName, clonedAttachment);
// Assign skin
skeleton.Skin = newSkin;
// At this point, clonedAttachment can now be modified
// and not affect other Skeleton instances
}
Here's a test skeleton with a single MeshAttachment with verts arranged in a 3x3 grid. The slot and attachment name is "__whitesquare"
: