Jump to content

Changing textures/skin in Pixi Spine


Poundmax
 Share

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

Link to comment
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

 

Link to comment
Share on other sites

  • 2 weeks later...

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

Link to comment
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

Link to comment
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.

 

Link to comment
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.

Link to comment
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

Link to comment
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?

Link to comment
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;
}

 

Link to comment
Share on other sites

  • 2 years later...

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

Link to comment
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

Link to comment
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?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...