cocosBuilder + cocos2d-x-LuaProxy 解决在CCB编辑器中的label的多国语言文本替换

cocosBuilder + cocos2d-x-LuaProxy 解决在CCB编辑器中的label的多国语言文本替换


我们使用cocos2d-x + lua来开发游戏,同时使用cocosBuilder作为UI编辑器。在UI中需要放置label,例如CCLabelTTF,但是在编辑器中我们无法给他设定不同语言的文本。由于我们使用的是Lua,使用cocos2d-x-LuaProxy这个库来在lua中载入ccbi场景。因此基于之前的 "lua多国语言解决方案",并针对luaProxy做一些扩展,实现了一个CCB编辑器中label的多国语言文本替换方案。

基本的原理:在CCB编辑中对于想替换文本的label绑定变量名,这个变量名直接使用文本索引的名字(见lua多国语言文本解决方案,如string_hello)。在lua脚本中使用CCBProxy载入ccbi文件之后,对该场景中所有的member (CCBProxy中的member,其实就是绑定了变量名的对象)进行遍历,如果发现绑定了像"string_xxx"这样的变量名,就把这个对象找出来,转型为CCLableTTF并使用"lua多国语言文本解决方案"的方法设置当前语言的文本。

下面是我实现的一个方法,用来替换CCB中的label文本:
function replaceCCBText(ccbp)
    local members = ccbp:getMembers() --ccbp是一个CCBProxy对象,注意getMembers接口CCBProxy并没有提供,是我自己绑定的,下面会说
    local count = members:count()
    if count==0 then return end
    
    local text = require('text').get
    local keys = members:allKeys() --获取所有key,也就是绑定的变量名

    for i=0,count-1 do --注意lua数组索引1开始,但cocos2d-x的lua绑定中依然需要使用从0开始的数组索引,可能由于绑定代码是tolua++自动生成的因此没法转换吧
        local key = tolua.cast(keys:objectAtIndex(i),"CCString"):getCString()
        --log('key is ' .. key)
        local start = string.find(key,'string_') --是我们标记的特殊的变量名吗?
        if start==1 then
            local obj = members:objectForKey(key)
            obj = tolua.cast(obj,"CCLabelTTF") --取得对象并转型为CCLabelTTF
            if obj~=nil then
                local strId = _G[key] --取得这个变量对应的值,例如string_hello的值是1,注意我使用的是lua5.1,lua5.2据说环境有所改变,我还没研究过
                if strId==nil then
                    --log('warning! text index not found for %s',key)
                    obj:setString(key) --如果文本索引不存在,则直接将label设置为key的值,引起注意
                else
                    --log('replace string for key:%s,id:%d',key,strId)
                    obj:setString(text(strId)) --替换为该索引对应的当前语言的文本
                end
            end
        end
    end

end

使用情景:
--载入主菜单的ccbi
    local ccbp = CCBProxy:create()
    local n = ccbp:readCCBFromFile("mainmenu.ccbi")
    local scene = CCScene:create()
    scene:addChild(tolua.cast(n,"CCNode"))
--替换文本
replaceCCBText(ccbp)

几个问题:
1)从CCBProxy中获取所有绑定了变量的对象是使用CCBProxy::getMemberVariables,但是CCBProxy并没有绑定这个方法,因此我自己绑定了一下

tolua_CCBProxy.h中添加
//CCBProxy::getMemberVariables
static int tolua_CCBProxy_getMembers(lua_State *l){
#ifndef TOLUA_RELEASE
    tolua_Error err;
    if(!tolua_isusertype(l, 1, "CCBProxy", 0, &err)){
        tolua_error(l,"#ferror in function 'CCBProxy.getMembers'.",&err);
        return 0;
    }
#endif
    CCBProxy *p = (CCBProxy *)tolua_tousertype(l, 1, NULL);
    
    CCDictionary* tolua_ret = (CCDictionary*)p->getMemberVariables();
    int nID = (tolua_ret) ? (int)tolua_ret->m_uID : -1;
    int* pLuaID = (tolua_ret) ? &tolua_ret->m_nLuaID : NULL;
    toluafix_pushusertype_ccobject(l, nID, pLuaID, (void*)tolua_ret,"CCDictionary");
    
    return 1;
}

luaOpen_LuaProxy.cpp中在tolua_beginmodule(l,"CCBProxy");下面添加:
tolua_function(l, "getMembers", tolua_CCBProxy_getMembers);

2)我这边只使用了CCLabelTTF这个一种控件,并没有使用CCLabelBMFont,其实我之前是这么写的:

obj = tolua.cast(obj,"CCLabelTTF") or tolua.cast(obj,"CCLabelBMFont")
if obj~=nil then

如果我给一个CCLabelBMFont绑定了变量名,我希望这个地方能正确的cast为CCLabelBMFont对象,但实际情况是他cast为CCLabelTTF。为什么呢?因为但对象并不是CCLabelTTF时,tolua.cast(obj,"CCLabelTTF")并不会返回nil!看tolua的代码就可以发现他里面只是一个指针的强转,即便你写一个不存在的"CCLableXXX",也不会返回nil。这个地方没有报错(只是不起作用)的原因是CCLabelBMFont和CCLabelTTF都有setString方法。如果你换成"CCLabelXXX"就会报错setString为nil。

对于这个问题我暂时就是使用一种控件,因为还有问题(3)要解决。

3)有时候我们不光要根据语言换文本内容,可能还需要换字体,甚至换控件。例如对于英文我们可能会使用CCLabelBMFont,但是对于中文可能就只有CCLabelTTF。这个问题可以将原控件获取后进行替换解决,在replaceCCBText的基础上进行修改。当然如果每个控件都设置不同的字体就比较麻烦了,只能手工获取各别特殊的控件并且替换字体了(使用getNodeWithType)


你可能感兴趣的:(lua游戏开发)