在lua中我们这么注册touch事件
local listenner = cc.EventListenerTouchOneByOne:create() listenner:registerScriptHandler(function(touch, event) return true; end, cc.Handler.EVENT_TOUCH_BEGAN)
在c++里面
typedef std::function<bool(Touch*, Event*)> ccTouchBeganCallback; ccTouchBeganCallback onTouchBegan; auto lis = EventListenerTouchOneByOne::create(); lis->onTouchBegan = CC_CALLBACK_2(TestLayer::touchBegan, this);
很明显onTouchBegin是一个std::function
,如果在c++中,如果我们的参数是一个function,那么生成的lua binding代码中会有这么一段逻辑:
std::function<void ()> arg0; do { // Lambda binding for lua is not supported. assert(false); } while(0) ;
很明显,这里主动报错了,注释中也说明了,function在lua中是不支持的
void scheduleOnce(const std::function<void(float)>& callback, float delay, const std::string &key);
static EventListenerCustom* create(const std::string& eventName, const std::function<void(EventCustom*)>& callback);
EventCustom
在lua中创建自定义事件:
local lis = cc.EventListenerCustom:create("APP_EVENT", function (){ log("EVENT") }); cc.Director:getInstance():getEventDispatcher():addEventListenerWithFixedPriority(lis, 1)
cc.EventListenerCustom:create
对应的c++ lua binding代码:
const std::string eventName = ((const std::string) tolua_tocppstring(tolua_S,2,0)); LUA_FUNCTION handler = toluafix_ref_function(tolua_S,3,0); cocos2d::EventListenerCustom* tolua_ret = LuaEventListenerCustom::create(eventName); // 你会发现最终其实它也是到了ScriptHandlerMgr.addObjectHandler,会将lua function存储在map表 ScriptHandlerMgr::getInstance()->addObjectHandler((void*)tolua_ret, handler, ScriptHandlerMgr::HandlerType::EVENT_CUSTIOM);
在tolua工具模板代码中并没有出现以上的c++片段,那么就是后期人为修正的一段逻辑
lua中触发
local event = cc.EventCustom:new("APP_EVENT") event.data="12"; cc.Director:getInstance():getEventDispatcher():dispatchEvent(event)
void EventDispatcher::dispatchEvent(Event* event){ auto iter = _listenerMap.find(listenerID); if (iter != _listenerMap.end()) { auto listeners = iter->second; auto onEvent = [&event](EventListener* listener) -> bool{ event->setCurrentTarget(listener->getAssociatedNode()); listener->_onEvent(event); // 响应触发事件,对于custom return event->isStopped(); }; (this->*pfnDispatchEventToListeners)(listeners, onEvent); } } bool EventListenerCustom::init(const ListenerID& listenerId, const std::function<void(EventCustom*)>& callback) { bool ret = false; _onCustomEvent = callback; auto listener = [this](Event* event){ if (_onCustomEvent != nullptr) { // 所以事件会派发到这里,lambda套娃,真实的函数实体在callback参数 _onCustomEvent(static_cast<EventCustom*>(event)); } }; // 第三个参数就是一个lambda,对应的是listener->_onEvent if (EventListener::init(EventListener::Type::CUSTOM, listenerId, listener)) { ret = true; } return ret; } // lua_cocos2dx_manual.cpp EventListenerCustom* LuaEventListenerCustom::create(const std::string& eventName) { EventListenerCustom* eventCustom = new (std::nothrow) EventListenerCustom(); if (nullptr == eventCustom) return nullptr; // callback参数 if ( eventCustom->init(eventName, [=](EventCustom* event){ // 最终是到达了这里 BasicScriptData data((void*)eventCustom,(void*)event); LuaEngine::getInstance()->handleEvent(ScriptHandlerMgr::HandlerType::EVENT_CUSTIOM, (void*)&data ); })) { eventCustom->autorelease(); } else { CC_SAFE_DELETE(eventCustom); } return eventCustom; } // 最后完成到lua层的调用,里面会有对参数的转换 int LuaEngine::handleEvenCustom(void* data){ }