Game Development Community

ShapeBaseImage skinning

by Ferdinand Stewart · in Torque 3D Professional · 02/22/2012 (12:51 am) · 16 replies

Hi Everyone,

I'm having issues trying to skin an image.

Here's the code I'm using in onPickup().
%player.mountImage(FlagImage,$FlagSlot,false,$taggedString);

This works, but only on the first time the image is mounted. On subsequent mounting of the image to the same player, the skin does not change, unless the player is killed.

I've tried this code and it didn't work.
removeTaggedString($taggedString);
addTaggedString(%teamflag);

I've been at this for sometime now, I've run out of ideas and all I've been able to find on the forums is the fourth paramater on mountimage.

I was hoping someone could shed some light on this.

Thanks for any info.

#1
02/22/2012 (6:51 am)
I think you have to destroy and re-create the object to change the skin on the fly. I have a bit that reskins a player when changing teams, but it destroys the player object and creates a new one with the new skin assigned.
#2
02/22/2012 (8:28 am)
Good morning Richard,

Which object are you refering to, the player or the flag? It seems silly to me to kill the player just to remount an image.
#3
02/22/2012 (2:35 pm)
He's referring to player reskinning.
#4
02/22/2012 (3:53 pm)
@Robert

Thanks. But player skinning works just fine. What I'm trying to reskin is the object I'm mounting on the player.
#5
02/22/2012 (6:53 pm)
I didn't "kill" the player... lol - I destroyed it.

Which object needs to have its skin reset? That's the object I would destroy and re-create. My specific case was reskinning players, but in theory it's the same thing - the functionality comes from the same base class I think....
#6
02/22/2012 (9:17 pm)
Reskinning objects isn't really the issue. I have all my objects skinned based on which team they belong to.

My issue is reskinning a shapebaseIMAGE, that is, the image I am mounting onto an object. Like a weapon, an armor, a shield, or a flag. On the first call to mountimage, the skin is applied just fine. However, unmounting the image and then remounting it has no effect on the skin.

I was hoping someone had figured out a way of doing this without respawning the player.
#7
02/23/2012 (6:43 am)
I was looking at the source and I think it might work if you call reSkin() after calling setSkinName(). Haven't tested this though.

In my reading I found that ShapeBaseImages don't have an underlying engine class so setSkinName() shouldn't even work on them. Is there a reason you can't make two flags and mount the appropriate one when a flag is picked up?
#8
02/23/2012 (7:32 am)
Good morning,

You are correct, setSkinName() does not work on ShapeBaseImages.
However, using a tagged string as the fourth paramater on mountImage allows you to reskin a ShapeBaseImage. for example.

%player.mountImage(%flag.image,$FlagSlot,false,$flagSkin[%flag.team]);

This works only on the first time it's called. Subsequent calls defaults back to the texture in the dae. Unless the player is killed or destroyed in between calls.

For example. The player scores and the flag is sent back to it's base to get picked up again. If the same player, without dying, picks up this flag again, the mounted image will not get skinned.

I read somewhere in the forums that tagged strings only get sent over the network once to cut down on traffic. My dilima is that I seem to be able to use the tagged string only once.

I guess my problem is, how do I use addTaggedString.
#9
02/23/2012 (8:02 am)
I'm failing to grasp the need for this. Make two ShapeBaseImageData objects for your flags and set the skin on level load for each. You could then treat it like a weapon pick-up: Create it as an ItemData, onCollision() destroy the ItemData, select the correct flag, mount the appropriate ShapeBaseImage to the player, destroy the ShapeBaseImage on score and drop the ItemData back at the flag location.

Adding the same tagged string again won't do it - you'd either overwrite the value of the entry with the same string contents (no net effect) or create a second tagged string with the same string contents (undefined behavior may result). Have you looked at the mountImage method? I don't know if its script or engine, but if it's script try calling reSkin() after the flag's skin name is set in that method.

Back to my original train of thought though - I wasn't suggesting you kill the player to reset the skin on the flag, I was suggesting you destroy and recreate the flag.

I haven't tried any of this, but treating the flag like other drops and having two flags (or more if you allow more teams) skinned appropriately in the model should work like a charm.
#10
02/23/2012 (9:36 am)
I really appreciate your time and effort with this issue.

I think I see the confusion. I can skin the flag without any problems.
The flag will take any skin I apply using setSkinName(%whateverIwant);

The problem is the flag.image. As far as I know, when you mount an image, you're not actually creating an object. Your just mounting an image datablock. Please correct me if I'm wrong, 'cause this maybe where my problem lies. The actual flag is getting destroyed in OnPickup();

The actual flag itself, I am treating like an item drop.

When the player is running around with a flag stuck to his back, that's the ShapeBaseImageData. You can change the skin when you mount it to your player.

Let's say the player is picking up a flag with a dragon for a logo. When he picks it up the first time. He's running around with flag on his back with a dragon logo. Then he drops it for some reason. Now thre's a flag in his world with a dragon logo. He picks it up again. Now he's running around with a flag on his back without a logo at all. He dropps it again. The correct logo is displayed. Somebody else picks it up. The correct logo is displayed.

When the flag is dropped, it displays the correct logo. When it's picked up by a player, the correct is displayed. When the same player picks up the flag more than once, then it no longer displays the correct logo.

Killing or destroying the player allows mounting the flag with the correct logo. It just seems like overkill, but less so than having multiple models.
#11
02/23/2012 (10:31 am)
@Ferdinand, this looks like a bug to me. I would suggest submitting a formal bug report for it.
I've just tested it out with a different model, and attempting to mount an image with a different skin more than once does not apply the skin.

As you correctly point out, mountImage takes the following parameters:
image the Image to mount
slot Image slot to mount into (valid range is 0 - 3)
loaded initial loaded state for the Image
skinTag tagged string to reskin the mounted Image

So, you are definately trying to use the function as it was intended, but the re-skinning part appears broken. Interestingly, the main shapeBase re-skinning was prone to a similar problem with earlier versions of T3D, I wonder if this got overlooked somewhere?

Richard is suggesting a method that you could use as a workaround. You would need separate ShapeBaseImageData datablocks for each team flag, and you would also need separate models for each team flag.

eg:
[code]
datablock ShapeBaseImageData(team1FlagImage)
{
shapeFile = "art/shapes/flags/team1Flag";
};

datablock ShapeBaseImageData(team2FlagImage)
{
shapeFile = "art/shapes/flags/team2Flag";
};

Then when the player picks the flag up, you mount the appropriate image. This method is less elegant than using 1 datablock for all flags, and simply changing the texture as you need multiple flag datablocks and multiple flag models.

#12
02/23/2012 (4:15 pm)
I agree that it appears to be a bug - The method suggested should work as a means to get your game functioning as intended (if not as planned :) ).

In fact, if this worked correctly you could change player skins on the fly as well.

Maybe using .reSkin() on the player when mounting before the mount call? Might refresh the skin for the system and kick the correct skin for the ShapeBaseImage.... <shrug> shot in the dark there. The call to setSkinName() wanders down into NetObject-land and I haven't had time to really dig.
#13
02/23/2012 (9:46 pm)
Ahhh, Thanks gentlemen.

It had not even occured to me that it might be a bug. Today I thought it might be because I just didn't know how to use addTaggedString, but testing with the other taggedString function always returned the correct values.

I suppose at this point in time, this has to be a dead end.

Anyway, my sulotion for now is to just respawn the player after he scores. Not as elegant, but in my opinion, cleaner than multiple models and datablocks for the same object.

Again, many thanks for all the help.
#14
02/24/2012 (6:15 am)
Did you go with respawning in place or sending the player back to an origin point?
#15
02/25/2012 (1:39 am)
Sorry it took so long to respond. Been busy.

Right now the player must go through a teleport to deliver the flag. As he teleports back out, I place the spawnMarker at the player position after teleporting. Respawn the player. Return the marker.

Doing it while teleporting takes care of the player winking in and out.