void YHCCActionHelper::runIntervalForeverAnimation2(float interval, cocos2d::CCAnimation * animation,
                                                    cocos2d::CCSprite * pSprite,
                                                    const std::function<void ()> & begin_callback,
                                                    const std::function<void ()> & end_callback)
{
    Vector<FiniteTimeAction *> actions;
    Animate * animate = Animate::create(animation);
    Hide * hide = Hide::create();
    DelayTime * delay = DelayTime::create(interval);
    Show * show = Show::create();
    
    if (begin_callback != nullptr)
    {
        CallFunc * callfunc = CallFunc::create(begin_callback);
        actions.pushBack(callfunc);
    }
    actions.pushBack(animate);
    actions.pushBack(hide);
    actions.pushBack(delay);
    actions.pushBack(show);
    if (end_callback != nullptr)
    {
        CallFunc * callfunc = CallFunc::create(end_callback);
        actions.pushBack(callfunc);
    }
    
    Sequence * sequence = Sequence::create(actions);
    RepeatForever * repeatForever = RepeatForever::create(sequence);
    AnimationFrame * frame = animate->getAnimation()->getFrames().at(0);
    pSprite->setDisplayFrame(frame->getSpriteFrame());
    pSprite->runAction(repeatForever);
}
Esempio n. 2
0
bool Animate::initWithAnimation(Animation *pAnimation)
{
    CCASSERT( pAnimation!=NULL, "Animate: argument Animation must be non-NULL");

    float singleDuration = pAnimation->getDuration();

    if ( ActionInterval::initWithDuration(singleDuration * pAnimation->getLoops() ) ) 
    {
        _nextFrame = 0;
        setAnimation(pAnimation);
        _origFrame = NULL;
        _executedLoops = 0;

        _splitTimes->reserve(pAnimation->getFrames()->count());

        float accumUnitsOfTime = 0;
        float newUnitOfTimeValue = singleDuration / pAnimation->getTotalDelayUnits();

        Array* pFrames = pAnimation->getFrames();
        CCARRAY_VERIFY_TYPE(pFrames, AnimationFrame*);

        Object* pObj = NULL;
        CCARRAY_FOREACH(pFrames, pObj)
        {
            AnimationFrame* frame = static_cast<AnimationFrame*>(pObj);
            float value = (accumUnitsOfTime * newUnitOfTimeValue) / singleDuration;
            accumUnitsOfTime += frame->getDelayUnits();
            _splitTimes->push_back(value);
        }    
Esempio n. 3
0
void Animation::draw(ResourceLoader *resLoader, SDL_Surface *screen, AnimationInstance *ai, float x, float y)
{
	AnimationFrame *currFrame = NULL;
	float cumulativeTime = 0;
	float timeThisFrame = 0;
	float timeInSeconds = ai->getComplete()*totalTime;
	for (int i = 0; i < numFrames; ++i)
	{
		if (timeInSeconds >= cumulativeTime)
		{
			timeThisFrame = timeInSeconds-cumulativeTime;
			currFrame = &(frames[i]);
		}else
		{
			break;
		}
		cumulativeTime += currFrame->getTime();
	}
	if (currFrame != NULL)
	{
		for (int i = 0; i < currFrame->getEffectSize(); ++i)
			currFrame->getEffect(i)->setTime(timeThisFrame);
		for (int i = 0; i < currFrame->getNumImages(); ++i)
		{
			Pos2 *offset = currFrame->getOffset(i);
			resLoader->draw_image(
				currFrame->getImage(i), 
				screen, x+offset->getX(), 
				y+offset->getY(), currFrame->getEffects(), currFrame->getEffectSize());
		}
	}
	//SDL_BlitSurface( resLoader->get_image(currFrame->image_type), src_rect, screen, dst_rect );
}
Esempio n. 4
0
    void AnimationAffector::end(long long dt, long long age) {
        W_UNUSED(dt); W_UNUSED(age);

        if(priv->restoreOriginal) {
            sprite->texture(priv->originalTexture);
            sprite->frame(priv->originalFrame.x(), priv->originalFrame.y());
        } else {
            AnimationFrame f = priv->animation->last();
            sprite->texture(f.texture());
            sprite->frame(f.frame().x(), f.frame().y());
        }
    }
    /// Duplicate from given frame.
    ///
    /// \param op Frame to duplicate.
    void duplicate(const AnimationFrame &op)
    {
      unsigned bone_count = op.getBoneCount();

      m_time = op.getTime();
      m_bones.resize(bone_count);

      for(unsigned ii = 0; (bone_count > ii); ++ii)
      {
        m_bones[ii] = op.getBoneState(ii);
      }
    }
void AnimationCache::parseVersion1(Dictionary* animations)
{
    SpriteFrameCache *frameCache = SpriteFrameCache::sharedSpriteFrameCache();

    DictElement* pElement = NULL;
    CCDICT_FOREACH(animations, pElement)
    {
        Dictionary* animationDict = (Dictionary*)pElement->getObject();
        Array* frameNames = (Array*)animationDict->objectForKey("frames");
        float delay = animationDict->valueForKey("delay")->floatValue();
        Animation* animation = NULL;

        if ( frameNames == NULL ) 
        {
            CCLOG("cocos2d: AnimationCache: Animation '%s' found in dictionary without any frames - cannot add to animation cache.", pElement->getStrKey());
            continue;
        }

        Array* frames = Array::createWithCapacity(frameNames->count());
        frames->retain();

        Object* pObj = NULL;
        CCARRAY_FOREACH(frameNames, pObj)
        {
            const char* frameName = ((String*)pObj)->getCString();
            SpriteFrame* spriteFrame = frameCache->spriteFrameByName(frameName);

            if ( ! spriteFrame ) {
                CCLOG("cocos2d: AnimationCache: Animation '%s' refers to frame '%s' which is not currently in the SpriteFrameCache. This frame will not be added to the animation.", pElement->getStrKey(), frameName);

                continue;
            }

            AnimationFrame* animFrame = new AnimationFrame();
            animFrame->initWithSpriteFrame(spriteFrame, 1, NULL);
            frames->addObject(animFrame);
            animFrame->release();
        }

        if ( frames->count() == 0 ) {
            CCLOG("cocos2d: AnimationCache: None of the frames for animation '%s' were found in the SpriteFrameCache. Animation is not being added to the Animation Cache.", pElement->getStrKey());
            continue;
        } else if ( frames->count() != frameNames->count() ) {
            CCLOG("cocos2d: AnimationCache: An animation in your dictionary refers to a frame which is not in the SpriteFrameCache. Some or all of the frames for the animation '%s' may be missing.", pElement->getStrKey());
        }

        animation = Animation::create(frames, delay, 1);

        AnimationCache::sharedAnimationCache()->addAnimation(animation, pElement->getStrKey());
        frames->release();
    }    
Esempio n. 7
0
void Sprite::setDisplayFrameWithAnimationName(const std::string& animationName, ssize_t frameIndex)
{
    CCASSERT(animationName.size()>0, "CCSprite#setDisplayFrameWithAnimationName. animationName must not be nullptr");

    Animation *a = AnimationCache::getInstance()->getAnimation(animationName);

    CCASSERT(a, "CCSprite#setDisplayFrameWithAnimationName: Frame not found");

    AnimationFrame* frame = a->getFrames().at(frameIndex);

    CCASSERT(frame, "CCSprite#setDisplayFrame. Invalid frame");

    setSpriteFrame(frame->getSpriteFrame());
}
Esempio n. 8
0
    void AnimationAffector::animate(long long dt, long long age) {
        W_UNUSED(age);

        priv->dt += dt;
        while(priv->dt > priv->animation->delay() && priv->currentFrame < priv->animation->frames()) {
            AnimationFrame f = priv->animation->frame(priv->currentFrame); 

            sprite->texture(f.texture());
            sprite->frame(f.frame().x(), f.frame().y());

            priv->currentFrame++;
            priv->dt -= priv->animation->delay();
        }
    }
Esempio n. 9
0
    void MovieSprite::initPlayer()
    {
        if (_initialized)
            return;

        _initialized = true;

        _initPlayer();

        Point sz = _bufferSize;
        //sz = Point(nextPOT(sz.x), nextPOT(sz.y));

        Point uvSize = _bufferSize / 2;
        //uvSize = Point(nextPOT(uvSize.x), nextPOT(uvSize.y));
        //uvSize = sz;

        _mtUV.init(uvSize.x, uvSize.y, TF_A8L8);
        _mtUV.fill_zero();
        _textureUV = IVideoDriver::instance->createTexture();
        _textureUV->init(uvSize.x, uvSize.y, _mtUV.getFormat(), false);

        _mtYA.init(sz.x, sz.y, _hasAlphaChannel ? TF_A8L8 : TF_L8);
        _mtYA.fill_zero();
        _textureYA = IVideoDriver::instance->createTexture();
        _textureYA->init(sz.x, sz.y, _mtYA.getFormat(), false);

        if (_hasAlphaChannel)
            setBlendMode(blend_premultiplied_alpha);
        else
            setBlendMode(blend_disabled);

        Diffuse d;
        d.base = _textureYA;
        d.alpha = _textureUV;
        d.premultiplied = true;

        AnimationFrame frame;
        RectF mr = _movieRect.cast<RectF>();

        Vector2 szf = sz.cast<Vector2>();
        RectF tcYA = RectF(mr.pos.div(szf), mr.size.div(szf));
        frame.init(0, d, tcYA, mr, mr.size);

        _yaScale = Vector2(uvSize.x / szf.x, uvSize.y / szf.y);
        _yaScale = Vector2(0.5f, 0.5f);
        _yaScale = Vector2(1, 1);
        Vector2 s = getSize();
        setAnimFrame(frame);
        setSize(s);
    }
        TextureLine(spNativeTexture t)
        {
            setVerticalMode(Box9Sprite::TILING_FULL);
            setHorizontalMode(Box9Sprite::TILING_FULL);
            Sprite::setResAnim(DebugActor::resSystem->getResAnim("checker"));

            AnimationFrame f;
            Vector2 s = fitSize(itemSize, Vector2((float)t->getWidth(), (float)t->getHeight()));

            setSize(s);

            Diffuse df;
            df.base = t;

            f.init(0, df, RectF(0, 0, 1.0f, 1.0f), RectF(0, 0, s.x, s.y), s);
            spSprite image = initActor(new Sprite,
                                       arg_blend = blend_disabled,
                                       arg_resAnim = f);
            addChild(image);

            spColorRectSprite rect = initActor(new ColorRectSprite,
                                               arg_color = Color(Color::White, 255),
                                               arg_attachTo = this);

            rect->addTween(Sprite::TweenColor(Color(Color::White, 0)), 4000, -1, true);

            char path[255];
            path::normalize(t->getName().c_str(), path);

            char txt[255];
            safe_sprintf(txt, "%s\n<div c=\"FF0000\">%s</div>-<div c=\"0000ff\">%dx%d</div>\nid: %d",
                         path,
                         textureFormat2String(t->getFormat()),
                         t->getWidth(), t->getHeight(), t->getObjectID());

            spTextField text = initActor(new TextField,
                                         arg_color = Color::Black,
                                         arg_w = (float)itemSize.x,
                                         arg_vAlign = TextStyle::VALIGN_TOP,
                                         arg_hAlign = TextStyle::HALIGN_LEFT,
                                         arg_multiline = true,
                                         arg_attachTo = rect,
                                         arg_htmlText = txt
                                        );

            text->setBreakLongWords(true);

            rect->setSize(text->getTextRect().size.cast<Vector2>() + Vector2(2, 2));
            rect->setY((itemSize.y - rect->getHeight()) / 2.0f);
        }
Esempio n. 11
0
	void Box9Sprite::animFrameChanged(const AnimationFrame &f)
	{
		_prepared = false;

		ResAnim *resanim = f.getResAnim();
		if (resanim)
		{
			float scaleFactor = resanim->getScaleFactor();

			pugi::xml_attribute attr = resanim->getAttribute("guideX1");
			if (!attr.empty())
				_guideX[0] = attr.as_float() * scaleFactor;

			attr = resanim->getAttribute("guideX2");
			if (!attr.empty())
				_guideX[1] = attr.as_float() * scaleFactor;

			attr = resanim->getAttribute("guideY1");
			if (!attr.empty())
				_guideY[0] = attr.as_float() * scaleFactor;

			attr = resanim->getAttribute("guideY2");
			if (!attr.empty())
				_guideY[1] = attr.as_float() * scaleFactor;

			attr = resanim->getAttribute("vertical");
			if (!attr.empty())
				_vertMode = (StretchMode)attr.as_uint();

			attr = resanim->getAttribute("horizontal");
			if (!attr.empty())
				_horzMode = (StretchMode)attr.as_uint();
		}
	}
Esempio n. 12
0
	void Sprite::setResAnim(const ResAnim *resanim)
	{
		if (resanim)
		{
			if (resanim->getTotalFrames()) 
				setAnimFrame(resanim);
			else
			{
				AnimationFrame fr;

				fr.init(0, Diffuse(), RectF(0,0,0,0), RectF(0,0,0,0), getSize());
				setAnimFrame(fr);
			}
		}
		else
			setAnimFrame(AnimationFrame());
	}
    void Sprite::setAnimFrame(const ResAnim* resanim, int col, int row)
    {
        //OX_ASSERT(resanim);
        if (!resanim)
        {
            changeAnimFrame(AnimationFrame());
            return;
        }

        if (resanim->getTotalFrames())
        {
            const AnimationFrame& frame = resanim->getFrame(col, row);
            changeAnimFrame(frame);
        }
        else
        {
            AnimationFrame frame;
            frame.setSize(getSize());
            changeAnimFrame(frame);
        }
    }
    /// Interpolate animation frame from two other frames.
    ///
    /// \param src Source frame (earlier).
    /// \param dst Destination frame (later).
    /// \param current_time Animation time.
    void interpolateFrom(const AnimationFrame &lhs, const AnimationFrame &rhs, float current_time)
    {
      unsigned bone_count = lhs.getBoneCount();
#if defined(USE_LD)
      if(rhs.getBoneCount() != bone_count)
      {
        std::ostringstream sstr;
        sstr << "cannot interpolate between frames of size " << bone_count << " and " << rhs.getBoneCount();
        BOOST_THROW_EXCEPTION(std::runtime_error(sstr.str()));
      }
#endif

      //std::cout << "resizing bones or not? " << m_bones.size() << " vs " << bone_count << std::endl;

      m_time = current_time;
      m_bones.resize(bone_count);

      for(unsigned ii = 0; (bone_count > ii); ++ii)
      {
        const BoneState &ll = lhs.getBoneState(ii);
        const BoneState &rr = rhs.getBoneState(ii);
        float ltime = lhs.getTime();
        float rtime = rhs.getTime();
        float mix_time = (current_time - ltime) / (rtime - ltime);
        vec3 mix_pos = mix(ll.getPosition(), rr.getPosition(), mix_time);
        quat mix_rot = mix(ll.getRotation(), rr.getRotation(), mix_time);

        //std::cout << "mix time: " << mix_time << ": " << mix_pos << " ; " << mix_rot << std::endl;

        m_bones[ii] = BoneState(mix_pos, mix_rot);
      }
    }
    void TreeInspectorPreview::init(spActor item)
    {
        //_item = item;
        STDRenderer r(&_videoCache);
        RenderState rs;
        rs.renderer = &r;
        rs.transform = item->getTransform();
        r.begin(0);
        //r.setTransform(rs.transform);
        item->doRender(rs);
        r.end();
        r.drawBatch();

        setSize(30, 30);

        RectF itemRect = _videoCache._bounds;
        if (itemRect.isEmpty())
        {
            itemRect = item->getDestRect();
            if (itemRect.isEmpty())
                itemRect.setSize(Vector2(10, 4));
        }

        Vector2 ns = fitSize(Vector2(50.0f, 50.0f), itemRect.size);
        float scale = ns.x / itemRect.size.x;

        _cacheTransform.identity();

        _cacheTransform.scale(Vector2(scale, scale));
        _cacheTransform.translate(-itemRect.pos);



        AnimationFrame fr = _tree->_resSystem->getResAnim("checker")->getFrame(0, 0);
        //Point itemSize(30, 30);// = _getItemRect().size;

        RectF srcRect = fr.getSrcRect();
        const Diffuse& df = fr.getDiffuse();
        srcRect.size.x = ns.x / (float)df.base->getWidth();
        srcRect.size.y = ns.y / (float)df.base->getHeight();
        RectF destRect = fr.getDestRect();
        destRect.size = ns;

        AnimationFrame cfr;
        cfr.init(0, df, srcRect, destRect, ns);

        setAnimFrame(cfr);


        /*
        spEventHandler bh = new EventHandler();

        bh->setCallbackEnter(CLOSURE(this, &TreeInspectorPreview::_onEvent));
        bh->setCallbackExit(CLOSURE(this, &TreeInspectorPreview::_onEvent));
        bh->setCallbackPressDown(CLOSURE(this, &TreeInspectorPreview::_onEvent));
        bh->setCallbackPressUp(CLOSURE(this, &TreeInspectorPreview::_onEvent));
        addEventHandler(bh);
        */
    }
Esempio n. 16
0
    void ResAnim::init(spNativeTexture texture, const Point& originalSize, int columns, int rows, float scaleFactor)
    {
        _scaleFactor = scaleFactor;
        if (!texture)
            return;

        int frame_width = originalSize.x / columns;
        int frame_height = originalSize.y / rows;

        animationFrames frames;
        int frames_count = rows * columns;
        frames.reserve(frames_count);

        Vector2 frameSize((float)frame_width, (float)frame_height);
        for (int y = 0; y < rows; ++y)
        {
            for (int x = 0; x < columns; ++x)
            {
                Rect src;
                src.pos = Point(x * frame_width, y * frame_height);
                src.size = Point(frame_width, frame_height);

                float iw = 1.0f / texture->getWidth();
                float ih = 1.0f / texture->getHeight();
                RectF srcRect(src.pos.x * iw, src.pos.y * ih, src.size.x * iw, src.size.y * ih);

                RectF destRect(Vector2(0, 0), frameSize * scaleFactor);
                AnimationFrame frame;
                Diffuse df;
                df.base = texture;
                frame.init(this, df, srcRect, destRect, destRect.size);
                frames.push_back(frame);
            }
        }

        init(frames, columns, scaleFactor);
    }
Esempio n. 17
0
void AnimationFrameView::setOnionSkinFrames()
{

    if(onionSkinBackward() > 0 && onionSkinForward()) {
        QList<AnimationFrame *> onionSkinFrames;
        int index = frame()->project()->frames().indexOf(frame());
        int beginOfOnionSkin = max(0, index-onionSkinBackward());
        int endOfOnionSkin = min(frame()->project()->frameCount(), index+onionSkinForward());
        if(endOfOnionSkin == frame()->project()->frameCount())
            endOfOnionSkin--;

        for(int i = beginOfOnionSkin; i < index; i++) {
            onionSkinFrames.push_back(frame()->project()->frame(i));
        }
        for(int i= index+1; i<= endOfOnionSkin; i++) {
            onionSkinFrames.push_back(frame()->project()->frame(i));
        }
        if(onionSkinFrames.size() > 0) {
            onionSkin = new QPixmap(frameItem->scene()->width(), frameItem->scene()->height());
            onionSkin->fill(Qt::transparent);
            QPainter *p = new QPainter(onionSkin);

            p->setOpacity(0.5);
            for (int i = 0; i < onionSkinFrames.size(); ++i) {
                AnimationFrame *f = onionSkinFrames.at(i);
                for (int j = f->layerCount() - 1; j >= 0; --j) {
                    const Layer *layer = f->layer(j);
                    const Canvas& canvas = (layer->canvas().pixmap());
                    p->drawPixmap(0, 0, canvas.pixmap());
                }
            }

            repaint();
        }
    }
}
Esempio n. 18
0
    void Sprite::changeAnimFrame(const AnimationFrame& frame)
    {
        if (_flags & flag_manageResAnim)
        {
            ResAnim* rs = _frame.getResAnim();
            if (rs)
                rs->getAtlas()->unload();

            rs = frame.getResAnim();
            if (rs)
                rs->getAtlas()->load();
        }

        bool flipX = (_flags & flag_flipX) != 0;
        bool flipY = (_flags & flag_flipY) != 0;
        if (flipX || flipY)
            _frame = frame.getFlipped(flipY, flipX);
        else
            _frame = frame;
        _setSize(_frame.getSize().mult(_localScale));


        animFrameChanged(_frame);
    }
    void Sprite::changeAnimFrame(const AnimationFrame& frame)
    {
        if (_flags & flag_manageResAnim)
        {
            ResAnim* rs = _frame.getResAnim();
            if (rs)
                rs->getAtlas()->unload();

            rs = frame.getResAnim();
            if (rs)
                rs->getAtlas()->load();
        }

        _frame = frame;
        setSize(_frame.getSize());

        animFrameChanged(_frame);
    }
Esempio n. 20
0
        void TransitionQuads::_run(spScene current, spScene next, bool back)
        {
            Point ds = core::getDisplaySize();
            spActor holder = new Actor;
            holder->setPosition(getStage()->global2local(Vector2(0, 0)));
            //holder->setVisible(false);
            holder->setSize(core::getDisplaySize());
            holder->attachTo(getStage());
            holder->setPriority(1000);

            int numX = ds.x / 40;
            int numY = ds.y / 40;

            //log::messageln("tq1");
            Vector2 quad(holder->getWidth() / numX, holder->getHeight() / numY);
            spTween slowestTween;

            for (int y = 0; y < numY; ++y)
            {
                for (int x = 0; x < numX; ++x)
                {
                    spSprite sp = new ColorRectSprite;
                    Vector2 pos(quad.x * x, quad.y * y);
                    pos += quad / 2;
                    sp->setPosition(pos);
                    sp->setAnchor(Vector2(0.5f, 0.5f));
                    sp->setSize(quad);
                    sp->attachTo(holder);
                    sp->setScale(0);
                    sp->setColor(Color(0xffffffff));
                    Vector2 d = pos - _center;
                    float time = d.length() / holder->getSize().length();
                    /*
                    if (back)
                    time = 1.0f - time;
                    */

                    float mp = 4.0f;
                    //mp = 10;
                    int tm = int(1 + time * 800 * mp);
                    spTween nt = sp->addTween(Actor::TweenScale(1.0f), int(100 * mp), 1, false, tm);
                    if (!slowestTween || (int)slowestTween->getDelay() < tm)
                        slowestTween = nt;
                }
            }

            //log::messageln("tq2");


#if OXYGINE_RENDERER <= 2

            STDRenderer r;
            RenderState rs;
            rs.renderer = &r;
            rs.renderer->initCoordinateSystem(ds.x, ds.y, true);

            spNativeTexture mask = IVideoDriver::instance->createTexture();
            mask->init(ds.x, ds.y, TF_R5G5B5A1, true);

            _mask = mask;


            spSprite maskSprite = new Sprite;
            {
                AnimationFrame fr;
                Diffuse df;
                df.base = mask;
                RectF srcRect(0, 0, (float)ds.x / mask->getWidth(), (float)ds.y / mask->getHeight());
                RectF destRect(Vector2(0, 0), ds);
                fr.init(0, df, srcRect, destRect, ds);
                maskSprite->setAnimFrame(fr);
            }

            //log::messageln("tq3");

            //#define BUG
            //STDMaterial
            spMaskedSprite bg = new MaskedSprite;
            bg->setMask(maskSprite);

            bg->attachTo(getStage());
            bg->setPriority(100);


            bg->addChild(next->getHolder());
            bg->setInputEnabled(false);
            _bg = bg;

            timeMS tm = getTimeMS() + 3000;

            holder->setCallbackDoUpdate(CLOSURE(this, &TransitionQuads::update));



            //_r = r;
            _holder = holder;
            waitTween(slowestTween);
#endif
        }
    void ResAtlasGeneric::loadAtlas2(CreateResourceContext& context)
    {
        _current = 0;
        pugi::xml_node node = context.walker.getNode();

        int w = node.attribute("width").as_int(defaultAtlasWidth);
        int h = node.attribute("height").as_int(defaultAtlasHeight);

        const char* format = node.attribute("format").as_string("8888");

        loadBase(node);

        atlas_data ad;


        TextureFormat tf = string2TextureFormat(format);


        bool compressed = false;


        std::vector<ResAnim*> anims;


        while (true)
        {
            XmlWalker walker = context.walker.next();
            if (walker.empty())
                break;

            pugi::xml_node child_node = walker.getNode();

            const char* name = child_node.name();
            if (strcmp(name, "image"))
                continue;


            std::string id = child_node.attribute("id").value();
            std::string file = child_node.attribute("file").value();

            if (file.empty())
            {
                createEmpty(walker, context);
                continue;
            }


            bool trim = child_node.attribute("trim").as_bool(true);
            bool extend = child_node.attribute("extend").as_bool(true);

            Point offset = extend ? Point(2, 2) : Point(0, 0);

            MemoryTexture mt;
            ImageData im;

            int columns = 0;
            int rows = 0;
            int frame_width = 0;
            int frame_height = 0;
            float frame_scale = 1.0f;
            bool loaded = false;


            file::buffer bf;
            file::read(walker.getPath("file"), bf);

            mt.init(bf, true, tf);
            im = mt.lock();
            if (im.w)
            {
                rows = child_node.attribute("rows").as_int();
                frame_width = child_node.attribute("frame_width").as_int();
                columns = child_node.attribute("cols").as_int();
                frame_height = child_node.attribute("frame_height").as_int();

                if (!rows)
                    rows = 1;

                if (!columns)
                    columns = 1;

                if (frame_width)
                    columns = im.w / frame_width;
                else
                    frame_width = im.w / columns;


                if (frame_height)
                    rows = im.h / frame_height;
                else
                    frame_height = im.h / rows;
            }


            if (columns)
            {
                animationFrames frames;
                int frames_count = rows * columns;
                frames.reserve(frames_count);

                ResAnim* ra = new ResAnim(this);


                anims.push_back(ra);

                for (int y = 0; y < rows; ++y)
                {
                    for (int x = 0; x < columns; ++x)
                    {
                        Rect frameRect;
                        frameRect.pos = Point(x * frame_width, y * frame_height);
                        frameRect.size = Point(frame_width, frame_height);

                        ImageData srcImage_ = im.getRect(frameRect);


                        HitTestData adata;
                        ImageData src;
                        Rect bounds(0, 0, im.w, im.h);
                        if (trim)
                            makeAlpha(srcImage_, bounds, _hitTestBuffer, adata, walker.getAlphaHitTest());
                        src = srcImage_.getRect(bounds);

                        Rect dest(0, 0, 0, 0);

                        if (!ad.texture)
                        {
                            std::string atlas_id = getName();
                            nextAtlas(w, h, tf, ad, atlas_id.c_str());
                        }

                        bool s = ad.atlas.add(&ad.mt, src, dest, offset);
                        if (s == false)
                        {
                            applyAtlas(ad, _linearFilter, _clamp2edge);

                            nextAtlas(w, h, tf, ad, walker.getCurrentFolder().c_str());
                            s = ad.atlas.add(&ad.mt, src, dest, offset);
                            OX_ASSERT(s);
                        }

                        //extend = false;
                        if (extend)
                        {
                            //duplicate image edges
                            MemoryTexture& mt = ad.mt;
                            ImageData tmp;

                            if (bounds.getY() == 0 && dest.pos.y != 0)
                            {
                                tmp = mt.lock(Rect(dest.pos.x, dest.pos.y - 1, src.w, 1));
                                operations::copy(src.getRect(Rect(0, 0, src.w, 1)), tmp);
                            }

                            if (bounds.getHeight() == im.h && dest.getBottom() != mt.getHeight())
                            {
                                tmp = mt.lock(Rect(dest.pos.x, dest.pos.y + src.h, src.w, 1));
                                operations::copy(src.getRect(Rect(0, src.h - 1, src.w, 1)), tmp);
                            }

                            if (bounds.getX() == 0 && dest.pos.x != 0)
                            {
                                tmp = mt.lock(Rect(dest.pos.x - 1, dest.pos.y, 1, src.h));
                                operations::copy(src.getRect(Rect(0, 0, 1, src.h)), tmp);
                            }

                            if (bounds.getWidth() == im.w && dest.getRight() != mt.getWidth())
                            {
                                tmp = mt.lock(Rect(dest.pos.x + src.w, dest.pos.y, 1, src.h));
                                operations::copy(src.getRect(Rect(src.w - 1, 0, 1, src.h)), tmp);
                            }
                        }


                        //operations::copy(src.getRect(Rect(0, 0, 1, 1)), mt.lock(&Rect(dest.pos.x - 1, dest.pos.y - 1, 1, 1)));
                        //operations::copy(src.getRect(Rect(src.w - 1, 0, 1, 1)), mt.lock(&Rect(dest.pos.x + src.w, dest.pos.y - 1, 1, 1)));

                        //operations::copy(src.getRect(Rect(0, src.h - 1, 1, 1)), mt.lock(&Rect(dest.pos.x - 1, dest.pos.y + src.h, 1, 1)));
                        //operations::copy(src.getRect(Rect(src.w - 1, src.h - 1, 1, 1)), mt.lock(&Rect(dest.pos.x + src.w, dest.pos.y + src.h, 1, 1)));


                        float iw = 1.0f;
                        float ih = 1.0f;

                        RectF srcRect(dest.pos.x * iw, dest.pos.y * ih, dest.size.x * iw, dest.size.y * ih);

                        Vector2 sizeScaled = Vector2((float)dest.size.x, (float)dest.size.y) * walker.getScaleFactor();
                        RectF destRect(bounds.pos.cast<Vector2>(), sizeScaled);

                        AnimationFrame frame;
                        Diffuse df;
                        df.base = ad.texture;
                        df.premultiplied = true;//!Renderer::getPremultipliedAlphaRender();

                        Vector2 fsize = Vector2((float)frame_width, (float)frame_height) * walker.getScaleFactor();
                        frame.init2(ra, x, y, df,
                                    srcRect, destRect, fsize);

                        frame.setHitTestData(adata);

                        frames.push_back(frame);
                    }
                }

                init_resAnim(ra, file, child_node);

                ra->init(frames, columns, walker.getScaleFactor(), 1.0f / walker.getScaleFactor());
                ra->setParent(this);
                context.resources->add(ra, context.options->_shortenIDS);
            }

        }

        applyAtlas(ad, _linearFilter, _clamp2edge);

        for (std::vector<ResAnim*>::iterator i = anims.begin(); i != anims.end(); ++i)
        {
            ResAnim* rs = *i;
            int num = rs->getTotalFrames();

            for (int n = 0; n < num; ++n)
            {
                AnimationFrame& frame = const_cast<AnimationFrame&>(rs->getFrame(n));

                float iw = 1.0f / frame.getDiffuse().base->getWidth();
                float ih = 1.0f / frame.getDiffuse().base->getHeight();

                RectF rect = frame.getSrcRect();
                rect.pos.x *= iw;
                rect.pos.y *= ih;
                rect.size.x *= iw;
                rect.size.y *= ih;
                frame.setSrcRect(rect);

                HitTestData ad = frame.getHitTestData();
                if (ad.pitch)
                {
                    ad.data = &_hitTestBuffer[reinterpret_cast<size_t>(ad.data)];
                    frame.setHitTestData(ad);
                }
            }
        }
    }
void IFPAnimationViewerWidget::updateFrameDisplay()
{
	if (!displayedFrame)
		return;

	AnimationBone* bone = NULL;

	if (currentAnim)
		bone = currentAnim->getBoneForFrame(displayedFrame);

	renderWidget->setCurrentBone(displayedFrame->getName());
	renderWidget->updateDisplay();

	if (bone) {
		AnimationFrame* f1;
		AnimationFrame* f2;
		float t;

		bone->getFrames(currentTime, f1, f2, t);

		AnimationFrame* f = bone->getInterpolatedFrame(currentTime);

		ui.ipFactorLabel->setText(QString("%1").arg(t));

		Quaternion f1r = f1->getRotation();
		Vector3 f1t = f1->getTranslation();
		Vector3 f1s = f1->getScale();
		ui.f1RotationLabel->setText(tr("(%1, %2, %3, %4)")
				.arg(f1r.getW()).arg(f1r.getX()).arg(f1r.getY()).arg(f1r.getZ()));
		ui.f1TranslationLabel->setText(tr("(%1, %2, %3)")
				.arg(f1t.getX()).arg(f1t.getY()).arg(f1t.getZ()));
		ui.f1ScaleLabel->setText(tr("(%1, %2, %3)")
				.arg(f1s.getX()).arg(f1s.getY()).arg(f1s.getZ()));
		ui.f1TimeLabel->setText(QString("%1").arg(f1->getStart()));

		Quaternion f2r = f2->getRotation();
		Vector3 f2t = f2->getTranslation();
		Vector3 f2s = f2->getScale();
		ui.f2RotationLabel->setText(tr("(%1, %2, %3, %4)")
				.arg(f2r.getW()).arg(f2r.getX()).arg(f2r.getY()).arg(f2r.getZ()));
		ui.f2TranslationLabel->setText(tr("(%1, %2, %3)")
				.arg(f2t.getX()).arg(f2t.getY()).arg(f2t.getZ()));
		ui.f2ScaleLabel->setText(tr("(%1, %2, %3)")
				.arg(f2s.getX()).arg(f2s.getY()).arg(f2s.getZ()));
		ui.f2TimeLabel->setText(QString("%1").arg(f2->getStart()));

		Quaternion ifr = f->getRotation();
		Vector3 ift = f->getTranslation();
		Vector3 ifs = f->getScale();
		ui.ipRotationLabel->setText(tr("(%1, %2, %3, %4)")
				.arg(ifr.getW()).arg(ifr.getX()).arg(ifr.getY()).arg(ifr.getZ()));
		ui.ipTranslationLabel->setText(tr("(%1, %2, %3)")
				.arg(ift.getX()).arg(ift.getY()).arg(ift.getZ()));
		ui.ipScaleLabel->setText(tr("(%1, %2, %3)")
				.arg(ifs.getX()).arg(ifs.getY()).arg(ifs.getZ()));
		ui.ipTimeLabel->setText(QString("%1").arg(f->getStart()));
	} else {
		ui.ipFactorLabel->setText(tr("-"));

		ui.f1RotationLabel->setText(tr("-"));
		ui.f1TranslationLabel->setText(tr("-"));
		ui.f1ScaleLabel->setText(tr("-"));
		ui.f1TimeLabel->setText(tr("-"));

		ui.f2RotationLabel->setText(tr("-"));
		ui.f2TranslationLabel->setText(tr("-"));
		ui.f2ScaleLabel->setText(tr("-"));
		ui.f2TimeLabel->setText(tr("-"));

		ui.ipRotationLabel->setText(tr("-"));
		ui.ipTranslationLabel->setText(tr("-"));
		ui.ipScaleLabel->setText(tr("-"));
		ui.ipTimeLabel->setText(tr("-"));
	}
}
	void ResStarlingAtlas::loadAtlas(CreateResourceContext &context)
	{
		const char *xml_name = context.node.attribute("file").value();

		string xml_path = *context.folder + xml_name;		


		file::buffer fb;
		file::read(xml_path.c_str(), fb);

		pugi::xml_document doc;
		doc.load_buffer_inplace(&fb.data[0], fb.data.size());

		pugi::xml_node starling_xml = doc.first_child();
		_imagePath = *context.folder + starling_xml.attribute("imagePath").value();

		_texture = IVideoDriver::instance->createTexture();

		if (context.meta)
		{
			int textureWidth = context.meta.attribute("tw").as_int();
			int textureHeight = context.meta.attribute("th").as_int();
			_texture->init(0, textureWidth, textureHeight, TF_R8G8B8A8);
		}
		else
		{
			spMemoryTexture mt = new MemoryTexture;

			ImageData im;
			file::buffer bf;
			file::read(_imagePath.c_str(), bf);

			mt->init(bf, true, _texture->getFormat());
			im = mt->lock();
			_texture->init(mt->lock(), false);
		}
		

		float iw = 1.0f / _texture->getWidth();
		float ih = 1.0f / _texture->getHeight();

		ResAnim *resAnim = 0;
		pugi::xml_node sub = starling_xml.first_child();

		animationFrames frames;

		while (sub)
		{
			const char *name = sub.attribute("name").value();
			int index_pos = strlen(name) - 4;
			const char *index = name + index_pos;
			char id[255];
			strcpy(id, name);
			id[index_pos] = 0;

			int frame_index = atoi(index);

			//todo optimize attributes 
			int x = sub.attribute("x").as_int();
			int y = sub.attribute("y").as_int();
			int width = sub.attribute("width").as_int();
			int height = sub.attribute("height").as_int();

			int frameX = sub.attribute("frameX").as_int();
			int frameY = sub.attribute("frameY").as_int();
			int frameWidth = sub.attribute("frameWidth").as_int(width);
			int frameHeight = sub.attribute("frameHeight").as_int(height);

			if (!resAnim || resAnim->getName() != id)
			{
				if (resAnim)
				{
					resAnim->init(frames, frames.size());
					context.resources->add(resAnim);
					frames.clear();
				}

				resAnim = new ResAnim(this);
				setNode(resAnim, context.node);
				resAnim->setName(id);
			}

			AnimationFrame frame;
			RectF srcRect(x * iw, y * ih, width * iw, height * ih);
			RectF destF = Rect(-frameX, -frameY, width, height).cast<RectF>();

			Diffuse df;
			df.base = _texture;
			frame.init(resAnim, df, srcRect, destF, Vector2((float)frameWidth, (float)frameHeight));
			frames.push_back(frame);

			sub = sub.next_sibling();
		}

		if (resAnim)
		{
			resAnim->init(frames, frames.size());
			context.resources->add(resAnim);
		}


	}
    void ResStarlingAtlas::loadAtlas(CreateResourceContext& context)
    {
        std::string xml_path = context.walker.getPath("file");

        file::buffer fb;
        file::read(xml_path, fb);

        pugi::xml_document doc;
        doc.load_buffer_inplace(&fb.data[0], fb.data.size());

        pugi::xml_node starling_xml = doc.first_child();

        pugi::xml_node root = doc.root().first_child();
        const std::string& img = root.attribute("imagePath").as_string();

        char head[255];
        char tail[255];
        path::split(xml_path.c_str(), head, tail);
        _imagePath = std::string(head) + img;

        _texture = IVideoDriver::instance->createTexture();

        pugi::xml_node meta = context.walker.getMeta();

        if (!meta.empty())
        {
            int textureWidth = meta.attribute("tw").as_int();
            int textureHeight = meta.attribute("th").as_int();
            _texture->init(0, textureWidth, textureHeight, TF_R8G8B8A8);
        }
        else
        {

            unsigned char buff[64];
            unsigned int size = 0;
            {
                file::autoClose ac(file::open(_imagePath, "rb"));
                size = file::read(ac.getHandle(), buff, sizeof(buff));
            }

            int width = 0;
            int height = 0;
            ImageType type;

            if (getImageInfo(buff, size, img.c_str(), type, width, height))
            {
                _texture->init(0, width, height, TF_R8G8B8A8);
            }
            else
            {
                spMemoryTexture mt = new MemoryTexture;

                ImageData im;
                file::buffer bf;
                file::read(_imagePath, bf);

                mt->init(bf, true, _texture->getFormat());
                im = mt->lock();
                _texture->init(mt->lock(), false);
            }
        }


        float iw = 1.0f / _texture->getWidth();
        float ih = 1.0f / _texture->getHeight();

        ResAnim* resAnim = 0;
        pugi::xml_node sub = starling_xml.first_child();

        animationFrames frames;

        while (sub)
        {
            const char* name = sub.attribute("name").value();

            char id[255];
            strcpy(id, name);

            //int frame_index = atoi(index);

            //todo optimize attributes
            int x = sub.attribute("x").as_int();
            int y = sub.attribute("y").as_int();
            int width = sub.attribute("width").as_int();
            int height = sub.attribute("height").as_int();

            int frameX = sub.attribute("frameX").as_int();
            int frameY = sub.attribute("frameY").as_int();
            int frameWidth = sub.attribute("frameWidth").as_int(width);
            int frameHeight = sub.attribute("frameHeight").as_int(height);

            if (!resAnim || resAnim->getName() != id)
            {
                if (resAnim)
                {
                    resAnim->init(frames, (int)frames.size());
                    resAnim->setParent(this);
                    context.resources->add(resAnim);
                    frames.clear();
                }

                resAnim = new ResAnim(this);
                setNode(resAnim, context.walker.getNode());
                resAnim->setName(id);
            }

            AnimationFrame frame;
            RectF srcRect(x * iw, y * ih, width * iw, height * ih);
            RectF destF = Rect(-frameX, -frameY, width, height).cast<RectF>();

            Diffuse df;
            df.base = _texture;
            frame.init(resAnim, df, srcRect, destF, Vector2((float)frameWidth, (float)frameHeight));
            frames.push_back(frame);

            sub = sub.next_sibling();
        }

        if (resAnim)
        {
            resAnim->init(frames, (int)frames.size());
            resAnim->setParent(this);
            context.resources->add(resAnim);
        }
    }
	void ResAtlas::loadAtlas(CreateResourceContext &context)
	{
		//string path = context.walker.getCurrentFolder();

		pugi::xml_node node = context.walker.getNode(); 
		pugi::xml_node meta = context.walker.getMeta();

        int w = node.attribute("width").as_int(defaultAtlasWidth);
        int h = node.attribute("height").as_int(defaultAtlasHeight);
		const char *format = node.attribute("format").as_string("8888");

		atlas_data ad;


		TextureFormat tf = string2TextureFormat(format);

		pugi::xml_node meta_image = meta.child("atlas");
		
		bool compressed = false;

		while(meta_image)
		{
			const char *file = meta_image.attribute("file").value();

			int w = meta_image.attribute("w").as_int();
			int h = meta_image.attribute("h").as_int();

			const char *file_format = meta_image.attribute("format").as_string(0);
			TextureFormat ffmt = TF_UNDEFINED;
			if (file_format)
			{
				ffmt = string2TextureFormat(file_format);
				compressed = isCompressedFormat(ffmt);
			}

			std::string alpha_file = meta_image.attribute("alpha").as_string("");
			if (!alpha_file.empty())
			{
				alpha_file = *context.prebuilt_folder + alpha_file;
			}

			addAtlas(tf, *context.prebuilt_folder + file, alpha_file, w, h);

			meta_image = meta_image.next_sibling("atlas");
			context.walker.nextMeta();
		}

		//

		std::vector<ResAnim*> anims;
	
		
		while (true)
		{
			XmlWalker walker = context.walker.next();
			if (walker.empty())
				break;

			pugi::xml_node child_node = walker.getNode();
			pugi::xml_node meta_frames = walker.getMeta();

			const char *name = child_node.name();
			if (!strcmp(name, "image"))
			{
				std::string id = child_node.attribute("id").value();
				std::string file = child_node.attribute("file").value();

				if (file.empty())
				{
					ResAnim *ra = new ResAnim(this);
					ra->init(0, 0, 0, walker.getScaleFactor());
					init_resAnim(ra, file, child_node);
					ra->setParent(this);
					context.resources->add(ra);
					continue;
				}

				if (meta)
				{
					OX_ASSERT(meta_frames && "Did you recreate atlasses?");
				}
				
				MemoryTexture mt;
				ImageData im;

				int columns = 0;
				int rows = 0;
				int frame_width = 0;
				int frame_height = 0;
				float frame_scale = 1.0f;
				bool loaded = false;

				if (meta_frames  || meta)
				{
					const char *frame_size = meta_frames.attribute("fs").value();

					//int w = 0;
					//int h = 0;

					sscanf(frame_size, "%d,%d,%d,%d,%f", &columns, &rows, 
						&frame_width, &frame_height, 
						&frame_scale);
					loaded = true;
					//frame_scale = 0.
					//frame_scale /= walker.getScaleFactor();//todo! fix

					//im.w = w;
					//im.h = h;
				}
				else
				{
					file::buffer bf;
					file::read(walker.getPath("file").c_str(), bf);

					mt.init(bf, Renderer::getPremultipliedAlphaRender(), tf);
					im = mt.lock();
					if (im.w)
					{
						rows = child_node.attribute("rows").as_int();
						frame_width = child_node.attribute("frame_width").as_int();
						columns = child_node.attribute("cols").as_int();
						frame_height = child_node.attribute("frame_height").as_int();

						if (!rows)
							rows = 1;

						if (!columns)
							columns = 1;

						if (frame_width)
							columns = im.w / frame_width;				
						else
							frame_width = im.w / columns;


						if (frame_height)				
							rows = im.h / frame_height;
						else
							frame_height = im.h / rows;				

					}
				}

				if (columns)
				{
					animationFrames frames;
					int frames_count = rows * columns;
					frames.reserve(frames_count);
					
					ResAnim *ra = new ResAnim(this);

					if (meta)
					{
						OX_ASSERT(meta_frames);

						/*
						if (string(meta_frames.attribute("debug_image").as_string()) == "backleft.png")
						{

						}
						*/

						char *frames_data = (char*)meta_frames.first_child().value();

						const char *begin = frames_data;
						while(*frames_data)
						{
							if (*frames_data == ';')
							{
								*frames_data = 0;
								int id = 0;
								int x = 0;
								int y = 0;

								int bbox_x = 0;
								int bbox_y = 0;
								int bbox_w = 0;
								int bbox_h = 0;

								sscanf(begin, "%d,%d,%d,%d,%d,%d,%d", &id, &x, &y, &bbox_x, &bbox_y, &bbox_w, &bbox_h);

								begin = frames_data + 1;

								spNativeTexture &texture = _atlasses[id].base;
								spNativeTexture &alpha = _atlasses[id].alpha;

								float iw = 1.0f / texture->getWidth();
								float ih = 1.0f / texture->getHeight();

								RectF srcRect(x * iw, y * ih, bbox_w * iw, bbox_h * ih);

								float fs = frame_scale;
								RectF destRect(
									Vector2((float)bbox_x, (float)bbox_y) * fs,
									Vector2((float)bbox_w, (float)bbox_h) * fs
									);

								AnimationFrame frame;
								Diffuse df;
								df.base = texture;
								df.alpha = alpha;
								//compressed data could not be premultiplied 
								if (Renderer::getPremultipliedAlphaRender())
									df.premultiplied = !compressed;
								else
									df.premultiplied = true;//render should think that it is already premultiplied and don't worry about alpha

								frame.init(ra, df,
									srcRect, destRect, 
									Vector2((float)frame_width, (float)frame_height));

								frames.push_back(frame);
								if((int)frames.size() >= frames_count)
									break;
							}

							++frames_data;
						}
					}
					else
					{
						anims.push_back(ra);

						for (int y = 0; y < rows; ++y)
						{
							for (int x = 0; x < columns; ++x)
							{
								Rect src;
								src.pos = Point(x * frame_width, y * frame_height);
								src.size = Point(frame_width, frame_height);

								ImageData srcImage = im.getRect(src);

								Rect dest(0,0,0,0);

								if (!ad.texture)
								{
									std::string atlas_id = getName();
									next_atlas(w, h, tf, ad, atlas_id.c_str());
								}

								bool s = ad.atlas.add(&ad.mt, srcImage, dest);
								if (s == false)
								{
									apply_atlas(ad);
									next_atlas(w, h, tf, ad, walker.getCurrentFolder().c_str());
									s = ad.atlas.add(&ad.mt, srcImage, dest);
									OX_ASSERT(s);
								}

								/*
								float iw = 1.0f / ad.mt.getWidth();
								float ih = 1.0f / ad.mt.getHeight();
								*/

								float iw = 1.0f;
								float ih = 1.0f;
								
								RectF srcRect(dest.pos.x * iw, dest.pos.y * ih, dest.size.x * iw, dest.size.y * ih);

								Vector2 sizeScaled = Vector2((float)dest.size.x, (float)dest.size.y) * walker.getScaleFactor();
								RectF destRect(Vector2(0, 0), sizeScaled);

								AnimationFrame frame;
								Diffuse df;
								df.base = ad.texture;
								df.premultiplied = true;//!Renderer::getPremultipliedAlphaRender();
								frame.init(ra, df, srcRect, destRect, Vector2((float)frame_width, (float)frame_height) * walker.getScaleFactor());
								frames.push_back(frame);
							}
						}
					}	


					
					init_resAnim(ra, file, child_node);
					
					ra->init(frames, columns, walker.getScaleFactor());					
					ra->setParent(this);
					context.resources->add(ra);
				}
			}
		}

		apply_atlas(ad);

		for (std::vector<ResAnim*>::iterator i = anims.begin(); i != anims.end(); ++i)
		{
			ResAnim *rs = *i;
			int num = rs->getTotalFrames();

			for (int n = 0; n < num; ++n)
			{
				AnimationFrame &frame = const_cast<AnimationFrame&>(rs->getFrame(n));
				
				float iw = 1.0f / frame.getDiffuse().base->getWidth();
				float ih = 1.0f / frame.getDiffuse().base->getHeight();

				RectF rect = frame.getSrcRect();
				rect.pos.x *= iw;
				rect.pos.y *= ih;
				rect.size.x *= iw;
				rect.size.y *= ih;
				frame.setSrcRect(rect);
			}
		}
	}