原文地址: http://blog.csdn.net/u011225840/article/details/34126789
1.继承结构
1.1 结构
不详吐槽太多,也不贴图了,贴图要审核好久好久好久好久。
从小到大,先来看下Event的结构。
1.Event--------EventTouch,EventCustom,EventMouse,EventKeyboard,EventFocus,EventAcceleration
其中,EventTouch 和 EventCustom是比较特殊的两个Event。EventTouch是3.x版本的触摸机制相关的Event,而EventCustom则是3.x自定义事件机制的基础,该机制取代了2.x版本中的NotificationCenter。
2.EventListener-------------EventListenerTouchOneByOne,EventListenerTouchAllAtOnce,EventListenerCustom,EventListenerFocus,EventListenerMouse....对应
相比于Event,Listener多了一个,因为对应的Touch被拆分成了两个Listener,一个是OneByone,一个是TouchAllAtOnce。前者是onTouchBegan等函数的Listener,后者是onTouchesBegan等函数的Listener。
1.2.EventDispatcher,EventListener,Event三者的关系
Event相当于data,EventListener包含了data与fuction的一种映射关系,而EventDispatcher相当于一个Manager,管理着EventListener,决定着Event的调用顺序。
Event中包含了type,target等信息;EventListener包含了ListenerID,相关联的Node,对应的callBack;EventDispatcher里含有各种map,vector来管理不同的Listener。具体的,可以看源码分析。
2.源码分析
本次源码分析的量比较大,大家要有心理准备哟~
2.1Event相关
2.1.1 Event
- enum class Type
- {
- TOUCH,
- KEYBOARD,
- ACCELERATION,
- MOUSE,
- FOCUS,
- CUSTOM
- };
- Type _type;
-
- bool _isStopped;
- Node* _currentTarget;
Event主要包含了三个重要的变量,type,是一个enum变量,里面定义了类型;isStopped定义该event是否已经停止,当一个event发生停止时,与其相关的Listener都要停止callback的调用;currentTarget是与该Event相关联的node。
2.1.2 EventTouch
EventTouch是cocos2d-x引擎中非常非常重要的事件。对应于四种touch操作,该类内部定义了四种EventCode
- enum class EventCode
- {
- BEGAN,
- MOVED,
- ENDED,
- CANCELLED
- };
不同的EventCode可以告诉Listener来调用不同的callback。
除此之外,EventTouch中含有std::vector<Touch*> _touches 来记录该事件相关的touch,值得注意的是,本版本默认含有的触摸点最大是5个。
2.1.3 EventCustom
EventCustom的出现取代了统治2.x版本多年的NotificationCenter,来看下EventCustom的两个重要成员变量。
- void* _userData;
- std::string _eventName;
有没有似曾相识的感觉,还是一样的key,还是一样的userData(有点不一样。原来是CCObject*)。
其他的Event因为重要性以及使用度的原因,这里不再赘述,如果以后笔者对他们有新的认识,将会在这里进行添加。
2.2 EventListener相关
2.2.1 EventListener
- std::function<void(Event*)> _onEvent;
- Type _type;
- ListenerID _listenerID;
- bool _isRegistered;
-
- int _fixedPriority;
- Node* _node;
- bool _paused;
- bool _isEnabled;
重要的成员变量:
1.onEvent,是绑定于该Listener的callback function,该func的声明使用了c++11的新特性。
2.type与Event类似,增加一个Unknown的属性。
3.isRegistered变量非常重要,如果他没有被注册,则他的事件不会触发。
4.优先级代表了响应一个事件时的顺序,该值越低,越先响应。
5.node 代表了与该listener相关的node,用于 scene graph类的事件响应,具体的在Dispatcher里面有进行介绍。
6.最后说下ListenerID,这是该类型事件的标识符。除了EventCustomListener的ListerID是与name相关的,其余的ListenerID都是固定的,用于标识该类EventListener。
-
-
-
-
-
-
- inline void setEnabled(bool enabled) { _isEnabled = enabled; };
-
-
-
-
-
-
-
-
- inline void setPaused(bool paused) { _paused = paused; };
上面两段话,解释了什么时候一个Listener是可以接收事件,什么时候是不可以的。
1.一个Listener想接收事件必须是enabled true 并且 paused false。
2.值得注意的是,pause的变量专门是为了scenGraph类的事件存在的(后续有说明),而且一个Node的onEnter和onExit 事件会影响到与Node相关的该类事件的pause状态。
2.2.2 EventListenerOneByOne
-
- virtual EventListenerTouchOneByOne* clone() override;
- virtual bool checkAvailable() override;
-
-
- public:
- std::function<bool(Touch*, Event*)> onTouchBegan;
- std::function<void(Touch*, Event*)> onTouchMoved;
- std::function<void(Touch*, Event*)> onTouchEnded;
- std::function<void(Touch*, Event*)> onTouchCancelled;
上面的是OneByOne重载父类的方法,以及自己本身需要被绑定4个callBack 函数。
- EventListenerTouchOneByOne* EventListenerTouchOneByOne::clone()
- {
-
- auto ret = new EventListenerTouchOneByOne();
- if (ret && ret->init())
- {
- ret->autorelease();
-
- ret->onTouchBegan = onTouchBegan;
- ret->onTouchMoved = onTouchMoved;
- ret->onTouchEnded = onTouchEnded;
- ret->onTouchCancelled = onTouchCancelled;
-
- ret->_claimedTouches = _claimedTouches;
- ret->_needSwallow = _needSwallow;
- }
- else
- {
- CC_SAFE_DELETE(ret);
- }
- return ret;
- }
- bool EventListenerTouchOneByOne::checkAvailable()
- {
-
-
-
- if (onTouchBegan == nullptr)
- {
- CCASSERT(false, "Invalid EventListenerTouchOneByOne!");
- return false;
- }
-
- return true;
- }
什么是可用性,当在dispatcher进行事件分发时,如果一个Listener是不可用的,则不会将该事件分发给他。
- std::vector<Touch*> _claimedTouches;
- bool _needSwallow;
OneByOne的touch是可以设置吞噬属性的。
2.2.3 EventListenerAllAtOnce
- std::function<void(const std::vector<Touch*>&, Event*)> onTouchesBegan;
- std::function<void(const std::vector<Touch*>&, Event*)> onTouchesMoved;
- std::function<void(const std::vector<Touch*>&, Event*)> onTouchesEnded;
- std::function<void(const std::vector<Touch*>&, Event*)> onTouchesCancelled;
AllAtOnce就是所谓的standard touch处理机制,一次性处理所有的touch。
值得注意的是AllAtOnce的checkAvailable要求,上述四个函数指针都不能为空。
- bool EventListenerTouchAllAtOnce::checkAvailable()
- {
- if (onTouchesBegan == nullptr && onTouchesMoved == nullptr
- && onTouchesEnded == nullptr && onTouchesCancelled == nullptr)
- {
- CCASSERT(false, "Invalid EventListenerTouchAllAtOnce!");
- return false;
- }
-
- return true;
- }
2.3 EventListenerCustom
同样的,EventListenerID是根据独特的Name进行命名的,值得注意的是请确保你的name是具有唯一性的,否在在DispatchCustomEvent时会有问题。
3. EventDispatcher
从头到尾写了这么多,才开始进入主题,上面的东西都是为了看EventDispatcher源码的开胃菜!!!在介绍这个之前,我们必须要看一个内部类
3.1 EventListenerVector
- class EventListenerVector
- {
- public:
- EventListenerVector();
- ~EventListenerVector();
- size_t size() const;
- bool empty() const;
-
- void push_back(EventListener* item);
- void clearSceneGraphListeners();
- void clearFixedListeners();
- void clear();
-
- inline std::vector<EventListener*>* getFixedPriorityListeners() const { return _fixedListeners; };
- inline std::vector<EventListener*>* getSceneGraphPriorityListeners() const { return _sceneGraphListeners; };
- inline ssize_t getGt0Index() const { return _gt0Index; };
- inline void setGt0Index(ssize_t index) { _gt0Index = index; };
- private:
- std::vector<EventListener*>* _fixedListeners;
- std::vector<EventListener*>* _sceneGraphListeners;
- ssize_t _gt0Index;
- };
首先我要说明的是两个非常非常重要的变量。fixedListeners和sceneGraphListeners,这是两个截然不同的Listener列表。
1.sceneGraph类型的事件,是与当前正在运行的scene下node相关的事件,也就是说一个事件(比如说触摸事件),需要按照一定的响应序列,依次对这些Node进行事件响应,所以该类型的事件都会绑定一个与此相关联的node,并且响应顺序是与node在scene下的zorder相关的。该类型下的事件优先级统一为0.
2.fixed类型的事件相对就比较简单了,但是有一个限制就是其优先级不能为0.
在EventDispatcher的成员变量中有一个map :std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listenerMap; 一种ListenerID对应了一个Vector。
- size_t EventDispatcher::EventListenerVector::size() const
- {
-
- size_t ret = 0;
- if (_sceneGraphListeners)
- ret += _sceneGraphListeners->size();
- if (_fixedListeners)
- ret += _fixedListeners->size();
-
- return ret;
- }
- void EventDispatcher::EventListenerVector::push_back(EventListener* listener)
- {
-
- if (listener->getFixedPriority() == 0)
- {
- if (_sceneGraphListeners == nullptr)
- {
- _sceneGraphListeners = new std::vector<EventListener*>();
- _sceneGraphListeners->reserve(100);
- }
-
- _sceneGraphListeners->push_back(listener);
- }
- else
- {
- if (_fixedListeners == nullptr)
- {
- _fixedListeners = new std::vector<EventListener*>();
- _fixedListeners->reserve(100);
- }
-
- _fixedListeners->push_back(listener);
- }
- }
上面两个函数是与一般Vector不一样的地方,需要注意的地方我已经标注了注释。
3.2 Add操作
既然是一个类似于Manager的类,那就先从Add操作开始吧。
三种事件的添加方式:
3.2.1 sceneGraph类
- void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)
- {
- CCASSERT(listener && node, "Invalid parameters.");
- CCASSERT(!listener->isRegistered(), "The listener has been registered.");
-
-
- if (!listener->checkAvailable())
- return;
-
- listener->setAssociatedNode(node);
- listener->setFixedPriority(0);
- listener->setRegistered(true);
-
- addEventListener(listener);
- }
3.2.2 fixed类
- void EventDispatcher::addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority)
- {
- CCASSERT(listener, "Invalid parameters.");
-
- CCASSERT(!listener->isRegistered(), "The listener has been registered.");
-
- CCASSERT(fixedPriority != 0, "0 priority is forbidden for fixed priority since it's used for scene graph based priority.");
-
-
- if (!listener->checkAvailable())
- return;
-
-
- listener->setAssociatedNode(nullptr);
- listener->setFixedPriority(fixedPriority);
- listener->setRegistered(true);
- listener->setPaused(false);
-
- addEventListener(listener);
- }
3.2.3 custom类
- EventListenerCustom* EventDispatcher::addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback)
- {
-
- EventListenerCustom *listener = EventListenerCustom::create(eventName, callback);
-
-
- addEventListenerWithFixedPriority(listener, 1);
-
- return listener;
- }
可以看出,添加函数最后都用到了一个函数addEventListener,下面对其进行剖析(这个函数又用到了其他函数,又,又,又。。。。。。)
3.2.4 addEventListener
- void EventDispatcher::addEventListener(EventListener* listener)
- {
-
- if (_inDispatch == 0)
- {
- forceAddEventListener(listener);
- }
- else
- {
-
- _toAddedListeners.push_back(listener);
- }
-
- listener->retain();
- }
3.2.5 forceAddEventListener
- void EventDispatcher::forceAddEventListener(EventListener* listener)
- {
- EventListenerVector* listeners = nullptr;
- EventListener::ListenerID listenerID = listener->getListenerID();
-
-
- auto itr = _listenerMap.find(listenerID);
-
- if (itr == _listenerMap.end())
- {
-
- listeners = new EventListenerVector();
- _listenerMap.insert(std::make_pair(listenerID, listeners));
- }
- else
- {
- listeners = itr->second;
- }
-
- listeners->push_back(listener);
-
-
- if (listener->getFixedPriority() == 0)
- {
-
-
- setDirty(listenerID, DirtyFlag::SCENE_GRAPH_PRIORITY);
-
-
-
-
-
- auto node = listener->getAssociatedNode();
- CCASSERT(node != nullptr, "Invalid scene graph priority!");
-
- associateNodeAndEventListener(node, listener);
-
-
- if (node->isRunning())
- {
- resumeEventListenersForTarget(node);
- }
- }
- else
- {
- setDirty(listenerID, DirtyFlag::FIXED_PRIORITY);
- }
- }
3.2.6associateNodeAndEventListener
- void EventDispatcher::associateNodeAndEventListener(Node* node, EventListener* listener)
- {
-
- std::vector<EventListener*>* listeners = nullptr;
- auto found = _nodeListenersMap.find(node);
- if (found != _nodeListenersMap.end())
- {
- listeners = found->second;
- }
- else
- {
- listeners = new std::vector<EventListener*>();
- _nodeListenersMap.insert(std::make_pair(node, listeners));
- }
-
- listeners->push_back(listener);
- }
3.2.7 removeEventListenersForTarget
- void EventDispatcher::resumeEventListenersForTarget(Node* target, bool recursive)
- {
-
- auto listenerIter = _nodeListenersMap.find(target);
- if (listenerIter != _nodeListenersMap.end())
- {
- auto listeners = listenerIter->second;
- for (auto& l : *listeners)
- {
- l->setPaused(false);
- }
- }
-
- for (auto& listener : _toAddedListeners)
- {
- if (listener->getAssociatedNode() == target)
- {
- listener->setPaused(false);
- }
- }
-
- setDirtyForNode(target);
-
- if (recursive)
- {
- const auto& children = target->getChildren();
- for (const auto& child : children)
- {
- resumeEventListenersForTarget(child, true);
- }
- }
- }
3.3 Remove
看完了Add,当然要讲remove
3.3.1 removeEventListener
3.3.2 removeEventListenersForListenerID
- void EventDispatcher::removeEventListenersForListenerID(const EventListener::ListenerID& listenerID)
- {
- auto listenerItemIter = _listenerMap.find(listenerID);
- if (listenerItemIter != _listenerMap.end())
- {
- auto listeners = listenerItemIter->second;
- auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
- auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
-
-
- auto removeAllListenersInVector = [&](std::vector<EventListener*>* listenerVector){
- if (listenerVector == nullptr)
- return;
-
- for (auto iter = listenerVector->begin(); iter != listenerVector->end();)
- {
-
- auto l = *iter;
- l->setRegistered(false);
- if (l->getAssociatedNode() != nullptr)
- {
- dissociateNodeAndEventListener(l->getAssociatedNode(), l);
- l->setAssociatedNode(nullptr);
- }
-
- if (_inDispatch == 0)
- {
- iter = listenerVector->erase(iter);
- CC_SAFE_RELEASE(l);
- }
- else
- {
- ++iter;
- }
- }
- };
-
-
- removeAllListenersInVector(sceneGraphPriorityListeners);
- removeAllListenersInVector(fixedPriorityListeners);
-
-
-
- _priorityDirtyFlagMap.erase(listenerID);
-
- if (!_inDispatch)
- {
- listeners->clear();
- delete listeners;
- _listenerMap.erase(listenerItemIter);
- }
- }
-
-
- for (auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end();)
- {
- if ((*iter)->getListenerID() == listenerID)
- {
- (*iter)->setRegistered(false);
- (*iter)->release();
- iter = _toAddedListeners.erase(iter);
- }
- else
- {
- ++iter;
- }
- }
- }
与其相关的两个remove函数
- void EventDispatcher::removeEventListenersForType(EventListener::Type listenerType)
- {
- if (listenerType == EventListener::Type::TOUCH_ONE_BY_ONE)
- {
- removeEventListenersForListenerID(EventListenerTouchOneByOne::LISTENER_ID);
- }
- else if (listenerType == EventListener::Type::TOUCH_ALL_AT_ONCE)
- {
- removeEventListenersForListenerID(EventListenerTouchAllAtOnce::LISTENER_ID);
- }
- else if (listenerType == EventListener::Type::MOUSE)
- {
- removeEventListenersForListenerID(EventListenerMouse::LISTENER_ID);
- }
- else if (listenerType == EventListener::Type::ACCELERATION)
- {
- removeEventListenersForListenerID(EventListenerAcceleration::LISTENER_ID);
- }
- else if (listenerType == EventListener::Type::KEYBOARD)
- {
- removeEventListenersForListenerID(EventListenerKeyboard::LISTENER_ID);
- }
- else
- {
- CCASSERT(false, "Invalid listener type!");
- }
- }
- void EventDispatcher::removeCustomEventListeners(const std::string& customEventName)
- {
- removeEventListenersForListenerID(customEventName);
- }
3.3.3 removeAllEventListeners
- void EventDispatcher::removeAllEventListeners()
- {
- bool cleanMap = true;
- std::vector<EventListener::ListenerID> types(_listenerMap.size());
-
- for (const auto& e : _listenerMap)
- {
- if (_internalCustomListenerIDs.find(e.first) != _internalCustomListenerIDs.end())
- {
- cleanMap = false;
- }
- else
- {
- types.push_back(e.first);
- }
- }
-
- for (const auto& type : types)
- {
- removeEventListenersForListenerID(type);
- }
-
- if (!_inDispatch && cleanMap)
- {
- _listenerMap.clear();
- }
- }
3.4 DispatchEvent(核心内容)
终于到了核心内容了,为啥我要把核心内容放到后面。如果不看上面,不了解Event,EventListener,EventVector以及Dispatcher是如何管理EventListener的,看下面的代码就会有很多的疑惑。ok,让我们静静欣赏源码吧。
3.4.1 dispatchEvent
- void EventDispatcher::dispatchEvent(Event* event)
- {
- if (!_isEnabled)
- return;
-
-
- updateDirtyFlagForSceneGraph();
-
-
- DispatchGuard guard(_inDispatch);
-
-
- if (event->getType() == Event::Type::TOUCH)
- {
- dispatchTouchEvent(static_cast<EventTouch*>(event));
- return;
- }
-
-
- auto listenerID = __getListenerID(event);
-
-
- sortEventListeners(listenerID);
-
- 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);
-
- return event->isStopped();
- };
-
-
- dispatchEventToListeners(listeners, onEvent);
- }
-
-
- updateListeners(event);
- }
我们可以看出,特殊的touchEvent和普通的event走的不是同一条控制流程,既然如此,我们就先一般后特殊吧,先来看看一般流程下的DispatchEventToListeners吧
3.4.2 dispatchEventToListeners
- void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent)
- {
- bool shouldStopPropagation = false;
- auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
- auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
-
-
- ssize_t i = 0;
-
- if (fixedPriorityListeners)
- {
- CCASSERT(listeners->getGt0Index() <= static_cast<ssize_t>(fixedPriorityListeners->size()), "Out of range exception!");
-
- if (!fixedPriorityListeners->empty())
- {
- for (; i < listeners->getGt0Index(); ++i)
- {
- auto l = fixedPriorityListeners->at(i);
-
-
- if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
- {
- shouldStopPropagation = true;
- break;
- }
- }
- }
- }
-
- if (sceneGraphPriorityListeners)
- {
- if (!shouldStopPropagation)
- {
-
- for (auto& l : *sceneGraphPriorityListeners)
- {
- if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
- {
- shouldStopPropagation = true;
- break;
- }
- }
- }
- }
-
- if (fixedPriorityListeners)
- {
- if (!shouldStopPropagation)
- {
-
- ssize_t size = fixedPriorityListeners->size();
- for (; i < size; ++i)
- {
- auto l = fixedPriorityListeners->at(i);
-
- if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
- {
- shouldStopPropagation = true;
- break;
- }
- }
- }
- }
- }
3.4.3 dispatchTouchEvent(3.x版本的触摸机制)
- 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 (nullptr == oneByOneListeners && nullptr == allAtOnceListeners)
- return;
-
-
- bool isNeedsMutableSet = (oneByOneListeners && allAtOnceListeners);
-
-
- const std::vector<Touch*>& originalTouches = event->getTouches();
- std::vector<Touch*> mutableTouches(originalTouches.size());
- std::copy(originalTouches.begin(), originalTouches.end(), mutableTouches.begin());
-
-
-
-
- if (oneByOneListeners)
- {
- auto mutableTouchesIter = mutableTouches.begin();
- auto touchesIter = originalTouches.begin();
-
- for (; touchesIter != originalTouches.end(); ++touchesIter)
- {
- bool isSwallowed = false;
-
-
- auto onTouchEvent = [&](EventListener* l) -> bool {
- EventListenerTouchOneByOne* listener = static_cast<EventListenerTouchOneByOne*>(l);
-
-
- 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 (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;
- }
- }
-
-
-
-
-
- if (allAtOnceListeners && mutableTouches.size() > 0)
- {
-
- auto onTouchesEvent = [&](EventListener* l) -> bool{
- EventListenerTouchAllAtOnce* listener = static_cast<EventListenerTouchAllAtOnce*>(l);
-
- 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 (event->isStopped())
- {
- updateListeners(event);
- return true;
- }
-
- return false;
- };
-
- dispatchEventToListeners(allAtOnceListeners, onTouchesEvent);
- if (event->isStopped())
- {
- return;
- }
- }
-
- updateListeners(event);
- }
很多需要注意的地方我全给了中文标识,但是这里我还要再次说明下新版本的touch OneByOne机制:
1.listener根据Node的优先级排序后,依次响应。值得注意的是,新版本的优先级是根据Node的global Zorder来的,而不是2.x的触摸优先级。
2.当TouchEvent Began来了之后,所有的listener会依次影响Touch Began。然后再依次响应Touch Move...而不是一个listener响应完 began move end之后 轮到下一个listener响应的顺序。
3.吞噬操作只有发生在began return true后才可以发生
3.4.4 DispatchCustomEvent (新版本的NotificationCenter机制)
- void EventDispatcher::dispatchCustomEvent(const std::string &eventName, void *optionalUserData)
- {
- EventCustom ev(eventName);
- ev.setUserData(optionalUserData);
- dispatchEvent(&ev);
- }
好简单,这个函数像不像 postNotification(......)?,在3.x的事件中,再也不要使用NotificationCenter了哦~
4.小结
Event,EventListener,EventDispatcher的关系
新的触摸机制
新的NotificationCenter方法