现在新版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_keypress
button的seletor全部为固定的onClicked
调用lua函数对应为CCBIfilename_keypress_onClicked
3. 成员变量名字也不能重复,都是全局的
CCBIfilename_text-CCLabelTTF(后面跟-类型)
lua对应的函数set_CCBIfilename_text(obj)
以后就可以直接用obj里面赋值的对象来操作
by 孙少磊