Hi all,
I'm stumped on something that seems like it should be easy but I feel like I'm swimming upstream and I can't seem to make sense of the docs on setting dynamic skins.
I'm one of the contributors to the FlatRedBall game engine (which is based on MonoGame) and we use the MonoGame runtime with a light wrapper for rendering in our engine. So the code I'm using is nearly pure MonoGame runtime and we have tested rigorously enough to be confident that everything is working. So, my problem is not a problem with the FlatRedBall or MonoGame SDK but rather understanding how it is intended to be used.
I have a Spine skeleton .json exported to my test project with a single skin called "template". This skin sets a default head, body, feet, and weapon texture on a simple skeleton. Here is a screenshot of my Spine setup:
I'd like to be able to swap these textures at runtime with textures from an atlas. Here is the C# method I have written to swap the texture used for a provided placeholder name:
public void SetTextureForPlaceholder(string placeholderName, string atlasTextureToSet, Atlas atlas)
{
var dynamicSkin = new Skin("dynamicSkin");
var templateSkin = SpineInstance.Skeleton.Data.FindSkin("template");
// copy the template to the dynamic skin to start
dynamicSkin.CopySkin(templateSkin);
// get the placeholder slot from the template skin
var existingSlot = dynamicSkin.Attachments
.Where(a => a.Name == placeholderName)
.FirstOrDefault();
var existingRegion = existingSlot.Attachment as RegionAttachment;
// create a new region that's a copy of the one we got from the template skin
var dynamicAttachment = new RegionAttachment(existingRegion);
// get dynamic region data from the atlas and set the texture on our dynamic region
var regionData = atlas.Where(r => r.name == atlasTextureToSet).First();
dynamicAttachment.Region = regionData;
// now set the attachment on the dynamic skin
dynamicSkin.SetAttachment(existingSlot.SlotIndex, existingSlot.Name, dynamicAttachment);
// apply the dynamic skin to the skeleton
SpineInstance.Skeleton.SetSkin(dynamicSkin);
}
This method appears to work. When I inspect the object, I can see the region data for the specific slot I'm trying to change appears to update. There are no errors thrown but the visible appearance of the skeleton does not change.
What am I doing wrong and is there a more simple way than this hacky system of copying and altering existing components?