Example #1
0
void XmlLoader::readPicture(QDomElement const &picture)
{
    QDomNodeList pictureAttributes = picture.childNodes();

    for (unsigned i = 0; i < pictureAttributes.length(); ++i) {
        QDomElement type = pictureAttributes.at(i).toElement();
        if (type.tagName() == "line")
            readLine(type);
        else if (type.tagName() == "ellipse")
            readEllipse(type);
        else if (type.tagName() == "arc")
            readArch(type);
        else if (type.tagName() == "rectangle")
            readRectangle(type);
        else if (type.tagName() == "stylus")
            readStylus(type);
        else if (type.tagName() == "path")
            readPath(type);
        else if (type.tagName() == "curve")
            readCurve(type);
        else if (type.tagName() == "text")
            readText(type);
        else
            qDebug() << "Incorrect picture tag";
    }
}
/** Initialise the Ipo from the specifications in the XML file.
 *  \param curve The XML node with the IPO data.
 *  \param fps Frames per second value, necessary to convert frame values
 *             into time.
 *  \param reverse If this is set to true, the ipo data will be reverse. This
 *             is used by the cannon if the track is driven in reverse.
 */
Ipo::IpoData::IpoData(const XMLNode &curve, float fps, bool reverse)
{
    if(curve.getName()!="curve")
    {
        fprintf(stderr, "Expected 'curve' for animation, got '%s' --> Ignored.\n", 
            curve.getName().c_str());
        return;
    }
    std::string channel;
    curve.get("channel", &channel);
    m_channel=IPO_MAX;
    for(unsigned int i=IPO_LOCX; i<IPO_MAX; i++)
    {
        if(m_all_channel_names[i]==channel) 
        {
            m_channel=(IpoChannelType)i;
            break;
        }
    }
    if(m_channel==IPO_MAX)
    {
        fprintf(stderr, "Unknown animation channel: '%s' - aborting.\n", 
                channel.c_str());
        exit(-1);
    }

    std::string interp; 
    curve.get("interpolation", &interp);
    if     (interp=="const" ) m_interpolation = IP_CONST;
    else if(interp=="linear") m_interpolation = IP_LINEAR;
    else                      m_interpolation = IP_BEZIER;

    std::string extend;
    curve.get("extend", &extend);
    if      (extend=="cyclic") m_extend = ET_CYCLIC;
    else if (extend=="const" ) m_extend = ET_CONST;
    else
    {
        // FIXME: do we want an error message here?
        // For now extrap and cyclic_extrap do not work
        fprintf(stderr, "Unsupported extend '%s' - defaulting to CONST.\n",
                extend.c_str());
        m_extend = ET_CONST;
    }

    if(m_channel==IPO_LOCXYZ)
        readCurve(curve, reverse);
    else
        readIPO(curve, fps, reverse);

}   // IpoData
static spAnimation *readAnimation(spSkeletonBinary *self, const char *name)
{
    float scale = self->scale;
    float duration = 0;
    int drawOrderCount;
    int eventCount;
    
    spAnimation *animation;
    _spTimelineArray arr;
    arr.timelines = NULL;
    arr.capacity = 0;
    arr.count = 0;
    
    // slot timelines
    for (int i = 0, n = readVarint(self, true); i < n; i++) {
        int slotIndex = readVarint(self, true);
        for (int ii = 0, nn = readVarint(self, true); ii < nn; ii++) {
            int timelineType = readByte(self);
            int frameCount = readVarint(self, true);
            switch (timelineType) {
                case SLOT_COLOR: {
                    spColorTimeline *timeline = spColorTimeline_create(frameCount);
                    timeline->slotIndex = slotIndex;
                    for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
                        float time = readFloat(self);
                        float r, g, b, a;
                        readColor(self, &r, &g, &b, &a);
                        spColorTimeline_setFrame(timeline, frameIndex, time, r, g, b, a);
                        if (frameIndex < frameCount - 1) {
                            readCurve(self, SUPER(timeline), frameIndex);
                        }
                    }
                    duration = MAX(duration, timeline->frames[(frameCount - 1) * COLOR_ENTRIES]);
                    addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline));
                    break;
                }
                case SLOT_ATTACHMENT: {
                    spAttachmentTimeline *timeline = spAttachmentTimeline_create(frameCount);
                    timeline->slotIndex = slotIndex;
                    for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
                        float time = readFloat(self);
                        char *name = readString(self);
                        spAttachmentTimeline_setFrame(timeline, frameIndex, time, name);
                    }
                    duration = MAX(duration, timeline->frames[frameCount - 1]);
                    addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline));
                    break;
                }
            }
        }
    }
    
    // bone timelines
    for (int i = 0, n = readVarint(self, true); i < n; i++) {
        int boneIndex = readVarint(self, true);
        for (int ii = 0, nn = readVarint(self, true); ii < nn; ii++) {
            int timelineType = readByte(self);
            int frameCount = readVarint(self, true);
            switch (timelineType) {
                case BONE_ROTATE: {
                    spRotateTimeline *timeline = spRotateTimeline_create(frameCount);
                    timeline->boneIndex = boneIndex;
                    for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
                        float time = readFloat(self);
                        float angle = readFloat(self);
                        spRotateTimeline_setFrame(timeline, frameIndex, time, angle);
                        if (frameIndex < frameCount - 1) {
                            readCurve(self, SUPER(timeline), frameIndex);
                        }
                    }
                    
                    duration = MAX(duration, timeline->frames[(frameCount - 1) * ROTATE_ENTRIES]);
                    addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline));
                    break;
                }
                case BONE_TRANSLATE:
                case BONE_SCALE:
                case BONE_SHEAR: {
                    spTranslateTimeline *timeline;
                    float timelineScale = 1;
                    if (timelineType == BONE_SCALE) {
                        timeline = spScaleTimeline_create(frameCount);
                    }
                    else if (timelineType == BONE_SHEAR)
                        timeline = spShearTimeline_create(frameCount);
                    else {
                        timeline = spTranslateTimeline_create(frameCount);
                        timelineScale = scale;
                    }
                    timeline->boneIndex = boneIndex;
                    for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
                        float time = readFloat(self);
                        float x = readFloat(self) * timelineScale;
                        float y = readFloat(self) * timelineScale;
                        spTranslateTimeline_setFrame(timeline, frameIndex, time, x, y);
                        if (frameIndex < frameCount - 1) {
                            readCurve(self, SUPER(timeline), frameIndex);
                        }
                    }
                    
                    duration = MAX(duration, timeline->frames[(frameCount - 1) * TRANSLATE_ENTRIES]);
                    addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline));
                    break;
                }
            }
        }
    }
    
    // ik constraint timelines
    for (int i = 0, n = readVarint(self, true); i < n; i++) {
        int index = readVarint(self, true);
        int frameCount = readVarint(self, true);
        spIkConstraintTimeline *timeline = spIkConstraintTimeline_create(frameCount);
        timeline->ikConstraintIndex = index;
        for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
            float time = readFloat(self);
            float mix = readFloat(self);
            int blendPositive = readByte(self);
            spIkConstraintTimeline_setFrame(timeline, frameIndex, time, mix, blendPositive);
            if (frameIndex < frameCount - 1) {
                readCurve(self, SUPER(timeline), frameIndex);
            }
        }
        duration = MAX(duration, timeline->frames[(frameCount - 1) * IKCONSTRAINT_ENTRIES]);
        addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline));
    }
    
    // transform constraint timelines
    for (int i = 0, n = readVarint(self, true); i < n; i++) {
        int index = readVarint(self, true);
        int frameCount = readVarint(self, true);
        spTransformConstraintTimeline *timeline = spTransformConstraintTimeline_create(frameCount);
        timeline->transformConstraintIndex = index;
        for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
            float time = readFloat(self);
            float rotateMix = readFloat(self);
            float translateMix = readFloat(self);
            float scaleMix = readFloat(self);
            float shearMix = readFloat(self);
            spTransformConstraintTimeline_setFrame(timeline, frameIndex, time, rotateMix, translateMix, scaleMix, shearMix);
            if (frameIndex < frameCount - 1) {
                readCurve(self, SUPER(timeline), frameIndex);
            }
        }
        
        duration = MAX(duration, timeline->frames[(frameCount - 1) * TRANSFORMCONSTRAINT_ENTRIES]);
        addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline));
    }
    
    // path constraint timelines
    for (int i = 0, n = readVarint(self, true); i < n; i++) {
        int index = readVarint(self, true);
        spPathConstraintData *data = self->skeletonData->pathConstraints[index];
        for (int ii = 0, nn = readVarint(self, true); ii < nn; ii++) {
            int timelineType = readByte(self);
            int frameCount = readVarint(self, true);
            switch (timelineType) {
                case PATH_POSITION:
                case PATH_SPACING: {
                    spPathConstraintPositionTimeline *timeline;
                    float timelineScale = 1;
                    if (timelineType == PATH_SPACING) {
                        timeline = (spPathConstraintPositionTimeline *)spPathConstraintSpacingTimeline_create(frameCount);
                        if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) {
                            timelineScale = scale;
                        }
                    } else {
                        timeline = spPathConstraintPositionTimeline_create(frameCount);
                        if (data->positionMode == SP_POSITION_MODE_FIXED) {
                            timelineScale = scale;
                        }
                    }
                    timeline->pathConstraintIndex = index;
                    for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
                        float time = readFloat(self);
                        float value = readFloat(self);
                        spPathConstraintPositionTimeline_setFrame(timeline, frameIndex, time, value);
                        if (frameIndex < frameCount - 1) {
                            readCurve(self, SUPER(timeline), frameIndex);
                        }
                    }
                    duration = MAX(duration, timeline->frames[(frameCount - 1) * PATHCONSTRAINTPOSITION_ENTRIES]);
                    addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline));
                    break;
                }
                case PATH_MIX: {
                    spPathConstraintMixTimeline *timeline = spPathConstraintMixTimeline_create(frameCount);
                    timeline->pathConstraintIndex = index;
                    for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
                        float time = readFloat(self);
                        float rotateMix = readFloat(self);
                        float translateMix = readFloat(self);
                        spPathConstraintMixTimeline_setFrame(timeline, frameIndex, time, rotateMix, translateMix);
                        if (frameIndex < frameCount - 1) {
                            readCurve(self, SUPER(timeline), frameIndex);
                        }
                    }
                    duration = MAX(duration, timeline->frames[(frameCount - 1) * PATHCONSTRAINTMIX_ENTRIES]);
                    addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline));
                    break;
                }
            }
        }
    }
    
    // deform timelines
    for (int i = 0, n = readVarint(self, true); i < n; i++) {
        spSkin *skin = self->skeletonData->skins[readVarint(self, true)];
        for (int ii = 0, nn = readVarint(self, true); ii < nn; ii++) {
            int slotIndex = readVarint(self, true);
            for (int iii = 0, nnn = readVarint(self, true); iii < nnn; iii++) {
                char *name = readString(self);
                spVertexAttachment *attachment = SUB_CAST(spVertexAttachment, spSkin_getAttachment(skin, slotIndex, name));
                bool weighted = attachment->bones != NULL;
                float *vertices = attachment->vertices;
                int deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount;
                
                int frameCount = readVarint(self, true);
                
                spDeformTimeline *timeline = spDeformTimeline_create(frameCount, deformLength);
                timeline->slotIndex = slotIndex;
                timeline->attachment = SUPER(attachment);
                
                for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
                    float time = readFloat(self);
                    float *deform;
                    int end = readVarint(self, true);
                    if (end == 0)
                        deform = weighted ? CALLOC(float, deformLength) : vertices;
                    else {
                        deform = CALLOC(float, deformLength);
                        int start = readVarint(self, true);
                        end += start;
                        if (scale == 1) {
                            for (int v = start; v < end; v++)
                                deform[v] = readFloat(self);
                        } else {
                            for (int v = start; v < end; v++)
                                deform[v] = readFloat(self) * scale;
                        }
                        if (!weighted) {
                            for (int v = 0, vn = deformLength; v < vn; v++)
                                deform[v] += vertices[v];
                        }
                    }
                    spDeformTimeline_setFrame(timeline, frameIndex, time, deform);
                    if (frameIndex < frameCount - 1) {
                        readCurve(self, SUPER(timeline), frameIndex);
                    }
                }
                duration = MAX(duration, timeline->frames[frameCount - 1]);
                addAnimationTimeline(&arr, SUPER_CAST(spTimeline, timeline));
            }
        }
    }
static Animation* _SkeletonJson_readAnimation (SkeletonJson* self, Json* root, SkeletonData *skeletonData) {
	Animation* animation;

	Json* bones = Json_getItem(root, "bones");
	int boneCount = bones ? Json_getSize(bones) : 0;

	Json* slots = Json_getItem(root, "slots");
	int slotCount = slots ? Json_getSize(slots) : 0;

	int timelineCount = 0;
	int i, ii, iii;
	for (i = 0; i < boneCount; ++i)
		timelineCount += Json_getSize(Json_getItemAt(bones, i));
	for (i = 0; i < slotCount; ++i)
		timelineCount += Json_getSize(Json_getItemAt(slots, i));
	animation = Animation_create(root->name, timelineCount);
	animation->timelineCount = 0;
	skeletonData->animations[skeletonData->animationCount] = animation;
	skeletonData->animationCount++;

	for (i = 0; i < boneCount; ++i) {
		timelineCount = 0;
		Json* boneMap = Json_getItemAt(bones, i);

		const char* boneName = boneMap->name;

		int boneIndex = SkeletonData_findBoneIndex(skeletonData, boneName);
		if (boneIndex == -1) {
			Animation_dispose(animation);
			_SkeletonJson_setError(self, root, "Bone not found: ", boneName);
			return 0;
		}

		timelineCount = Json_getSize(boneMap);
		for (ii = 0; ii < timelineCount; ++ii) {
			float duration;
			Json* timelineArray = Json_getItemAt(boneMap, ii);
			int frameCount = Json_getSize(timelineArray);
			const char* timelineType = timelineArray->name;

			if (kdStrcmp(timelineType, "rotate") == 0) {
				
				RotateTimeline *timeline = RotateTimeline_create(frameCount);
				timeline->boneIndex = boneIndex;
				for (iii = 0; iii < frameCount; ++iii) {
					Json* frame = Json_getItemAt(timelineArray, iii);
					RotateTimeline_setFrame(timeline, iii, Json_getFloat(frame, "time", 0), Json_getFloat(frame, "angle", 0));
					readCurve(SUPER(timeline), iii, frame);
				}
				animation->timelines[animation->timelineCount++] = (Timeline*)timeline;
				duration = timeline->frames[frameCount * 2 - 2];
				if (duration > animation->duration) animation->duration = duration;

			} else {
				int isScale = kdStrcmp(timelineType, "scale") == 0;
				if (isScale || kdStrcmp(timelineType, "translate") == 0) {
					float scale = isScale ? 1 : self->scale;
					TranslateTimeline *timeline = isScale ? ScaleTimeline_create(frameCount) : TranslateTimeline_create(frameCount);
					timeline->boneIndex = boneIndex;
					for (iii = 0; iii < frameCount; ++iii) {
						Json* frame = Json_getItemAt(timelineArray, iii);
						TranslateTimeline_setFrame(timeline, iii, Json_getFloat(frame, "time", 0), Json_getFloat(frame, "x", 0) * scale,
								Json_getFloat(frame, "y", 0) * scale);
						readCurve(SUPER(timeline), iii, frame);
					}
					animation->timelines[animation->timelineCount++] = (Timeline*)timeline;
					duration = timeline->frames[frameCount * 3 - 3];
					if (duration > animation->duration) animation->duration = duration;
				} else {
					Animation_dispose(animation);
					_SkeletonJson_setError(self, 0, "Invalid timeline type for a bone: ", timelineType);
					return 0;
				}
			}
		}
	}

	for (i = 0; i < slotCount; ++i) {
        timelineCount = 0;
		Json* slotMap = Json_getItemAt(slots, i);
		const char* slotName = slotMap->name;

		int slotIndex = SkeletonData_findSlotIndex(skeletonData, slotName);
		if (slotIndex == -1) {
			Animation_dispose(animation);
			_SkeletonJson_setError(self, root, "Slot not found: ", slotName);
			return 0;
		}

		timelineCount = Json_getSize(slotMap);
		for (ii = 0; ii < timelineCount; ++ii) {
			float duration;
			Json* timelineArray = Json_getItemAt(slotMap, ii);
			int frameCount = Json_getSize(timelineArray);
			const char* timelineType = timelineArray->name;

			if (kdStrcmp(timelineType, "color") == 0) {
				ColorTimeline *timeline = ColorTimeline_create(frameCount);
				timeline->slotIndex = slotIndex;
				for (iii = 0; iii < frameCount; ++iii) {
					Json* frame = Json_getItemAt(timelineArray, iii);
					const char* s = Json_getString(frame, "color", 0);
					ColorTimeline_setFrame(timeline, iii, Json_getFloat(frame, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2),
							toColor(s, 3));
					readCurve(SUPER(timeline), iii, frame);
				}
				animation->timelines[animation->timelineCount++] = (Timeline*)timeline;
				duration = timeline->frames[frameCount * 5 - 5];
				if (duration > animation->duration) animation->duration = duration;

			} else if (kdStrcmp(timelineType, "attachment") == 0) {
				AttachmentTimeline *timeline = AttachmentTimeline_create(frameCount);
				timeline->slotIndex = slotIndex;
				for (iii = 0; iii < frameCount; ++iii) {
					Json* frame = Json_getItemAt(timelineArray, iii);
					Json* name = Json_getItem(frame, "name");
					AttachmentTimeline_setFrame(timeline, iii, Json_getFloat(frame, "time", 0),
							name->type == Json_NULL ? 0 : name->valuestring);
				}
				animation->timelines[animation->timelineCount++] = (Timeline*)timeline;
				duration = timeline->frames[frameCount - 1];
				if (duration > animation->duration) animation->duration = duration;

			} else {
				Animation_dispose(animation);
				_SkeletonJson_setError(self, 0, "Invalid timeline type for a slot: ", timelineType);
				return 0;
			}
		}
	}

	return animation;
}