cocos2d-x解析ccb及绑定到lua
来源:互联网 发布:java可变长参数 数组 编辑:程序博客网 时间:2024/05/18 03:58
要点一:C++解析ccb主要是这几个文件
CCBReader.h/cpp、CCNodeLoaderLibrary.cpp、CCNodeLoader.h/cpp等
CCBReader文件中的CCBReader::readNodeGraph方法是读取ccbi的节点(该方法应该看懂),该方法做的事有
/* Read class name. */ std::string className = this->readCachedString();
2.节点名字memberVarAssignmentName
// Read assignment type and name int memberVarAssignmentType = this->readInt(false); std::string memberVarAssignmentName; if(memberVarAssignmentType != kCCBTargetTypeNone) { memberVarAssignmentName = this->readCachedString(); }3.解析节点属性
... CCNodeLoader *ccNodeLoader = this->mCCNodeLoaderLibrary->getCCNodeLoader(className.c_str()); if (! ccNodeLoader) { CCLog("no corresponding node loader for %s", className.c_str()); returnNULL; } CCNode *node = ccNodeLoader->loadCCNode(pParent, this); ... // Read properties ccNodeLoader->parseProperties(node, pParent, this);从上面3中可以得知mCCNodeLoaderLibrary为CCNodeLoaderLibrary.cpp类实例对象getCCNodeLoader(className.c_str())为获取对应的节点类型Loader实例对象。
要点二:把CCB原有控件及事件绑定到Lua中(CCControlButton)
在CCNode * CCBReader::readNodeGraph(CCNode * pParent)方法最后加上以下代码
//-------------------binding lua if (memberVarAssignmentName != "") { ZGLuaUtils::bindCCBAssign(memberVarAssignmentName.c_str(), className.c_str(), node); } //-------------------binding lua------end我们看下C++中ZGLuaUtils类代码
void ZGLuaUtils::bindCCBAssign(constchar* assignmentName, constchar *className, CCNode* node) { lua_State *L = ((CCLuaEngine*)CCScriptEngineManager::sharedManager()->getScriptEngine())->getLuaStack()->getLuaState(); lua_getglobal(L, "GF_setCCBBind"); /**//* Push PARAMETERS to STACK */ tolua_pushstring(L, assignmentName); tolua_pushusertype(L, node, className); /**//* Call FUNCTION in LUA */ int iError; iError = lua_pcall(L, //VMachine 2, //Argument Count LUA_MULTRET, //Return Value Count 0); if (iError) { constchar* errorInfo = lua_tostring(L, 1); CCLOG("CCBReader::bindCCBAssign pcall FAILED, %s, %d", errorInfo, iError); } /**//* Check Return Value Types */ }
上面调用 了Lua中的全局函数也即C++调用Lua拉,查看ZGCCBSupport.lua文件
GV_CCBVars = nilfunction GF_setCCBBind(nodeKey, node) CCBLOG ("binding.."..nodeKey) GV_CCBVars[nodeKey] = nodeend
lua中具体实现调用节点控件见LuaLayer.lua文件
function LuaLayer:createLayer() self:initForVars() self.layer = CCBReader:nodeGraphFromFile(self.ccbiName) self.ccbReader = GV_CCBReader self.ccbReader:retain() self:initUI() local function sceneEventHandler( eventType ) if eventType == "enter" then self:onPreEnter() else self:onPreExit() end end self.layer:registerScriptHandler(sceneEventHandler) return self.layerend-- init ccb varsfunction LuaLayer:initForVars( ) self.ccbVars = {} self:initVarsForCCB() GV_CCBVars = self.ccbVarsend经过以上操作Lua中就能操作该节点拉!下面实现绑定控件的事件,也即注册控件事件 (如CCControlButton)
1)修改CCNodeLoader.h中的BlockCCControlData加上std::string mSelectorName;
struct BlockCCControlData { SEL_CCControlHandler mSELCCControlHandler; CCObject * mTarget; std::string mSelectorName; int mControlEvents;};2)修改CCNodeLoader.cpp函数parsePropTypeBlockCCControl
BlockCCControlData * CCNodeLoader::parsePropTypeBlockCCControl(CCNode * pNode, CCNode * pParent, CCBReader * pCCBReader) { //-----直接传出带selectorName的BlockData std::string selectorName = pCCBReader->readCachedString(); // 在返回之前,要把下面这个玩意读出来,否则的话会造成读取数据的错位 pCCBReader->readInt(false); // for int selectorTarget pCCBReader->readInt(false); // for int controlEvents if(selectorName.length() > 0) { BlockCCControlData *blockData = newBlockCCControlData(); blockData->mSelectorName = selectorName; return blockData; } //-----直接传出带selectorName的BlockData---end return NULL;}3)修改CCControlLoader.cpp中的事件函数onHandlePropTypeBlockCCControl
#include "CCControlLoader.h"#include "ZGLuaUtils.h"void CCControlLoader::onHandlePropTypeBlockCCControl(CCNode * pNode, CCNode * pParent, constchar * pPropertyName, BlockCCControlData * pBlockCCControlData, CCBReader * pCCBReader) { ZGLuaUtils::bindCCBFunctionForCCControl(pBlockCCControlData->mSelectorName.c_str(), "CCControlButton", pNode, false);}我们看下C++中ZGLuaUtils类代码
void ZGLuaUtils::bindCCBFunctionForCCControl(constchar *selectorName, constchar *className, cocos2d::CCNode *node, bool isRegistForTouch) { lua_State *L = getLuaState(); lua_getglobal(L, "GF_setCCBCallback"); /**//* Push PARAMETERS to STACK */ tolua_pushusertype(L, node, className); tolua_pushstring(L, selectorName); tolua_pushboolean(L, isRegistForTouch); /**//* Call FUNCTION in LUA */ int iError; iError = lua_pcall(L, //VMachine 3, //Argument Count LUA_MULTRET, //Return Value Count 0); if (iError) { constchar* errorInfo = lua_tostring(L, 1); CCLOG("CCBReader::bindCCBFunctionForCCControl pcall FAILED, %s, %d", errorInfo, iError); } /**//* Check Return Value Types */}上面调用 了Lua中的全局函数也即C++调用Lua拉,查看ZGCCBSupport.lua文件
function GF_setCCBCallback(node, callbackKey, isRegistForTouch) CCBLOG ("binding callback.."..callbackKey) local value = GV_CCBVars[callbackKey] if isRegistForTouch then -- registe for CCControlButton and others node:registerScriptTouchHandler(GV_CCBVars[callbackKey]) else -- registe for CCMenuItems GF_dump(node, "node") GF_dump(callbackKey, "callbackKey") node:registerScriptTapHandler(GV_CCBVars[callbackKey]) end end上面取得了CCBI中事件名称对应到Lua中相同名称的方法再注册节点脚本事件,但是上面貌似完美但是CCControlButton默认没有registerScriptTapHandler 方法,所以node:registerScriptTapHandler(GV_CCBVars[callbackKey])还是有问题所以还要第4步
4)修改CCControlButton.h文件增加以下代码
// add lua touch support protected: int m_nScriptTapHandler; public: virtualvoid registerScriptTapHandler(int nHandler); virtualvoid unregisterScriptTapHandler(void); int getScriptTapHandler() { returnm_nScriptTapHandler; }; // add lua touch support修改CCControlButton.cpp文件,增加以下代码
#include "script_support/CCScriptSupport.h" #include "ZGLuaUtils.h" voidCCControlButton::registerScriptTapHandler(int nHandler) { unregisterScriptTapHandler(); m_nScriptTapHandler = nHandler; LUALOG("[LUA] Add CCMenuItem script handler: %d", m_nScriptTapHandler); } voidCCControlButton::unregisterScriptTapHandler(void) { if (m_nScriptTapHandler) { CCScriptEngineManager::sharedManager()->getScriptEngine()->removeScriptHandler(m_nScriptTapHandler); LUALOG("[LUA] Remove CCMenuItem script handler: %d", m_nScriptTapHandler); m_nScriptTapHandler = 0; } }5)修改ZGToLua 加上以上二个方法以便在Lua中能访问(不能是tolua工具生成,参数是句柄而不是真正意义上的int)
说明:如果Lua在C++中注册回调函数。也即向C++的函数传的参是Lua函数,但C++函数形参却是int型(Lua函数的标号即句柄),在这里程序启动后,每注册一个回调则回调的函数标识是加1的,即句柄是自增长的int型
上面已经实现在Lua中绑定事件即Lua中注册事件但还要在Lua中实现响应事件
6)修改CCControlButton.cpp文件
/**(i)在 CCControlButton::~CCControlButton()方法体内加上unregisterScriptTapHandler(); **(ii)在 ccTouchEnded方法实现调用注册的事件即加上以下代码 **if (m_nScriptTapHandler != 0) { ** ZGLuaUtils::getLuaEngine()->executeControlButtonEvent(this); **} **/ void CCControlButton::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) { m_isPushed = false; setHighlighted(false); if (isTouchInside(pTouch)) { sendActionsForControlEvents(CCControlEventTouchUpInside); if (m_nScriptTapHandler != 0) { ZGLuaUtils::getLuaEngine()->executeControlButtonEvent(this); } } else { sendActionsForControlEvents(CCControlEventTouchUpOutside); } }7)修改CCLuaEngin.h/ccp
//修改.h文件增加以下代码 #include "cocos-ext.h" virtual int executeControlButtonEvent(cocos2d::extension::CCControlButton *controlButton); //修改.cpp文件增加以下代码 int CCLuaEngine::executeControlButtonEvent(cocos2d::extension::CCControlButton *controlButton) { int nHandler = controlButton->getScriptTapHandler(); if (!nHandler) return0; m_stack->pushInt(controlButton->getTag()); m_stack->pushCCObject(controlButton, "CCControlButton"); returnm_stack->executeFunctionByHandler(nHandler, 2); }要点三:把CCB自定义控件及事件绑定到Lua中(CCScrollLayerButton)
1)CCLuaEngin.h/ccp 其它一些控件类会调用CCLuaEngin中的一些方法,而本类又是C++调用Lua堆栈,用处是处理控件和控件的事件响应
//修改.h文件,加上以下代码#include "CCScrollLayerButton.h"virtual int executeScrollLayerButtonEvent(CCScrollLayerButton *scrollLayerButton);
//修改.cpp文件,加上以下代码int CCLuaEngine::executeScrollLayerButtonEvent(CCScrollLayerButton *scrollLayerButton) { int nHandle = scrollLayerButton->getScriptTapHandler(); if (!nHandle) return 0; m_stack->pushInt(scrollLayerButton->getTag()); m_stack->pushCCObject(scrollLayerButton, "CCScrollLayerButton"); return m_stack->executeFunctionByHandler(nHandle, 2);}2)修改CCScrollLayerButton.h/cpp 。跟CCControlButton一样加上注册事件及删除事件及取得回调句柄
3)修改CCBReader.cpp CCNode * CCBReader::readNodeGraph(CCNode * pParent)方法最后加上以下代码
//-------------------binding lua if (memberVarAssignmentName != "") { //CCScrollLayerButton特殊处理 if (strcmp(className.c_str(), "CCScrollLayerButton") == 0) { vector<string> stringVec; ZGStringUtils::splitString(memberVarAssignmentName, "@", stringVec); string member = stringVec[0]; string function = stringVec[1]; //bind var name ZGLuaUtils::bindCCBAssign(member.c_str(), "CCScrollLayerButton", node); //bind function ZGLuaUtils::bindCCBFunctionForCCControl(function.c_str(), "CCScrollLayerButton", node, false); }else{ ZGLuaUtils::bindCCBAssign(memberVarAssignmentName.c_str(), className.c_str(), node); } } //-------------------binding lua------end3)修改ZGToLua.cpp
bindCCBFunctionForCCControl方法调用lua中的方法ZGCCBSupport.lua 文件中的GF_setCCBCallback方法,而方法又调用了节点的node:registerScriptTapHandler(GV_CCBVars[callbackKey]), 因为Lua调用c++代码且是自定义控件所以ZGToLua中加入CCScrollLayerButton的registerScriptTapHandler方法
4)但是由上面要点一第3小点可得CCBReader还会解析控件的属性所以必须加上以下代码,当然也要在项目上加上CCScrollLayerButtonLoader.h文件
#include "CCScrollLayerButtonLoader.h" voidCCNodeLoaderLibrary::registerDefaultCCNodeLoaders() { this->registerCCNodeLoader("CCScrollLayerButton", CCScrollLayerButtonLoader::loader()); }
- cocos2d-x解析ccb及绑定到lua
- cocos2d-x解析ccb及绑定到lua
- cocos2d-x绑定ccb文件
- Cocos2d-x手动绑定C++类到Lua
- Cocos2d-x手动绑定C++类到Lua 分享0
- Cocos2d-x手动绑定C++类到Lua
- 【Cocos2d-x】绑定C++自定义类到Lua
- Cocos2d-x手动绑定C++类到Lua
- Cocos2d-x手动绑定C++类到Lua
- Cocos2d-x Tutorial 之 如何绑定 C++ 类到 Lua
- Cocos2d-x手动绑定C++类到Lua .
- cocos2d-x的lua绑定
- Cocos2d-x 3.x lua绑定
- cocos2d-x Lua绑定C++ 自定义类到Runtime(Lua-binding)
- cocos2d-x hello.lua解析
- cocos2d-x lua json解析
- cocos2d-x从c++文件生成lua绑定文件及lua脚本文件
- CocosBuilder绑定到cocos2d-x
- LUA与python根本就不具有可比性
- Linux网卡驱动程序
- ZOJ 3430 Detect the Virus AC自动机
- 批量 SQL 之 FORALL 语句
- 代理模式之我见
- cocos2d-x解析ccb及绑定到lua
- Create()函数
- 自己改编的一道acm题目。感觉思想不错。比较创新
- sql 循环删除
- Android SAX解析XML
- javascript的var使用
- 正则表达式
- C# 常用的对象操作
- 常用的插值函数