I'm just going to get some facts down related to this:
(1) A Skin is a Map/Hashmap/Dictionary of names and attachments.
This means a Skin has a bunch of key-value pairs {attachment name, attachment object}
(More specifically, it's a {{slot index, attachment name}, attachment object}).
The runtimes use this by passing the Skin a string name and a slot id and getting the attachment object in return.
(2) In Spine Editor, you can put a bunch of "skin placeholders" under slots. These correspond to the "attachment name" key inside Skins.
When you add attachments under skin placeholders in a Skin, each will get exported as an entry in their corresponding Skin's Map/Dictionary.
(3) For different Skins in the editor, you can leave some skin placeholders empty.
On export, skin placeholders without attachments are excluded from the Skin's map.
(3.1) If all placeholders are empty, the resulting Skin would also be an empty Map/Dictionary. But empty skins are also not exported.
(4) You can change skins by calling Skeleton.setSkin.
It will not only change what data source the skeleton will pull from to know what attachments to use.
It will also attempt to apply the attachments stored in the skin immediately.
The current Java implementation is as follows (you can find this in Skeleton.java
):
public void setSkin (Skin newSkin) {
if (newSkin != null) {
if (skin != null)
newSkin.attachAll(this, skin);
else {
Array<Slot> slots = this.slots;
for (int i = 0, n = slots.size; i < n; i++) {
Slot slot = slots.get(i);
String name = slot.data.attachmentName;
if (name != null) {
Attachment attachment = newSkin.getAttachment(i, name);
if (attachment != null) slot.setAttachment(attachment);
}
}
}
}
skin = newSkin;
}
String name = slot.data.attachmentName;
means that it uses setup pose data, not the current state (slot.attachment?.name
), to determine what to attach.
Combined with the above, if (name != null)
means it will not change slots that were empty in setup pose.
Attachment attachment = newSkin.getAttachment(i, name);
asks the Skin object for an attachment. It may return null, meaning the entry was not there (because empty skin placeholders are not added to the Map/Dictionary).
if (attachment != null) slot.setAttachment(attachment);
means attachments are only changed if the entry existed in the skin.
(4.1)
Those key lines are where you could change the logic to get the desired behavior.
For example:
If you want nulling behavior, the if (attachment != null)
conditional can be removed. slot.setAttachment
will accept a null parameter.
If you want slots that were empty at setup pose to get set to null, you can add an else clause that runs slot.setAttachment(null);
. This will however have an effect of nulling slots that were either animated to change or changed programmatically.
If you want to use current state instead of setup pose, you can change:
String name = slot.data.attachmentName;
to
Attachment currentAttachment = slot.attachment;
String name = null;
if (currentAttachment != null) {
name = currentAttachment.getName();
}
(4.2)
Using Skeleton.setSlotsToSetupPose
is also an option that uses Setup Pose data and can also null out slots that were animated or changed programmatically. Using it should be fine if your animation system isn't too complicated.