Poundmax

Changing textures/skin in Pixi Spine

Recommended Posts

Hi all,

I'm working on an avatarbuilder and would like to use Spine for the animations. The avatar is made up of several parts (head, body, arms etc) that can be changed in order to get the desired combination. Now, I've been looking at using skins, but I'm not sure if I'm going the right direction. Since it's not a complete skin that needs to be swapped, but just a part of it.

The avatarbuilder will be made in Haxe using Pixi and Spine.

My main questions are:

1) Would it be possible to use skins in order to only change the head, or the body for instance?

2) Am I moving in the right direction using the skin feature of Spine?

 

Thanks in advance!

Maarten

Share this post


Link to post
Share on other sites

Either you do it with skins, either you use features that are pixi-specific. Basically, you can change texture of any sprite inside Spine object, and PIXI will work with it just fine. That's one of latest features, we couldn't do that before! Also, other spine runtimes (libgdx and other) can't do that.

https://github.com/pixijs/pixi-spine/issues/91

https://github.com/pixijs/pixi-spine/issues/92

 

Share this post


Link to post
Share on other sites

Hi Ivan,

Thanks for your reply. Was a lot faster than mine (sorry about that :)). 

I've managed to change the textures referencing the sprites in animation.slotContainer (like in animation.slotContainer[0].children[0], that I cast to Sprite). That worked like a charm, until we started using meshes. I could not cast the object to Sprite anymore (in order to change the texture) because of the extra fields of the mesh (like uvs, vertices etc).

I've also searched for the 'currentSprite' field, but could not find it in any of the slotContainers, since it's an Array of Pixi Containers.

Is there another way to locate the sprite of an Spine slot that uses meshing (and those that don't as well) ?

I fear it's something very easy that I'm overlooking :).

 

Thanks in advance!

Maarten

Share this post


Link to post
Share on other sites

Yes, its not that easy for meshes :) 

I'm doing it for the first time, so ther might be errors. I did not test that code.

//let 'spine' be Spine object
var spine = new PIXI.spine.Spine(loader.resources['spineBoy'].data);
//let 'num' be the number of the slot with mesh. 
var num = spine.skeleton.findSlotIndex('meshSlot');
//let myTexture be the texture you are assigning. it can be something from the spritesheet
var myTexture = loader.resources['newMeshTexture'].texture;

var slot = spine.skeleton.slots[num];
var attachment = slot.attachment;
var slotContainer = spine.slotContainers[num];

attachment.rendererObject.texture = myTexture;
attachment.updateUVs();
//the same as slotContainer.children[0]
if (slot.currentMesh) {
    slot.currentMesh.texture = myTexture;
}

Code for reference: https://github.com/pixijs/pixi-spine/blob/master/src/Spine/index.js#L71

https://github.com/pixijs/pixi-spine/blob/master/src/Spine/index.js#L335

https://github.com/pixijs/pixi-spine/blob/master/src/SpineRuntime/MeshAttachment.js#L21

https://github.com/pixijs/pixi-spine/blob/master/src/SpineRuntime/AtlasRegion.js

UPD. added it to pixi-spine README.md

Share this post


Link to post
Share on other sites

I've implemented your lines in this function:

private function updateMesh(type:BodyType, texture:Texture):Void {
	var newTexture = texture;
	var slot = animation.skeleton.slots[type.getIndex()];
	var attachment = slot.attachment;
	var slotContainer = animation.slotContainers[type.getIndex()];
		
	attachment.rendererObject.texture = newTexture;
	attachment.updateUVs();

    //the same as slotContainer.children[0]
	if (slot.currentMesh != null) {
		slot.currentMesh.texture = newTexture;
	}
}

 

But I don't really see any different from when I just swapped the texture for another.

Yet, I don't see anything else in the code reference that I could be missing or needing to do.

So it does switch the texture, but it's scaled and doesn't really look like the first time it is being loaded and shown.

 

Share this post


Link to post
Share on other sites

I've download the zip file from the repository today and I'm using the js file from the bin folder. I assume it's the latest, stable one.

I can upload a demo PM you the url, so you can see what's going on instead of me describing it :)

To make a small demo with code you can review will be a bit more 'challenging' hehe.

Share this post


Link to post
Share on other sites
7 minutes ago, Poundmax said:

I've download the zip file from the repository today and I'm using the js file from the bin folder. I assume it's the latest, stable one.

I can upload a demo PM you the url, so you can see what's going on instead of me describing it :)

To make a small demo with code you can review will be a bit more 'challenging' hehe.

I can easily make the demo if you give me any spine model with additional texture that isnt working. You can make it from standart spine resources (Raptor).n

Share this post


Link to post
Share on other sites
9 minutes ago, ivan.popelyshev said:

I can easily make the demo if you give me any spine model with additional texture that isnt working. You can make it from standart spine resources (Raptor).n

Oh, that would be awesome! Will the spritesheet, atlas and json together with the additional texture be enough? Or is the complete Spine model needed?

And where can I send it to?

Share this post


Link to post
Share on other sites

That was a huge hack. Solution:

var slot = animation.skeleton.slots[0];
var attachment = slot.attachment;
attachment.rendererObject.texture = purpleTop;
attachment.updateUVs();
if (slot.currentMesh) {
    slot.currentMesh.texture = purpleTop;
    slot.currentMesh.uvs = new Float32Array(attachment.uvs);
    slot.currentMesh.dirty = true;
}

 

Share this post


Link to post
Share on other sites

Hi sorry to bump this, but was something I've just been trying out and haven't been able to get it to work if anyone could help?  Is this the correct way still to do this.  I have an animation of a character with 3 different flags waving (as meshes) and need text on those flags, so thought it would be good to try and renderTexture out dynamically with the base png and text on top, then replace.

rendererObject no longer seems to be a property - but have found texture under "region".  With the below the texture doesnt appear

    updateRewardFlag(bonusAmount){
        window.Game.flags.createFlag(bonusAmount);
        let meshTexture = window.Game.flags.latestFlag();

        let num = this.monster.skeleton.findSlotIndex('rag1');

        let slot = this.monster.skeleton.slots[num];
        let attachment = slot.attachment;

        attachment.region.texture = meshTexture;
        attachment.updateUVs();

        if(slot.currentMesh !=null) {
            console.log(slot.currentMesh);
            slot.currentMesh.texture = meshTexture;
            slot.currentMesh.uvs = new Float32Array(attachment.uvs);
            slot.currentMesh.dirty = true;
        }
    }

if I comment out as below it does appear but massively out of scale and rotated. 

    updateRewardFlag(bonusAmount, flagNumber){
        window.Game.flags.createFlag(bonusAmount);
        let meshTexture = window.Game.flags.latestFlag();

        let num = this.monster.skeleton.findSlotIndex('rag1');

        let slot = this.monster.skeleton.slots[num];
        let attachment = slot.attachment;

        attachment.region.texture = meshTexture;
        attachment.updateUVs();

        if(slot.currentMesh !=null) {
            console.log(slot.currentMesh);
            slot.currentMesh.texture = meshTexture;
            //slot.currentMesh.uvs = new Float32Array(attachment.uvs);
            //slot.currentMesh.dirty = true;
        }
    }

Any ideas greatly appreciated!

flag.jpg

Share this post


Link to post
Share on other sites

scrap that! had another look .uvs property has changed to regionUVs, works perfectly now! :D
 

    updateRewardFlag(bonusAmount, flagNumber){
        window.Game.flags.createFlag(bonusAmount);
        let meshTexture = window.Game.flags.latestFlag();

        let num = this.monster.skeleton.findSlotIndex('rag1');

        let slot = this.monster.skeleton.slots[num];
        let attachment = slot.attachment;

        console.log(attachment);

        attachment.region.texture = meshTexture;
        attachment.updateUVs();

        if(slot.currentMesh) {
            console.log(slot.currentMesh);
            slot.currentMesh.texture = meshTexture;
            slot.currentMesh.uvs = new Float32Array(attachment.regionUVs);
            slot.currentMesh.dirty = true;
        }
    }

flagTexture.jpg

Share this post


Link to post
Share on other sites

OK, i failed to do this thing two or three months ago but for legal case, changing texture through skin, without hacks. Thanks, I'll add that hack somewhere ... in examples maybe.

Strange, maybe we just had to enable `uploadTransform` for mesh? http://pixijs.download/v4.x/docs/PIXI.mesh.Mesh.html#uploadUvTransform on creation?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.