Before writing an article about Cocos2dx-lua's spine local dress up. The main principle is to add the Addskin () method according to the Setskin () method in the SpineRenderer.cpp in COCOS2DX. And in
Add method int Lua_cocos2dx_spine_skeletonrenderer_addskin (la_state* tolua_S) in Lua_cocos2dx_spine_auto.cpp, Complete the lua-building so that it can be invoked at the Lua end.
Previous address: http://blog.csdn.net/u010536615/article/details/51137235
The reasons for writing in the order are:
Spine animation When there is a key frame of things, the general animation when the first frame will be all the relevant components (slots) key on the keyframe. However, we did not animate the key on the keyframe, so the previous Addskin () method has no problem. However, after the key frame key, the Addskin () method is not used, although there is no problem with the method implementation. So the spine from parsing to the animation of the implementation of the code are read again. Enables the method to support local dress up after keyframes on key.
The solution looks directly at the title 3.
---------------------------------------------------------------1. Dress principle--------------------------------------------
Replace the attachment part in the slots slot.
Find the attachment part that corresponds to the slots, and then traverse the skins to see if there is a attachment part in the current skin, and if so, replace the part in the slots part of the original attachment.
---------------------------------------------------------------2. The cause of the problem--------------------------------------------
The reason:
Self.actor = sp. Skeletonanimation:create ("Red/red.json", "Red/red.atlas", 1)
Self.actor:setAnimation (0, "red_wait", True)
Self.actor:setPosition (450, 300)
Self:addchild (Self.actor)
In fact, only create, do not drop animation self.actor:setAnimation (0, "red_wait", True), Addskin () method is useful.
So the problem is when you play the animation. When the animation is played, the attachment in slots is replaced with the current skin. So the Addskin () that was previously set is replaced, and the animation doesn't work when it moves.
--The Setskin () of the engine belt works:
So why Setskin () is useful. That's the point.
Also said before, the replacement is to find the current settings of the skin. And the logic of the engine can only set the overall skin, that is, the whole outfit. Does not provide the ability to set a single part skin.
The Setskin method passes
Const_cast (spskin*, Self->skin) = Newskin;
To set the current overall equipment.
Replace each part with the current skin:
if (Self->skin) {
Spattachment *attachment =spskin_getattachment (Self->skin, Slotindex, AttachmentName);
if (attachment) return attachment;
}
if (Self->data->defaultskin) {
Spattachment *attachment =spskin_getattachment (Self->data->defaultskin, Slotindex, attachmentName);
if (attachment) return attachment;
}
So what we need to do is add the skin attribute to each slot.
When replacing, find out if the current part has skin, and some words apply the part's skin. Instead of the whole skin.
--------------------------------------3. Solution--------------------------------------------
1. Add skin attributes to each slot
Add the Spskin*const skin attribute to the spslotdata structure in editor-support->spine->slotdata.h and enclose the initial value.
Add Skin.h #include <spine/Skin.h>
typedef struct SPSLOTDATA {
constchar* const name;
const spbonedata* Const bonedata;
Const char* AttachmentName;
Float R, G, B, A;
Spblendmode Blendmode;
spskin* Const skin;//New Skin Property
#ifdef __cplusplus
Spslotdata ():
Name (0),
Bonedata (0),
AttachmentName (0),
Skin (0),//New Skin Property
R (0), g (0), B (0), a (0),
Blendmode (sp_blend_mode_normal) {
}
#endif
} Spslotdata; 2.addSkin () method, replace the corresponding slot attached skin
Editor-support->spine->skeleton.c to modify the Spskeleton_addskin method in my previous article:
void Spskeleton_addskin (spskeleton* self,spskin* Newskin, constchar* partname) {
if (Newskin) {
int i;
for (i = 0; i < self->slotscount; ++i) {
spslot* slot = self->slots[i];
if (slot->data->attachmentname) {
if (strcmp (Slot->data->attachmentname, PartName) ==0) {
spattachment* attachment =spskin_getattachment (Newskin, I, slot->data->attachmentname);
if (attachment)
{
Const_cast (spskin*, Self->data->slots[i]->skin) = Newskin;//slot->skin Assignment
Spslot_setattachment (slot, attachment);
}
}
}
}
}
3. To determine the current slot skin when replacing slot attachment parts
Modify the Spskeleton_getattachmentforslotindex method in Editor-support->spine->skeleton.c, where two if is the new code.
spattachment* Spskeleton_getattachmentforslotindex (constspskeleton* self, int slotindex, const char* attachmentName) {
if (Slotindex = = 1) return 0;
if (Self->skin) {
New
if (Self->data->slots[slotindex]->skin) {
Spattachment *attachment =spskin_getattachment (Self->data->slots[slotindex]->skin, SlotIndex, AttachmentName);
if (attachment) return attachment;
}
Spattachment *attachment =spskin_getattachment (Self->skin, Slotindex, AttachmentName);
if (attachment) return attachment;
}
if (Self->data->defaultskin) {
New
if (Self->data->slots[slotindex]->skin) {
Spattachment *attachment =spskin_getattachment (Self->data->slots[slotindex]->skin, SlotIndex, AttachmentName);
if (attachment) return attachment;
}
Spattachment *attachment =spskin_getattachment (Self->data->defaultskin, Slotindex, attachmentName);
if (attachment) return attachment;
}
Return0;
}
4. Application
The Setskin method is used for contrast detection.
Self.actor = sp. Skeletonanimation:create ("Red/red.json", "Red/red.atlas", 1)
Self.actor:setAnimation (0, "red_wait", True)
Self.actor:setPosition (450, 300)
Self:addchild (Self.actor)
Self.actor:setSkin ("Hm_lv1")
Local FASHIONSTR = String.Format ("hm_lv%d", 4)
Self.actor:addSkin ("Hm_lv2", "Weap_wuqi")
Self.actor:addSkin (Fashionstr, "hm_huwan_z")
Self.actor:addSkin (Fashionstr, "Hm_r_jiao")
Self.actor:addSkin (Fashionstr, "hm_jiao_l")--hm_l_jiao
Self.actor:addSkin (Fashionstr, "Hm_dun")
Self.actor:addSkin (Fashionstr, "Hm_kuzi")
--------------------------------------4. Notes & Notes--------------------------------------------
-First attach the difference between the JSON file after the animation key and the non key keyframe:
Key on:
"Animations": {"red_wait": {"slots": {
"Hm_r_jiao": {"attachment": [
{' time ': 0, ' name ': ' Hm_r_jiao '},
{' Time ': 0.6, ' name ': null}],
"Color": [
{"Time": 0, "color": "FFFFFFFF"},
{"Time": 0.3, "color": "00ffffff"}
]}}}
No key on:
"Animations": {"red_wait": {"slots": {
]}}}
In fact is the key on the slots "Hm_r_jiao" attributes, the key in the attachment attribute, in fact, remove the attachment attribute, only the Color property, before the Addskin () local dress is also useful.
--Animation code:
In SkeletonAnimation.cpp
void Skeletonanimation::update (float deltatime) {
Super::update (deltatime);
Deltatime *= _timescale;
Spanimationstate_update (_state, deltatime);
Spanimationstate_apply (_state, _skeleton);
Spskeleton_updateworldtransform (_skeleton);
}
This code to look at the line, the focus is below.
-The Attachment property of the code that parses the previous paragraph:
The _spskeletonjson_readanimation method in the Skeletonjson.c file:
else if (strcmp (timelinearray->name, "attachment") = = 0) {
Spattachmenttimeline *timeline = spattachmenttimeline_create (timelinearray->size);
Timeline->slotindex = Slotindex;
for (frame = timelinearray->child, i = 0; frame; frame = Frame->next, ++i) {
json* name = Json_getitem (frame, "name");
Spattachmenttimeline_setframe (timeline, I, Json_getfloat (frame, "time", 0),
Name->type = = Json_null? 0:name->valuestring);
}
animation->timelines[animation->timelinescount++] = Super_cast (sptimeline, Timeline);
Duration = timeline->frames[timelinearray->size-1];
if (Duration > Animation->duration) animation->duration = Duration;
}
of which spattachmenttimeline_create (timelinearray->size):
spattachmenttimeline* spattachmenttimeline_create (int framescount) {
spattachmenttimeline* self =new (spattachmenttimeline);
_sptimeline_init (SUPER (self), sp_timeline_attachment,_spattachmenttimeline_dispose,_spattachmenttimeline_apply) ;
const_cast (int, self->framescount) = Framescount;