今天看看事件是如何分发的。代码版本:cocos2dx-3.9
上次说到GLView接手touch事件:handleTouchesBegin。
源代码:
void GLView::handleTouchesBegin(int num, intptr_t ids[], float xs[], float ys[])
{
intptr_t id = 0;
float x = 0.0f;
float y = 0.0f;
int unusedIndex = 0;
EventTouch touchEvent;
for (int i = 0; i < num; ++i)
{
id = ids[i];
x = xs[i];
y = ys[i];
auto iter = g_touchIdReorderMap.find(id);
// it is a new touch
if (iter == g_touchIdReorderMap.end())
{
unusedIndex = getUnUsedIndex();
// The touches is more than MAX_TOUCHES ?
if (unusedIndex == -1) {
CCLOG("The touches is more than MAX_TOUCHES, unusedIndex = %d", unusedIndex);
continue;
}
Touch* touch = g_touches[unusedIndex] = new (std::nothrow) Touch();
touch->setTouchInfo(unusedIndex, (x - _viewPortRect.origin.x) / _scaleX,
(y - _viewPortRect.origin.y) / _scaleY);
CCLOGINFO("x = %f y = %f", touch->getLocationInView().x, touch->getLocationInView().y);
g_touchIdReorderMap.insert(std::make_pair(id, unusedIndex<span style="color:#ffffff;">));</span>
touchEvent._touches.push_back(touch);
}
}
if (touchEvent._touches.size() == 0)
{
CCLOG("touchesBegan: size = 0");
return;
}
touchEvent._eventCode = EventTouch::EventCode::BEGAN;
auto dispatcher = Director::getInstance()->getEventDispatcher();
<span style="color:#ff6666;">dispatcher->dispatchEvent(&touchEvent);</span>
}
上面红色代码,是事件分发的关键。
首先是g_touchIdReorderMap这个用于存储touch信息,其次dispatcher用于对事件分发。g_touchIdReorderMap很好理解。重点看看dispatcher。点击getEventIdspatcher(),看看dispatcher的获取:
<span style="white-space:pre"> </span>EventDispatcher* getEventDispatcher() const { return _eventDispatcher; }
找到_eventDispatcher这个变量的初始化,在Director::init()里面:
bool Director::init(void)
{
//....省略
_eventDispatcher = new (std::nothrow) EventDispatcher();
//...
return true;
}
下面是我们获取touch事件的代码。
auto listener = EventListenerTouchAllAtOnce::create();
listener->onTouchesMoved = CC_CALLBACK_2(CameraArcBallDemo::onTouchsMoved, this);
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
我们在Node里面可以找到一个声明:
EventDispatcher* _eventDispatcher; ///< event dispatcher used to dispatch all kinds of events
找到它的初始化,发现这个东西就是Director里面的_eventDispatcher。
导演是一个单例,事件分发变量也是只有一个。
接着看看addEventListtenerWithSceneGraphpriority, 对lisnter进行设置,判断是否正在进行分发。
<pre name="code" class="cpp">void EventDispatcher::dispatchTouchEvent(EventTouch* event)
{
//方便阅读,此处用伪代码进行代替
对多点触摸进行排序
对单点触摸进行排序
if(单点触摸)
{
<span style="white-space:pre"> </span>1.遍历事件
<span style="white-space:pre"> </span>2.根据事件类型进行分发
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>if(多点触摸)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>根据事件类型进行分发
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>更新事件,对之前的存储事件数据,进行删除。
}