• Runtimes
  • [cocos2d-x] How to delete attachments from a skin

Related Discussions
...

Hi,

Once a custom skin is created at run-time, there is no way to delete attachments that were added to it. Within the Skin class I can see an internal class named AttachmentMap, which has a "remove()" method, but it doesn't seem to be used anywhere, with no references to it from the Skin class.

I added a new method to the Skin class in my local code, as follows:

void Skin::removeAttachment(size_t slotIndex, const String& name) {
    _attachments.remove(slotIndex, name);
}

Now, this works for me, but is there a reason that this was never provided in the API? Does it have any side effects that you are aware of?

Also, from searching this forum, I read comments regarding calling this method to clear an attachment, but it didn't work:

void Skeleton::setAttachment(const String &slotName, const String &attachmentName)

Calling it like this didn't remove the attachment, even though internally I can see it sets the slot attachment to null on the skeleton:

skeleton->setAttachment("SlotID", "");

Is Skeleton::setAttachment(SlotId, "") supposed to delete the attachment from the currently assigned skin too?

There aren't any side effects apart from the renderer not finding an attachment needed for a specific slot. However, the reason we don't have removeAttachment is because Skin::setAttachment(slotIndex, name, NULL) is equivalent to what you are doing in terms of semantics.

I'm curious, how were you able to call Skin::setAttachment() without the third parameter?

badlogic a écrit

However, the reason we don't have removeAttachment is because Skin::setAttachment(slotIndex, name, NULL) is equivalent to what you are doing in terms of semantics.
I'm curious, how were you able to call Skin::setAttachment() without the third parameter?

I never mentioned anything regarding Skin::setAttachment(), since it doesn't actually exist in the v3.7 C++ runtime, so I'm not sure what you're referring to.

The C++ 3.7 run-time has these:

void Slot::setAttachment(Attachment *inValue);

void Skeleton::setAttachment(const String &slotName, const String &attachmentName);

I'm using the current stable version of Spine (3.7.xx), and the v3.7 run-time to match.

I'm really sorry, I mistook "Skeleton::" for "Skin::".

Slot::setAttachment() will only set the attachment on the slot, and not modify any skin set on the skeleton. This is likely not what you want.

The Skeleton::setAttachment() method is meant for setting an attachment that's contained in the currently active skin.

If you want to remove an attachment from a skin, you have to do so on the skin itself. You can get the currently active skin like this:

Skin* skin = skeleton->getSkin();
skin->addAttachment(slotIndex, name, NULL);
badlogic a écrit

If you want to remove an attachment from a skin, you have to do so on the skin itself. You can get the currently active skin like this:

Skin* skin = skeleton->getSkin();
skin->addAttachment(slotIndex, name, NULL);

That's the first thing I tried, but it doesn't work, because it will assert on a null attachment, as you can see from the implementation:

void Skin::addAttachment(size_t slotIndex, const String &name, Attachment *attachment) {
   assert(attachment);
   _attachments.put(slotIndex, name, attachment);
}

That's the reason for this entire thread, since I literally tried whatever I could see in the API before coming here to ask about it, and nothing worked.

So, any other ideas I could try, or should I just stick with the Skin::removeAttachment() function that I added to my own code (it seems to be working fine so far)?

Ah, you are correct. Sorry, I overlooked that. I've added Skin::removeAttachment to both the 3.7 and the 3.8-beta branch. Note that in 3.7, removing the attachment from the skin will not free the memory associated with the attachment. You'll have to explicitely delete it if you no longer need it. In the 3.8-beta branch we use reference counting. If no other Skin is referencing the attachment, it will be automatically deleted.

That is good news, and thank you for the info!