cocos2d-x lua分支加载ccbi文件

cocos2d-x lua的分支竟然没有提供扩展包里面的类,苦大了我们啊, 经过各种尝试摸索,终于OK cocos2d-x <wbr>lua分支加载ccbi文件

不完美处就是留下一些使用的潜规则:
1、所有的控件名字不得重复(要根据控件名字注册lua的回调方法)
2、如果是成员变量名字格式为 空间名-空间类型 比如:second_text-CCLabelTTF
3、点击事件的lua回调方法名为 控件名_onClicked 比如:button_onClicked
4、所有的成员变量需要暴露给lua,通过lua的函数调用以传参的方式暴露 格式为 set_控件名例子:set_second_text

补充俩图看看cocosbuilder里面需要做的设置



剩下就是代码实现的机制了,先上代码,下面部分是要暴露给lua的,具体怎么暴露参看tolua++
CCNode* CCBIFactory::loadCCBI(CCScene *pScene, char* ccbiPath, char* loaderName){

    CCNodeLoaderLibrary * ccNodeLoaderLibrary = CCNodeLoaderLibrary::newDefaultCCNodeLoaderLibrary();

    CCNodeLoader*nodeLoader = GameUILoader::loader();

    ccNodeLoaderLibrary->registerCCNodeLoader(loaderName, nodeLoader);

    CCBReader * ccbReader = new CCBReader(ccNodeLoaderLibrary);

    CCNode * node = ccbReader->readNodeGraphFromFile(ccbiPath, this);

    ccbReader->autorelease();

    return node;

}


在下面就是CCBI所映射的类了,在C++中一个ccbi是对应着一个类存在的,里面包含了所有控件回调的注册,实例是在解析ccbi文件的时候创建的,如果要用C++ lua 的情况下肯定不能为每个ccbi都创建一个类,所以就需要一个通用格式的类定义,需要解决的问题有一下几点

1、要把所有可点击控件的点击事件转到lua的函数中,在回调里目前无法获取到被点击对象的标识,换句话说,根本不知道哪个控件点击的,C++中是根据不同的回调函数来区分的,但是要在头文件中把相应方法定义好,既然要通用,肯定不能确定该有多少个控件,这步就卡这了。我们的解决方案是把所有的控件全部在onAssignCCBMemberVariable执行的时候记录下来m_uid 和控件名,把这两个值存到map结构里面,根据m_uid来区分谁触发的点击事件,点击事件触发后由C++根据map结构中的值查询出控件名字,然后调用lua中按照此控件名字命名的函数,剩下的就交给lua了。

2、成员变量绑定的控件要导出到lua中,这点也挺恶心,因为不知道有多少个,不能直接在头文件定义,而且还获取不到控件类型。解决方法喝上一步差不多,我们是在所有这种控件的名字后面加上 -类型 比如:second_text-CCLabelTTF ,然后程序也是在onAssignCCBMemberVariable方法执行的时候调用lua里面和空间名字相同的函数把对象给暴露出去比如控件名是second_text-CCLabelTTF,那个回调函数为set_second_test(obj),  obj为CCLabelTTF的对象


废话不多说了,上代码:

#include "GameUILayer.h"
#include "CCLuaEngine.h"

USING_NS_CC;
USING_NS_CC_EXT;

using namespace std;

void GameUILayer::onNodeLoaded(cocos2d::CCNode * pNode,  cocos2d::extension::CCNodeLoader * pNodeLoader) {
}

SEL_MenuHandler GameUILayer::onResolveCCBCCMenuItemSelector(CCObject * pTarget, CCString * pSelectorName) {
    return NULL;
}

SEL_CCControlHandler GameUILayer::onResolveCCBCCControlSelector(CCObject * pTarget, CCString * pSelectorName) {
    string name = pSelectorName->getCString();     // 控件名字
     CCB_SELECTORRESOLVER_CCCONTROL_GLUE(this, name.c_str(), GameUILayer::onClicked);
    return NULL;
}

bool GameUILayer::onAssignCCBMemberVariable(CCObject * pTarget, CCString * pMemberVariableName, CCNode * pNode) {
    CCNode *button = NULL;
    string name = pMemberVariableName->getCString();
    XIAOLEI_CCB_MEMBERVARIABLEASSIGNER_GLUE(this, name.c_str(), CCNode *, button);
    int index = name.find_first_of('-', 0);
    if (index != string::npos)
    {
        char* funcName = (char*) (("set_" + name.substr(0,index)).c_str());
        char* typeName = (char*) name.substr(index+1).c_str();
        CCLuaEngine* pEngine = CCLuaEngine::defaultEngine();
        pEngine->registerCCBIMember(funcName, button, typeName);     // 这个函数是我们改动cocos2d源码增加的,很简单就是调用lua的函数并且传过去一个CCObject的对象作为参数
    }
    objectNameMapping.insert(map<int, string>::value_type(button->m_uID, name));     // 注册m_uid和控件名的绑定
    return false;
}

void GameUILayer::onClicked(CCObject * pSender, cocos2d::extension::CCControlEventpCCControlEvent) {
// 所有控件统一注册这一个回调函数
    map<int, string>::iterator iter = objectNameMapping.find(pSender->m_uID);
    if(iter != objectNameMapping.end())
    {
        CCLuaEngine* pEngine = CCLuaEngine::defaultEngine();
        pEngine->executeGlobalFunction((iter->second+"_onClicked").c_str());     // 根据控件名调用相应的lua方法
    }
}

头文件什么的就不提供了,想要正常运行还要实现以下registerCCBIMember 这个方法,这点就不用说了吧.

贴出lua代码(主要代码)

hello.lua

require "Utils"
require "first"
require "second"

sceneGame = CCScene:create()

function main()
    loader = CCBIFactory:create()
    node = loader:loadCCBI(sceneGame, "first.ccbi", "GameUILoader")
    sceneGame:addChild(node)
    
    CCDirector:sharedDirector():runWithScene(sceneGame)
end

xpcall(main, __G__TRACKBACK__)

second.lua

function second_change_onClicked()
    node:removeFromParentAndCleanup(true)
        
    local loader = CCBIFactory:create()
    node = loader:loadCCBI(sceneGame, "first.ccbi", "GameUILoader")
    sceneGame:addChild(node)
    
    return 0
end

function second_text_onClicked()
    second_text:setString("test")
    return 0
end


function set_second_text(obj)
    second_text = obj
end


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值