Concept #1:
Spine geometry is flat. Although everything is hierarchical with bones, the second you generate the geometry, for regions, meshes, etc... it's all flattened. Your game object hierarchy probably pushes a stack as it traverses. Also, your gameobjects probably draw themselves as they are traversed, and one of your game object types is a Spine animation. So if you make the gameobject a child of the Spine animation, everything in Spine draws, and then your child draws.
You want to interleave without losing gameobject hierarchy functionality (e.g. hit testing).
Concept #2:
You are using one of the runtime's preferred methods of rendering attachments. You iterate over the slots of a skeleton, each slot having a unique name, to render an attachment (each having a unique name) if the attachment is present.
Now, there are currently four types of attachments. It's tempting to add a custom attachment type, but the editor doesn't support custom types. Some of the runtimes use a hack that if you prepend a star to the attachment/slot name it does something different.
Step #1
For now, instead of creating a new attachment type, we'll just pay attention to the names of the slot and attachment. There we can create a MAP['slot/attachment/name'] -> OVERRIDE(gameobject). The override GameObject isn't the child you want to draw, but instead a special object type that breaks normal hierarchical rendering. (I.e. the 'Render/DrawAll()' method returns without visiting children or drawing itself.
This means that during setup you want to grab the name of the slot to override, create a gameobject override instance and add it as a child to the Spine Animation. Then add the gameobjects you are interleaving in the animation to the override.
Step#2
When iterating the slots, you check the MAP for 'slot' or 'attachment' name to see if an override gameobject. If it does exist, you need to grab the transformation matrix of the slot attachment (region) or the slot's bone. Push it to the transform stack and draw the gameobject override and all its children.
Here's how I'm grabbing the slot attachment's transform:
void SpineSlotGO::SetAttachment( spAttachment* attachment )
{
if(!attachment) return;
switch (attachment->type)
{
case SP_ATTACHMENT_REGION:
{
Transform aTrans;
spRegionAttachment* regionAttachment = (spRegionAttachment*)attachment;
float scaleX = regionAttachment->width / regionAttachment->regionWidth;
scaleX *= regionAttachment->scaleX;
float scaleY = regionAttachment->height / regionAttachment->regionHeight;
scaleY *= regionAttachment->scaleY;
float rotation = (float)((90 - regionAttachment->rotation) * 3.1415926535897932385 / 180); // copied from spine
float xTrans = regionAttachment->x;
float yTrans = regionAttachment->y;
aTrans.Scale(scaleX,scaleY);
aTrans.RotateRadFast(rotation);
aTrans.Translate(-xTrans/2, -yTrans/2);
aTrans *= Transform(mTransformMat); // previous transform ??
mTransformMat = aTrans.GetMatrix();
break;
}
case SP_ATTACHMENT_MESH:
case SP_ATTACHMENT_SKINNED_MESH:
case SP_ATTACHMENT_BOUNDING_BOX:
default:
return; // unsupported
}
}
Alternatively, it you are just overriding the slot, then grab slot->bone and:
void SexyAnimation::SpineSlotDO::SetBone( spBone* val )
{
// capture transform
mTransformMat._11 = val->m00;
mTransformMat._12 = -val->m10;
mTransformMat._21 = val->m01;
mTransformMat._22 = -val->m11;
mTransformMat._41 = val->worldX;
mTransformMat._42 = -val->worldY; // positive y-axis down in my setup
}
Some of these things are engine specific, for instance I have a transform class that allows me to build a matrix.
Also, I'm doing a shitload of caching of geometry and in this instance the transform, which leads to
Step#3
You're going to want to save the tranformation matrix so you can use it for hit testing. The OVERRIDE GameObject not only overrides Draw(), but also ContainsClick().
Final Notes:
SetAttachment or SetBone (step #2) is going to need to be called during every update of the animation.