9.【cocos2d-x 源码分析】:Texture的详细分析

对应源码位置:cocos2d-x-3.3\cocos\render\CCTexture*
从Sprite谈起

Sprite其实内部必然包含一个纹理图片,但我们写代码时候用到的是传入一个图片路径,从下面看:

//直接 传入Texture2D 对象
Sprite* Sprite::createWithTexture(Texture2D *texture)
{
   
    Sprite *sprite = new (std::nothrow) Sprite();
    if (sprite && sprite->initWithTexture(texture))
    {
   
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}
//直接 传入Texture2D 对象
Sprite* Sprite::createWithTexture(Texture2D *texture, const Rect& rect, bool rotated)
{
   
    Sprite *sprite = new (std::nothrow) Sprite();
    if (sprite && sprite->initWithTexture(texture, rect, rotated))
    {
   
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}
//传入路径
Sprite* Sprite::create(const std::string& filename)
{
   
    Sprite *sprite = new (std::nothrow) Sprite();
    if (sprite && sprite->initWithFile(filename))
    {
   
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}

Sprite* Sprite::create(const std::string& filename, const Rect& rect)
{
   
    Sprite *sprite = new (std::nothrow) Sprite();
    if (sprite && sprite->initWithFile(filename, rect))
    {
   
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}
//直接 传入SpriteFrame 对象
Sprite* Sprite::createWithSpriteFrame(SpriteFrame *spriteFrame)
{
   
    Sprite *sprite = new (std::nothrow) Sprite();
    if (sprite && spriteFrame && sprite->initWithSpriteFrame(spriteFrame))
    {
   
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}

Sprite* Sprite::createWithSpriteFrameName(const std::string& spriteFrameName)
{
   
    SpriteFrame *frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(spriteFrameName);
    
#if COCOS2D_DEBUG > 0
    char msg[256] = {
   0};
    sprintf(msg, "Invalid spriteFrameName: %s", spriteFrameName.c_str());
    CCASSERT(frame != nullptr, msg);
#endif
    
    return createWithSpriteFrame(frame);
}

Sprite* Sprite::create()
{
   
    Sprite *sprite = new (std::nothrow) Sprite();
    if (sprite && sprite->init())
    {
   
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}

bool Sprite::init(void)
{
   
    return initWithTexture(nullptr, Rect::ZERO );
}

bool Sprite::initWithTexture(Texture2D *texture)
{
   
    CCASSERT(texture != nullptr, "Invalid texture for sprite");

    Rect rect = Rect::ZERO;
    rect.size = texture->getContentSize();

    return initWithTexture(texture, rect);
}

bool Sprite::initWithTexture(Texture2D *texture, const Rect& rect)
{
   
    return initWithTexture(texture, rect, false);
}
//传入路径
bool Sprite::initWithFile(const std::string& filename)
{
   
    CCASSERT(filename.size()>0, "Invalid filename for sprite");
	//获取对应的 Texture2D 
    Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(filename);
    if (texture)
    {
   
        Rect rect = Rect::ZERO;
        rect.size = texture->getContentSize();
        return initWithTexture(texture, rect);
    }

    // don't release here.
    // when load texture failed, it's better to get a "transparent" sprite then a crashed program
    // this->release();
    return false;
}

bool Sprite::initWithFile(const std::string &filename, const Rect& rect)
{
   
    CCASSERT(filename.size()>0, "Invalid filename");
	//同理 获取Texture2D 
    Texture2D *texture = Director::getInstance()->getTextureCache()->addImage(filename);
    if (texture)
    {
   
        return initWithTexture(texture, rect);
    }

    // don't release here.
    // when load texture failed, it's better to get a "transparent" sprite then a crashed program
    // this->release();
    return false;
}

bool Sprite::initWithSpriteFrameName(const std::string& spriteFrameName)
{
   
    CCASSERT(spriteFrameName.size() > 0, "Invalid spriteFrameName");

    SpriteFrame *frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(spriteFrameName);
    return initWithSpriteFrame(frame);
}

bool Sprite::initWithSpriteFrame(SpriteFrame *spriteFrame)
{
   
    CCASSERT(spriteFrame != nullptr, "");
	//最终从 spriteFrame获取Texture2D 
    bool bRet = initWithTexture(spriteFrame->getTexture(), spriteFrame->getRect());
    setSpriteFrame(spriteFrame);

    return bRet;
}

//最终的初始化位置
bool Sprite::initWithTexture(Texture2D *texture, const Rect& rect, bool rotated)
TextureCache 类的分析
class CC_DLL TextureCache : public Ref
{
   
public:
  
    CC_DEPRECATED_ATTRIBUTE static TextureCache * getInstance();
public:
  	//根据文件 路径 添加图片 返回Texture2D
    Texture2D* addImage(const std::string &filepath);
	//在 单独线程中 加载图片
    virtual void addImageAsync(const std::string &filepath, const std::function<void(Texture2D*)>& callback);
   //添加的时候 传入Image   key
    Texture2D* addImage(Image *image, const std::string &key);
private:
    void addImageAsyncCallBack(float dt);
    void loadImage();

public:
	//异步 结构体 传入 文件名 以及 回调
    struct AsyncStruct
    {
   
    public:
        AsyncStruct(const std::string& fn, std::function<void(Texture2D*)> f) : filename(fn), callback(f) {
   }

        std::string filename;
        std::function<void(Texture2D*)> callback;
    };

protected:
	// 图片信息 文件名 回调 以及 image对象
    typedef struct _ImageInfo
    {
   
        AsyncStruct *asyncStruct;
        //后面细讲
        Image        *image;
    } ImageInfo;
    //用于 加载的线程
    std::thread* _loadingThread;
	
    std::queue<AsyncStruct*>* _asyncStructQueue;
    std::deque<ImageInfo*>* _imageInfoQueue;
	//两个 互斥量
    std::mutex _asyncStructQueueMutex;
    std::mutex _imageInfoMutex;

    std::mutex _sleepMutex;
    //条件变量
    std::condition_variable _sleepCondition;

    bool _needQuit;

    int _asyncRefCount;
	//最重要的 用于存储 Texture2D的map
    std::unordered_map<std::string, Texture2D*> _textures;
};

其中 addImage的实现

Texture2D * TextureCache::addImage(const std::string &path)
{
   
	//这两个 对象后面说
    Texture2D * texture = nullptr;
    Image* image = nullptr;
    // Split up directory and filename
    // MUTEX:
    // Needed since addImageAsync calls this method from a different thread
	//获取 全路径
    std::string fullpath = FileUtils::getInstance()->fullPathForFilename(path);
    if (fullpath.size() == 0)
    {
   
        return nullptr;
    }
    //先以全路径为 key 查找一下
    auto it = _textures.find(fullpath);
    //找到了 直接返回 这就是cache的作用
    if( it != _textures.end() )
        texture = it->second;
	//没找到
    if (! texture)
    {
   
        // all images are handled by UIImage except PVR extension that is handled by our own handler
        do 
        {
   
            image = new (std::nothrow) Image();
            CC_BREAK_IF(nullptr == image);
			//加载一下
            bool bRet = image->initWithImageFile(fullpath);
            CC_BREAK_IF(!bRet);
			//以Image初始化 texture 
            texture = new (std::nothrow) Texture2D();

            if( texture && texture->initWithImage(image) )
            {
   
#if CC_ENABLE_CACHE_TEXTURE_DATA
                // cache the texture file name
                //支持缓存  就存起来
                VolatileTextureMgr::addImageTexture(texture, fullpath);
#endif
                // texture already retained, no need to re-retain it
                //加入 map中
                _textures.insert( std::make_pair(fullpath, texture) );
            }
            else
            {
   
                CCLOG("cocos2d: Couldn't create texture for file:%s in TextureCache", path.c_str());
            }
        } while (0);
    }
	//没用了
    CC_SAFE_RELEASE(image);
	//返回 texture
    return texture;
}

Texture2D* TextureCache::addImage(Image *image, const std::string &key)
{
   
    CCASSERT(image != nullptr, "TextureCache: image MUST not be nil");

    Texture2D * texture = nullptr;
    do
    {
   
    //不同点在于 用的是key
        auto it = _textures.find(key);
        if( it != _textures.end() ) {
   
            texture = it->second;
            break;
        }

        // prevents overloading the autorelease pool
        //此时 已经有了Image 
        texture = new (std::nothrow) Texture2D();
        texture->initWithImage(image);

        if(texture)
        {
   
            _textures.insert( std::make_pair(key, texture) );
            texture->retain();

            texture->autorelease();
        }
        else
        {
   
            CCLOG("cocos2d: Couldn't add UIImage in TextureCache");
        }

    } while 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值