cocos2d-x源码分析-----触摸事件的实现

版本:3.0Beta2 

在android上,触摸事件的原始起点在nativeactivity分发出去。

例如:

cocos2d::Director::getInstance()->getOpenGLView()->handleTouchesBegin(1, &pointerId, &x, &y);

总共有几下几种,在EGLView当中,实现了

    virtual void handleTouchesBegin(int num, int ids[], float xs[], float ys[]);
    virtual void handleTouchesMove(int num, int ids[], float xs[], float ys[]);
    virtual void handleTouchesEnd(int num, int ids[], float xs[], float ys[]);
    virtual void handleTouchesCancel(int num, int ids[], float xs[], float ys[]);

在上面几种方法中,再由EventDispatcher的dispatchEvent方法传递出去。

dispatchEvent不仅分发了触摸事件还有其它事件,比如在drawScene方法中,渲染后,update事件等。

下面主要看触摸事件的实现,

dispatchTouchEvent(static_cast<EventTouch*>(event));

 触摸事件分为两类:oneByone,allAtOnce

oneByone会将Event一个一个传递过去,而allAtOnce会一次性将Event传递过去。Event中包括坐标信息。void EventDispatcher::dispatchTouchEvent(EventTouch* event)

{
sortEventListeners(EventListenerTouchOneByOne::LISTENER_ID); sortEventListeners(EventListenerTouchAllAtOnce::LISTENER_ID); auto oneByOnelisteners
= getListeners(EventListenerTouchOneByOne::LISTENER_ID); auto allAtOncelisteners = getListeners(EventListenerTouchAllAtOnce::LISTENER_ID); // If there aren't any touch listeners, return directly. if (nullptr == oneByOnelisteners && nullptr == allAtOncelisteners) return; bool isNeedsMutableSet = (oneByOnelisteners && allAtOncelisteners); std::vector<Touch*> orignalTouches = event->getTouches(); std::vector<Touch*> mutableTouches(orignalTouches.size()); std::copy(orignalTouches.begin(), orignalTouches.end(), mutableTouches.begin()); // // process the target handlers 1st // if (oneByOnelisteners) { auto mutableTouchesIter = mutableTouches.begin(); auto touchesIter = orignalTouches.begin(); for (; touchesIter != orignalTouches.end(); ++touchesIter) { bool isSwallowed = false; auto onTouchEvent = [&](EventListener* l) -> bool { // Return true to break EventListenerTouchOneByOne* listener = static_cast<EventListenerTouchOneByOne*>(l); // Skip if the listener was removed. if (!listener->_isRegistered) return false; event->setCurrentTarget(listener->_node); bool isClaimed = false; std::vector<Touch*>::iterator removedIter; EventTouch::EventCode eventCode = event->getEventCode(); if (eventCode == EventTouch::EventCode::BEGAN) { if (listener->onTouchBegan) { isClaimed = listener->onTouchBegan(*touchesIter, event); if (isClaimed && listener->_isRegistered) { listener->_claimedTouches.push_back(*touchesIter); } } } else if (listener->_claimedTouches.size() > 0 && ((removedIter = std::find(listener->_claimedTouches.begin(), listener->_claimedTouches.end(), *touchesIter)) != listener->_claimedTouches.end())) { isClaimed = true; switch (eventCode) { case EventTouch::EventCode::MOVED: if (listener->onTouchMoved) { listener->onTouchMoved(*touchesIter, event); } break; case EventTouch::EventCode::ENDED: if (listener->onTouchEnded) { listener->onTouchEnded(*touchesIter, event); } if (listener->_isRegistered) { listener->_claimedTouches.erase(removedIter); } break; case EventTouch::EventCode::CANCELLED: if (listener->onTouchCancelled) { listener->onTouchCancelled(*touchesIter, event); } if (listener->_isRegistered) { listener->_claimedTouches.erase(removedIter); } break; default: CCASSERT(false, "The eventcode is invalid."); break; } } // If the event was stopped, return directly. if (event->isStopped()) { updateListeners(event); return true; } CCASSERT((*touchesIter)->getID() == (*mutableTouchesIter)->getID(), ""); if (isClaimed && listener->_isRegistered && listener->_needSwallow) { if (isNeedsMutableSet) { mutableTouchesIter = mutableTouches.erase(mutableTouchesIter); isSwallowed = true; } return true; } return false; }; // dispatchEventToListeners(oneByOnelisteners, onTouchEvent); if (event->isStopped()) { return; } if (!isSwallowed) ++mutableTouchesIter; } } // // process standard handlers 2nd // if (allAtOncelisteners && mutableTouches.size() > 0) { auto onTouchesEvent = [&](EventListener* l) -> bool{ EventListenerTouchAllAtOnce* listener = static_cast<EventListenerTouchAllAtOnce*>(l); // Skip if the listener was removed. if (!listener->_isRegistered) return false; event->setCurrentTarget(listener->_node); switch (event->getEventCode()) { case EventTouch::EventCode::BEGAN: if (listener->onTouchesBegan) { listener->onTouchesBegan(mutableTouches, event); } break; case EventTouch::EventCode::MOVED: if (listener->onTouchesMoved) { listener->onTouchesMoved(mutableTouches, event); } break; case EventTouch::EventCode::ENDED: if (listener->onTouchesEnded) { listener->onTouchesEnded(mutableTouches, event); } break; case EventTouch::EventCode::CANCELLED: if (listener->onTouchesCancelled) { listener->onTouchesCancelled(mutableTouches, event); } break; default: CCASSERT(false, "The eventcode is invalid."); break; } // If the event was stopped, return directly. if (event->isStopped()) { updateListeners(event); return true; } return false; }; dispatchEventToListeners(allAtOncelisteners, onTouchesEvent); if (event->isStopped()) { return; } } updateListeners(event); }

sortEventListeners(EventListenerTouchOneByOne::LISTENER_ID);

sortEventListeners(EventListenerTouchAllAtOnce::LISTENER_ID);

首先根据优先级进行排序。

然后分发给各个node

原文地址:https://www.cnblogs.com/lihaibo19891007/p/3580431.html