1. 程式人生 > >cocos2dx學習原始碼之介面iOS事件分發(2)

cocos2dx學習原始碼之介面iOS事件分發(2)

今天看看事件是如何分發的。程式碼版本: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>更新事件,對之前的儲存事件資料,進行刪除。
}