- 수정됨
[ts] Change color of an instances attachment at runtime
I am looking to add a custom color to the players' complexion at runtime, there will be many different instances of the player. They should be able to pick from a color wheel of colors, so there are too many options to create skins for in the Spine project editor and use Mix and Match.
I implemented a method using a custom skin per instance and then copy the attachment to color, assign a new color to it and assign it to the instances custom skin.
Any feedback on this method or suggestions on alternatives?
SetCustomAttachmentColor(skinName, slotName, attachmentName, color)
{
const skeleton = this.skeletonInfo.skeleton;
let skin = this.customSkins[skinName];
let slotIndex = skeleton.data.findSlot(slotName).index;
let attachment = skin.getAttachment(slotIndex, attachmentName);
let newAttachment = attachment.copy();
let tint = new spine.Color(
SpineBatch.getRValue(color),
SpineBatch.getGValue(color),
SpineBatch.getBValue(color),
SpineBatch.getAValue(color));
newAttachment.color = tint;
skin.setAttachment(slotIndex, attachmentName, newAttachment);
console.log('[Spine] attachment', newAttachment)
skeleton.setSkin(this.customSkins[skinName]);
skeleton.setSlotsToSetupPose();
}
Example (two instances of the same skeleton):
That#s one way of doing it. Alterantively you could also just change the slot color of the specific attachment.
Thanks for the comments. I implemented both methods. The slot change is 'temporary', if the same skin is set again, the slot color is removed. The above code will change the skin itself.
Technically slot color is separate from the skin, it is not reset if the skin is changed. I guess you are calling Skeleton setToSetupPose
or Skeleton setSlotsToSetupPose
when changing skins? Note while that is often what a user wants, it may not always be the case.
Setting the slot color will affect any attachment in that slot. The slot color may be keyed in animations, which would overwrite the set color when such an animation is applied. Because of this it is common to apply animations, then apply other changes (set slot color, change attachments, modify bone transforms, etc).
Setting the attachment color affects only that attachment. If the attachment is not copied, the color change may affect multiple skeleton instances using the same attachment instance. If the attachment is copied, code that attaches a specific attachment will attach the original attachment, where the color was not set. For example, an animation with an AttachmentTimeline uses Skeleton getAttachment
to find the attachment by name in the skeleton's active skins, as does Slot setToSetupPose
. Your code sets the attachment in the skin, which means if other skeleton instances use that skin instance, they could end up with the colored attachment if it is keyed in an animation or Slot setToSetupPose
(or Skeleton setToSetupPose
or Skeleton setSlotsToSetupPose
, which call Slot setToSetupPose
).
It may complicate your API to provide users with utility methods that copy an attachment and replace the old attachment in the skin. What is your end goal? If it's just to set an attachment's color, a method that does that (without copying it or changing the skins) could make sense if it is a common need and the manual way of doing it is verbose. If you want to provide a way to set a slot's color and have it override any existing color or that from animations, it could make sense to have a method that adds the color to a list for the skeleton and sets the slot colors every frame, after applying animations. You could do this with other things, too (any changes to skeleton/slot/bone/etc state: setting attachments, bone transforms, etc).
- 수정됨
Thanks for all the details. I need to take a step back and think about how much to expose and what to do with 'convenience' functions/actions that must be used with constraints.
In this case, with the custom skin defined above, the custom skin is only available to one particular skeleton instance (in terms of how the functions/actions work, another instance cannot use the same custom skin.) So, I think this is a reasonable method - the new custom skin is only available to the instance, the copied attachment has the same name as it was previously, so getAttachment should work same as before.
After working on this for a bit with real projects. I went with your recommended path of coloring slots and keeping track of slot colors, so if a new skin is set or calling setToSetupPose, I have an action which can reapply the slot colors again as needed. I also have some actions to reset the 'saved' slot colors back to normal. I also added dark color for slots, which looks great too!
Sounds like a good solution!