• Runtimes
  • [tk2d] Creating skin programmatically

Related Discussions
...

Im talking about rjohnn posts. I have the same problem when I added the MeshAttachments code lines

               if (att is Spine.MeshAttachment)
               {
                                    Spine.Attachment newMeshAtt = spriteCollectionAttachmentLoader.NewMeshAttachment(newSkin,spriteImageName,spriteImageName);

              Spine.MeshAttachment NewMatt = newMeshAtt as Spine.MeshAttachment;
              Spine.MeshAttachment oldMatt = att as Spine.MeshAttachment;

              NewMatt.vertices = oldMatt.vertices;
              NewMatt.UVs = oldMatt.UVs;
              NewMatt.regionUVs = oldMatt.regionUVs;
              NewMatt.Triangles = oldMatt.Triangles;


              newSkin.AddAttachment(slotIndex, attName, NewMatt);
           }

newSkin is the empty new skin created, As you see, what I'm doing is adding the attachments to the new skin. If I don't copy the NewMatt properties from the oldMatt the attachments are not visible. I don't know why but It works.

So how do I have access to the timelines and copy them to the new skin?

Replace all of that with:

newSkin.AddAttachment(slotIndex, attName, att);

Thank you Nate it works!!

Also one more thing, maybe I need to open a new thread.

TK2D now have 2 options to save the atlas format: Unity texture, and png.

The png format doesn't work. Unity shows empty sprites.

Glad it works in a much simpler way. 🙂

I committed a fix, discussed here:
viewtopic.php?p=10899#p10899
I found def.material == def.materialInst when using "Unity texture" but not when using PNG, so I'm hoping it's ok to use all the time.

5ヶ月 後

Hello!
I need to create skin programmatically.
My platform is Cocos2d 2.0.
I can't find any method like addSkin() in SkeletonData.h like above.
Is there any to do like that?

Thank you.

1年 後

If anyone like me got here looking for a way to put TextureRegion inside Spine animation programmatically (by replacing one of attachments) here's your answer in LibGDX:

/**
 * SpineUtils.putRegionIntoSpineSkin() allows to programmatically put LibGDX TextureRegion into Spine animation slot by replacing existing attachment in cloned spine skin. This way you don't have to change SkeletonData so you can use it for multiple spine animations with LibGDX AssetManager.
 *
 * @author Lukasz Zmudziak, @"lukz_dev"#4132 on 2016-01-11.
 */
public class SpineUtils {

    public static Skin cloneSkin(Skeleton skeleton, Skin oldSkin, String newName) {
        Skin newSkin = new Skin(newName);

Array<Attachment> slotAttachments = new Array<Attachment>();
Array<String> attachmentNames = new Array<String>();

// Loop through every slot
for(Slot slot : skeleton.getSlots()) {

    // Get the slot index
    int slotIndex = skeleton.findSlotIndex(slot.getData().getName());

    // Get attachments and names from this slot
    oldSkin.findAttachmentsForSlot(slotIndex, slotAttachments);
    oldSkin.findNamesForSlot(slotIndex, attachmentNames);

    // For each attachment in this slot, copy it to new skin
    for(int i = 0; i < slotAttachments.size; i++) {
        newSkin.addAttachment(slotIndex, attachmentNames.get(i), slotAttachments.get(i));
    }

    // Clear arrays
    slotAttachments.clear();
    attachmentNames.clear();
}

return newSkin;
    }

/**
 * Makes a copy of default skin and replace attachment with the new one
 * @param spineAnim
 * @param region
 * @param slot name of slot that contains replaced attachment
 */
public static void putRegionIntoSpineSkin(SpineAnimationComponent spineAnim, TextureRegion region, String slot) {
    // Get old attachment
    RegionAttachment oldAttach = (RegionAttachment)spineAnim.skeleton.findSlot(slot).getAttachment();

    // Prepare new attachment
    RegionAttachment newAttach = new RegionAttachment("Attachment");
    newAttach.setRegion(region);
    newAttach.setWidth(region.getRegionWidth());
    newAttach.setHeight(region.getRegionHeight());
    newAttach.setScaleX(Assets.ASSET_RESOLUTION_SCALE); // This is specific for my code
    newAttach.setScaleY(Assets.ASSET_RESOLUTION_SCALE); // This is specific for my code
    newAttach.setRotation(oldAttach.getRotation());
    newAttach.getColor().set(oldAttach.getColor());
    newAttach.setX(oldAttach.getX());
    newAttach.setY(oldAttach.getY());
    newAttach.updateOffset();

    // Find proper slot
    int slotIndex = spineAnim.skeleton.findSlotIndex(slot);

    // Prepare new skin and replace attachment with the new one
    Skin skin = SpineUtils.cloneSkin(spineAnim.skeleton, spineAnim.skeleton.getData().getDefaultSkin(), "Custom");
    skin.addAttachment(slotIndex, oldAttach.getName(), newAttach);

    // Set up new skin
    spineAnim.skeleton.setSkin(skin);
    spineAnim.skeleton.setSlotsToSetupPose();
}
}
2年 後
rjohnn wrote

if(att is Spine.MeshAttachment)
{
Spine.Attachment newMeshAtt = spriteCollectionAttachmentLoader.NewMeshAttachment(newSkin,spriteImageName,spriteImageName);

              Spine.MeshAttachment NewMatt = newMeshAtt as Spine.MeshAttachment;
              Spine.MeshAttachment oldMatt = att as Spine.MeshAttachment;

              NewMatt.vertices = oldMatt.vertices;
              NewMatt.UVs = oldMatt.UVs;
              NewMatt.regionUVs = oldMatt.regionUVs;
              NewMatt.Triangles = oldMatt.Triangles;
              

              newSkin.AddAttachment(slotIndex, attName, NewMatt);

}

I've trying to get Spine Skin cloning working in order to easily switch out materials on spine objects. The post by rjohnn for cloning RegionAttachments works great. However, I'm finding Copying the MeshAttachment doesn't work. Not sure what the issue is, the code seems correct. Unity gives me this:

Failed setting triangles. Some indices are referencing out of bounds vertices. IndexCount: 198, VertexCount: 24
UnityEngine.Mesh:SetTriangles(Int32[], Int32)
Spine.Unity.MeshGeneration.ArraysSubmeshSetMeshGenerator:GenerateMesh(ExposedList1, Int32, Int32) (at Assets/Libraries/lib_unity_SlotsClient/Assets/Scripts/Slots/Spine/spine-unity/Mesh Generation/Arrays/ArraysSubmeshSetMeshGenerator.cs:134)
Spine.Unity.Modules.SkeletonPartsRenderer:RenderParts(ExposedList
1, Int32, Int32) (at Assets/Libraries/lib_unity_SlotsClient/Assets/Scripts/Slots/Spine/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs:78)
Spine.Unity.Modules.SkeletonRenderSeparator:HandleRender(Instruction) (at Assets/Libraries/lib_unity_SlotsClient/Assets/Scripts/Slots/Spine/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs:155)
Spine.Unity.SkeletonRenderer:LateUpdateInternal() (at Assets/Libraries/lib_unity_SlotsClient/Assets/Scripts/Slots/Spine/spine-unity/SkeletonRenderer.cs:464)
Spine.Unity.SkeletonRenderer:LateUpdate() (at Assets/Libraries/lib_unity_SlotsClient/Assets/Scripts/Slots/Spine/spine-unity/SkeletonRenderer.cs:269)

I've been trying to trace this back but can't find a solution so far, maybe someone out there knows the answer.

Nate wrote

Replace all of that with:
newSkin.AddAttachment(slotIndex, attName, att);

Seems incorrect, when I do this it only adds the existing attachments without my material applied. Am I missing something here?

Thanks much,

Jason

I think you may have read advice/copied code from much older versions of the Spine runtime.

Spine-Unity now comes with some extension methods for easy cloning of attachments. They may become part of the core runtime in the future.

Make sure you add the using for it.

using Spine.Unity.Modules.AttachmentTools;

and to get a clone of an attachment, you just call:

var clonedAttachment = myAttachment.GetClone(true); // true param means mesh attachments will be cloned as linked meshes so they will obey Deform animations from the source attachments.

You can find the code here: spine-runtimes/AttachmentTools.cs at 3.6

Great thanks Pharan! extremely helpful.

-Jason