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; }