现在新版cocos2dx已经官方支持lua调用ccbi文件, 具体官方有例子

下面的文章已经用处不大




目前cocos2dx 暂时不支持lua调用高级的extensions类, 但是界面部分大量使用cocosbuilder,所以增加了lua支持ccbi和superanimation。

一。cocos2dx中C调lua函数: CCLuaEngine* pEngine = CCLuaEngine::defaultEngine();
pEngine->executeGlobalFunction(iter->second.c_str()); //必须是全局的,参数为函数的名字/***********************************************************二。lua调用c的函数:用tolua++,编写pkg文件,生成cpp文件, 可以用一个pkg,include其他的pkg文件例如$#include "zsw_extension.h"$pfile "CCBIFactory.pkg"
$pfile "SuperAnimNodeV2.pkg"这样生成一个zsw_extension.cpp文件,这里要注意一下:在使用回调lua函数的时候(registerScriptTapHandler)需要手动修改一个地方 !tolua_isusertype(tolua_S,1,"SuperAnimNode",0,&tolua_err) ||
(tolua_isvaluenil(tolua_S,2,&tolua_err) || !toluafix_isfunction(tolua_S,2,"LUA_FUNCTION",0,&tolua_err)) ||
!tolua_isnoobj(tolua_S,3,&tolua_err) (修改error的判断)下面修改返回的是function SuperAnimNode* self = (SuperAnimNode*) tolua_tousertype(tolua_S,1,0);
//int nHandler = ((int) tolua_tonumber(tolua_S,2,0));
LUA_FUNCTION funcID = ( toluafix_ref_function(tolua_S,2,0));
。。。
self->registerScriptTapHandler(funcID);让回调返回lua的函数然后可以手动copy一个zsw_extension.h文件
#ifndef __LUAzsw_H_
#define __LUAzsw_H_

extern "C" {
#include "tolua++.h"
#include "tolua_fix.h"
}

#include <map>
#include <string>
#include "tolua_fix.h"
#include "cocos2d.h"
#include "CCLuaEngine.h"
#include "SimpleAudioEngine.h"
#include "../zgame/Animation.h"




using namespace cocos2d;
using namespace CocosDenshion;

TOLUA_API int tolua_ZgameLua_open(lua_State* tolua_S);

#endif // __LUAzsw_H_


再打开cocos2dx_support目录下面的CCLuaEngine.cpp(copy这个文件到本地目录,然后在工程中加入该文件)1. 添加#include "zsw_extension.h"2. 在init中加入我们生成的bool CCLuaEngine::init(void)
{
m_state = lua_open();
luaL_openlibs(m_state);
tolua_Cocos2d_open(m_state);
tolua_zsw_open(m_state); // (这里就是加入的函数)之后lua就可以调用pkg编写的函数了/****************************************************************************三。ccb事件和回调处理方法

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();
registerCCBIMember(funcName, button, typeName);
}

objectNameMapping.insert(map<int, string>::value_type(button->m_uID, name));

return false;
}

void GameUILayer::onClicked(CCObject * pSender, cocos2d::extension::CCControlEvent pCCControlEvent) {

map<int, string>::iterator iter = objectNameMapping.find(pSender->m_uID);

if(iter != objectNameMapping.end())
{
CCLuaEngine* pEngine = (CCLuaEngine*)CCScriptEngineManager::sharedManager()->getScriptEngine();
// pEngine->executeGlobalFunctionByShaoLei(iter->second.c_str(), pSender, (char*)iter->second.c_str(), pCCControlEvent);
pEngine->executeGlobalFunction((iter->second+"_onClicked").c_str());
}
}

void GameUILayer::registerCCBIMember(const char* functionName, CCObject *obj, char* typeName)
{
CCLuaEngine* m_engine = (CCLuaEngine*)CCScriptEngineManager::sharedManager()->getScriptEngine();

lua_State* m_state_ = m_engine->getLuaState();

lua_getglobal(m_state_, functionName); /* query function by name, stack: function */
if (!lua_isfunction(m_state_, -1))
{
CCLOG("[LUA ERROR] name '%s' does not represent a Lua function", functionName);
lua_pop(m_state_, 1);
return;
}

m_engine->pushCCObject(obj, typeName);

int error = lua_pcall(m_state_, 1, 0, 0); /* callfunction, stack: ret */
if (error)
{
CCLOG("[LUA ERROR] %s", lua_tostring(m_state_, - 1));
lua_pop(m_state_, 1); // clean error message
return;
}

}



四,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


五。ccb编辑注意名字:1. 名字不能重复,因为lua都是全局的2. button部分, CCBIfilename_keypressbutton的seletor全部为固定的onClicked调用lua函数对应为CCBIfilename_keypress_onClicked3. 成员变量名字也不能重复,都是全局的CCBIfilename_text-CCLabelTTF(后面跟-类型)lua对应的函数set_CCBIfilename_text(obj)以后就可以直接用obj里面赋值的对象来操作
by 孙少磊