void TransformUtil::transformPointWithParent(DBTransform &transform, DBTransform &parent)
        {
            transformToMatrix(parent, _helpMatrix);
            _helpMatrix = MatrixInvert(_helpMatrix);

            Number x = transform.x;
            Number y = transform.y;

            transform.x = _helpMatrix.a * x + _helpMatrix.c * y + _helpMatrix.tx;
            transform.y = _helpMatrix.b * x + _helpMatrix.d * y + _helpMatrix.ty;

            transform.skewX = formatRadian(transform.skewX - parent.skewX);
            transform.skewY = formatRadian(transform.skewY - parent.skewY);
        }
void BaseDataParser::getTimelineTransform(const TransformTimeline *timeline, int position, Transform *retult, bool isGlobal)
{
    for (size_t i = 0, l = timeline->frameList.size(); i < l; ++i)
    {
        const TransformFrame *currentFrame = static_cast<const TransformFrame*>(timeline->frameList[i]);
        
        if (currentFrame->position <= position && currentFrame->position + currentFrame->duration > position)
        {
            if (i == timeline->frameList.size() - 1 || position == currentFrame->position)
            {
                //copy
                *retult = isGlobal ? currentFrame->global : currentFrame->transform;
            }
            else
            {
                float progress = (position - currentFrame->position) / (float)(currentFrame->duration);
                const float tweenEasing = currentFrame->tweenEasing;
                
                if (tweenEasing && tweenEasing != NO_TWEEN_EASING && tweenEasing != AUTO_TWEEN_EASING)
                {
                    progress = getEaseValue(progress, tweenEasing);
                }
                
                const TransformFrame *nextFrame = static_cast<const TransformFrame*>(timeline->frameList[i + 1]);
                const Transform *currentTransform = isGlobal ? &currentFrame->global : &currentFrame->transform;
                const Transform *nextTransform = isGlobal ? &nextFrame->global : &nextFrame->transform;
                retult->x = currentTransform->x + (nextTransform->x - currentTransform->x) * progress;
                retult->y = currentTransform->y + (nextTransform->y - currentTransform->y) * progress;
                retult->skewX = formatRadian(currentTransform->skewX + (nextTransform->skewX - currentTransform->skewX) * progress);
                retult->skewY = formatRadian(currentTransform->skewY + (nextTransform->skewY - currentTransform->skewY) * progress);
                retult->scaleX = currentTransform->scaleX + (nextTransform->scaleX - currentTransform->scaleX) * progress;
                retult->scaleY = currentTransform->scaleY + (nextTransform->scaleY - currentTransform->scaleY) * progress;
            }
            
            break;
        }
    }
}
void BaseDataParser::transformAnimationData(AnimationData *animationData, const ArmatureData *armatureData)
{
    SkinData *skinData = armatureData->getSkinData("");
    
    for (size_t i = 0, l = armatureData->boneDataList.size(); i < l; ++i)
    {
        const BoneData *boneData = armatureData->boneDataList[i];
        TransformTimeline *timeline = animationData->getTimeline(boneData->name);
        
        if (!timeline)
        {
            continue;
        }
        
        SlotData *slotData = nullptr;
        
        if (skinData)
        {
            for (size_t i = 0, l = skinData->slotDataList.size(); i < l; ++i)
            {
                slotData = skinData->slotDataList[i];
                
                if (slotData->parent == boneData->name)
                {
                    break;
                }
            }
        }
        
        Transform *originTransform = nullptr;
        Point *originPivot = nullptr;
        TransformFrame *prevFrame = nullptr;
        
        for (size_t i = 0, l = timeline->frameList.size(); i < l; ++i)
        {
            TransformFrame *frame = static_cast<TransformFrame*>(timeline->frameList[i]);
            setFrameTransform(animationData, armatureData, boneData, frame);
            frame->transform.x -= boneData->transform.x;
            frame->transform.y -= boneData->transform.y;
            frame->transform.skewX -= boneData->transform.skewX;
            frame->transform.skewY -= boneData->transform.skewY;
            frame->transform.scaleX -= boneData->transform.scaleX;
            frame->transform.scaleY -= boneData->transform.scaleY;
            
            if (!timeline->transformed && slotData)
            {
                frame->zOrder -= slotData->zOrder;
            }
            
            if (!originTransform)
            {
                // copy
                timeline->originTransform = frame->transform;
                originTransform = &timeline->originTransform;
                originTransform->skewX = formatRadian(originTransform->skewX);
                originTransform->skewY = formatRadian(originTransform->skewY);
                // copy
                timeline->originPivot = frame->pivot;
                originPivot = &timeline->originPivot;
            }
            
            frame->transform.x -= originTransform->x;
            frame->transform.y -= originTransform->y;
            frame->transform.skewX = formatRadian(frame->transform.skewX - originTransform->skewX);
            frame->transform.skewY = formatRadian(frame->transform.skewY - originTransform->skewY);
            frame->transform.scaleX -= originTransform->scaleX;
            frame->transform.scaleY -= originTransform->scaleY;
            
            if (!timeline->transformed)
            {
                frame->pivot.x -= originPivot->x;
                frame->pivot.y -= originPivot->y;
            }
            
            if (prevFrame)
            {
                const float dLX = frame->transform.skewX - prevFrame->transform.skewX;
                
                if (prevFrame->tweenRotate)
                {
                    if (prevFrame->tweenRotate > 0)
                    {
                        if (dLX < 0)
                        {
                            frame->transform.skewX += PI * 2;
                            frame->transform.skewY += PI * 2;
                        }
                        
                        if (prevFrame->tweenRotate > 1)
                        {
                            frame->transform.skewX += PI * 2 * (prevFrame->tweenRotate - 1);
                            frame->transform.skewY += PI * 2 * (prevFrame->tweenRotate - 1);
                        }
                    }
                    else
                    {
                        if (dLX > 0)
                        {
                            frame->transform.skewX -= PI * 2;
                            frame->transform.skewY -= PI * 2;
                        }
                        
                        if (prevFrame->tweenRotate < 1)
                        {
                            frame->transform.skewX += PI * 2 * (prevFrame->tweenRotate + 1);
                            frame->transform.skewY += PI * 2 * (prevFrame->tweenRotate + 1);
                        }
                    }
                }
                else
                {
                    frame->transform.skewX = prevFrame->transform.skewX + formatRadian(frame->transform.skewX - prevFrame->transform.skewX);
                    frame->transform.skewY = prevFrame->transform.skewY + formatRadian(frame->transform.skewY - prevFrame->transform.skewY);
                }
            }
            
            prevFrame = frame;
        }
        
        timeline->transformed = true;
    }
}