cocos2dx-3.0 : EventDispatcher
来源:互联网 发布:淘宝美工设计兼职 编辑:程序博客网 时间:2024/06/05 14:25
http://blog.csdn.net/u012085988/article/details/16881387
- <pre name="code" class="cpp"></pre><pre name="code" class="cpp"><pre name="code" class="cpp"><pre name="code" class="cpp"><pre name="code" class="cpp"><pre name="code" class="cpp"><pre name="code" class="cpp">.h
- #ifndef __CC_EVENT_DISPATCHER_H__
- #define __CC_EVENT_DISPATCHER_H__
- #include "CCPlatformMacros.h"
- #include "CCEventListener.h"
- #include "CCEvent.h"
- #include <functional>
- #include <string>
- #include <unordered_map>
- #include <list>
- #include <vector>
- NS_CC_BEGIN
- class Event;
- class EventTouch;
- class Node;
- /**
- 管理 event listener 服务以及事件分发 (event dispatching).
- The EventListener list is managed in such a way that
- event listeners can be added and removed even
- from within an EventListener, while events are being
- dispatched.
- */
- class EventDispatcher : public Object
- {
- public:
- /** 注册监听事件 (优先级 基于 Node绘制顺序 )
- * 在消息路由时,先处理优先级<0的,在处理优先级=0(按Node绘制顺序),最后处理优先级>0的
- * @param listener 监听器
- * @param node 监听的node
- * @note fixedProprity必须是0
- */
- void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);
- /** 注册监听事件 (指定优先级)
- * @param listener The listener of a specified event.
- * @param fixedPriority The fixed priority of the listener.
- * @note A lower priority will be called before the ones that have a higher value.
- * 0 priority is forbidden for fixed priority since it's used for scene graph based priority.
- */
- void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);
- /** 删除某一个监听器
- * @param listener The specified event listener which needs to be removed.
- */
- void removeEventListener(EventListener* listener);
- /** 删除某一类监听器 */
- void removeEventListeners(EventListener::Type listenerType);
- /** Removes all custom listeners with the same event name */
- void removeCustomEventListeners(const std::string& customEventName);
- /** 删除所有监听器 */
- void removeAllEventListeners();
- /** 修改某监听器的优先级 */
- void setPriority(EventListener* listener, int fixedPriority);
- /** 设置事件分发器是否可用 */
- void setEnabled(bool isEnabled);
- /** Checks whether dispatching events is enabled */
- bool isEnabled() const;
- /** 分发事件
- * 同时从dispatcher list 中删除标记为deletion的监听器
- */
- void dispatchEvent(Event* event);
- /** Constructor of EventDispatcher */
- EventDispatcher();
- /** Destructor of EventDispatcher */
- ~EventDispatcher();
- private:
- friend class Node;
- /** 将Node记为Dirty
- 即将Node加入_dirtyNodes*/
- void setDirtyForNode(Node* node);
- /** 跟node相关联的所有listener都暂停 */
- void pauseTarget(Node* node);
- /** 跟node相关联的所有listener都唤醒 */
- void resumeTarget(Node* node);
- /** 删除所有跟node相关联的listener */
- void cleanTarget(Node* node);
- /**
- * The vector to store event listeners with scene graph based priority and fixed priority.
- */
- 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 long getGt0Index() const { return _gt0Index; };
- inline void setGt0Index(long index) { _gt0Index = index; };
- private:
- std::vector<EventListener*>* _fixedListeners;
- std::vector<EventListener*>* _sceneGraphListeners;
- long _gt0Index;
- };
- /** Adds event listener with item */
- void addEventListener(EventListener* listener);
- /** Gets event the listener list for the event listener type. */
- EventListenerVector* getListeners(EventListener::ListenerID listenerID);
- /** Update dirty flag */
- void updateDirtyFlagForSceneGraph();
- /** Removes all listeners with the same event listener ID */
- void removeEventListenersForListenerID(EventListener::ListenerID listenerID);
- /** 排序 */
- void sortEventListeners(EventListener::ListenerID listenerID);
- /** 根据node优先级排序 */
- void sortEventListenersOfSceneGraphPriority(EventListener::ListenerID listenerID);
- /** 根据优先级排序 */
- void sortEventListenersOfFixedPriority(EventListener::ListenerID listenerID);
- /** Updates all listeners
- * 1) 删除所有标记为 deleted 的监听器.
- * 2) 添加_toAddedListeners中的监听器.
- */
- void updateListeners(Event* event);
- /** Touch event needs to be processed different with other events since it needs support ALL_AT_ONCE and ONE_BY_NONE mode. */
- void dispatchTouchEvent(EventTouch* event);
- /** Associates node with event listener */
- void associateNodeAndEventListener(Node* node, EventListener* listener);
- /** Dissociates node with event listener */
- void dissociateNodeAndEventListener(Node* node, EventListener* listener);
- /** Dispatches event to listeners with a specified listener type */
- void dispatchEventToListeners(EventListenerVector* listeners, std::function<bool(EventListener*)> onEvent);
- /// Priority dirty flag
- enum class DirtyFlag
- {
- NONE = 0,
- FIXED_PRITORY = 1 << 0,
- SCENE_GRAPH_PRIORITY = 1 << 1,
- ALL = FIXED_PRITORY | SCENE_GRAPH_PRIORITY
- };
- /** Sets the dirty flag for a specified listener ID */
- void setDirty(EventListener::ListenerID listenerID, DirtyFlag flag);
- /** 遍历场景,获取每个Node的绘制顺序;
- 此函数在sortEventListenersOfSceneGraphPriority之前调用 */
- void visitTarget(Node* node);
- private:
- /** map 存储所有监听器 map::key 监听器类型 */
- std::unordered_map<EventListener::ListenerID, EventListenerVector*> _listeners;
- /** map 存储一类监听器是否被污染。
- 即:按优先级分类,可以把所有监听器分为两类(Node, fixd priority)。
- 如果_listenner[type] 里的监听器全是Node priority, 则DirtyFlag为SCENE_GRAPH_PRIORITY;
- 若全为fixd priority 则为 FIXED_PRITORY;若两种都有, 则为ALL = FIXED_PRITORY | SCENE_GRAPH_PRIORITY */
- std::unordered_map<EventListener::ListenerID, DirtyFlag> _priorityDirtyFlagMap;
- /** map 关联Node与监听器 */
- std::unordered_map<Node*, std::vector<EventListener*>*> _nodeListenersMap;
- /** 存储每个Node的优先级(即绘制顺序);
- 在visitTarge中更新该值,
- 在sortEventListenersOfSceneGraphPriority中使用该值*/
- std::unordered_map<Node*, int> _nodePriorityMap;
- /** 如果注册监听器时正在dispathch event,则将该监听器加到_toAddedListeners中,
- 等dispatch完成后,在将其从_toAddedListeners中移到其他容器,*/
- std::vector<EventListener*> _toAddedListeners;
- /** 优先级发生改变的Node
- 此集合中的Node所对应的Listener所在的那个vector(_listeners[ID])将会重排序*/
- std::set<Node*> _dirtyNodes;
- /** 判断是否正在dispatch */
- int _inDispatch;
- /** Whether to enable dispatching event */
- bool _isEnabled;
- int _nodePriorityIndex;
- };
- NS_CC_END
- #endif // __CC_EVENT_DISPATCHER_H__
- cpp
- #include "CCEventDispatcher.h"
- #include "CCEvent.h"
- #include "CCEventTouch.h"
- #include "CCEventCustom.h"
- #include "CCEventListenerTouch.h"
- #include "CCNode.h"
- #include "CCDirector.h"
- #include <algorithm>
- #define DUMP_LISTENER_ITEM_PRIORITY_INFO 0
- namespace
- {
- /************************************************************************/
- /* 用于自动处理count。 一般用于构造一个局部变量。与指针计数器原理相同。
- 构造时 +1,
- 析构时 -1.
- 若函数中有多处return,而每次renturn前都要处理某变量的值,则可以采用此机制优化代码;
- 此机制只需利用变量a构造一个局部变量, 无需在每次返回前再处理变量a。
- */
- class DispatchGuard
- {
- public:
- DispatchGuard(int& count) :
- _count(count)
- {
- ++_count;
- }
- ~DispatchGuard()
- {
- --_count;
- }
- private:
- int& _count;
- };
- }
- NS_CC_BEGIN
- // 根据Event 的type 确定EventListener的Type
- // 关于EventListener的ListenerId 与 EventListener的Type(注意这里不是Event::Type)映射关系
- // 出自定制类型外,其他类型都是用枚举一一映射的,而自定制类型则是计算hash值
- static EventListener::ListenerID getListenerID(Event* event)
- {
- EventListener::ListenerID ret;
- switch (event->getType())
- {
- case Event::Type::ACCELERATION:
- ret = static_cast<EventListener::ListenerID>(EventListener::Type::ACCELERATION);
- break;
- case Event::Type::CUSTOM:
- {
- auto customEvent = static_cast<EventCustom*>(event);
- auto listenerID = std::hash<std::string>()(customEvent->getEventName());
- ret = static_cast<EventListener::ListenerID>(listenerID);
- }
- break;
- case Event::Type::KEYBOARD:
- ret = static_cast<EventListener::ListenerID>(EventListener::Type::KEYBOARD);
- break;
- case Event::Type::MOUSE:
- ret = static_cast<EventListener::ListenerID>(EventListener::Type::MOUSE);
- break;
- case Event::Type::TOUCH:
- // Touch listener is very special, it contains two kinds of listeners, EventListenerTouchOneByOne and EventListenerTouchAllAtOnce.
- // return UNKNOW instead.
- ret = static_cast<EventListener::ListenerID>(EventListener::Type::UNKNOWN);
- break;
- default:
- CCASSERT(false, "Invalid type!");
- break;
- }
- return ret;
- }
- EventDispatcher::EventListenerVector::EventListenerVector()
- : _sceneGraphListeners(nullptr)
- , _fixedListeners(nullptr)
- , _gt0Index(0)
- {
- }
- EventDispatcher::EventListenerVector::~EventListenerVector()
- {
- CC_SAFE_DELETE(_sceneGraphListeners);
- CC_SAFE_DELETE(_fixedListeners);
- }
- size_t EventDispatcher::EventListenerVector::size() const
- {
- size_t ret = 0;
- if (_sceneGraphListeners)
- ret += _sceneGraphListeners->size();
- if (_fixedListeners)
- ret += _fixedListeners->size();
- return ret;
- }
- bool EventDispatcher::EventListenerVector::empty() const
- {
- return (_sceneGraphListeners == nullptr || _sceneGraphListeners->empty())
- && (_fixedListeners == nullptr || _fixedListeners->empty());
- }
- 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);
- }
- }
- void EventDispatcher::EventListenerVector::clearSceneGraphListeners()
- {
- if (_sceneGraphListeners)
- {
- _sceneGraphListeners->clear();
- delete _sceneGraphListeners;
- _sceneGraphListeners = nullptr;
- }
- }
- void EventDispatcher::EventListenerVector::clearFixedListeners()
- {
- if (_fixedListeners)
- {
- _fixedListeners->clear();
- delete _fixedListeners;
- _fixedListeners = nullptr;
- }
- }
- void EventDispatcher::EventListenerVector::clear()
- {
- clearSceneGraphListeners();
- clearFixedListeners();
- }
- EventDispatcher::EventDispatcher()
- : _inDispatch(0)
- , _isEnabled(true)
- , _nodePriorityIndex(0)
- {
- _toAddedListeners.reserve(50);
- }
- EventDispatcher::~EventDispatcher()
- {
- removeAllEventListeners();
- }
- void EventDispatcher::visitTarget(Node* node)
- {
- int i = 0;
- Array* children = node->getChildren();
- int childrenCount = children ? children->count() : 0;
- if (childrenCount > 0)
- {
- Node* child = nullptr;
- // 只计算子节点中 zOrder < 0 的
- for (; i < childrenCount; i++)
- {
- child = static_cast<Node*>(children->getObjectAtIndex(i));
- if (child && child->getZOrder() < 0)
- visitTarget(child);
- else
- break;
- }
- // 记录Node的优先级
- _nodePriorityMap.insert(std::make_pair(node, ++_nodePriorityIndex));
- for (; i < childrenCount; i++)
- {
- child = static_cast<Node*>(children->getObjectAtIndex(i));
- if (child)
- visitTarget(child);
- }
- }
- else
- {
- _nodePriorityMap.insert(std::make_pair(node, ++_nodePriorityIndex));
- }
- }
- void EventDispatcher::pauseTarget(Node* node)
- {
- auto listenerIter = _nodeListenersMap.find(node);
- if (listenerIter != _nodeListenersMap.end())
- {
- auto listeners = listenerIter->second;
- for (auto& l : *listeners)
- {
- l->setPaused(true);
- }
- }
- }
- void EventDispatcher::resumeTarget(Node* node)
- {
- auto listenerIter = _nodeListenersMap.find(node);
- if (listenerIter != _nodeListenersMap.end())
- {
- auto listeners = listenerIter->second;
- for (auto& l : *listeners)
- {
- l->setPaused(false);
- }
- }
- setDirtyForNode(node);
- }
- void EventDispatcher::cleanTarget(Node* node)
- {
- auto listenerIter = _nodeListenersMap.find(node);
- if (listenerIter != _nodeListenersMap.end())
- {
- auto listeners = listenerIter->second;
- auto listenersCopy = *listeners;
- for (auto& l : listenersCopy)
- {
- removeEventListener(l);
- }
- }
- }
- 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*>();
- }
- listeners->push_back(listener);
- _nodeListenersMap.insert(std::make_pair(node, listeners));
- }
- void EventDispatcher::dissociateNodeAndEventListener(Node* node, EventListener* listener)
- {
- std::vector<EventListener*>* listeners = nullptr;
- auto found = _nodeListenersMap.find(node);
- if (found != _nodeListenersMap.end())
- {
- listeners = found->second;
- auto iter = std::find(listeners->begin(), listeners->end(), listener);
- if (iter != listeners->end())
- {
- listeners->erase(iter);
- }
- if (listeners->empty())
- {
- _nodeListenersMap.erase(found);
- delete listeners;
- }
- }
- }
- void EventDispatcher::addEventListener(EventListener* listener)
- {
- // 如果不是正在路由事件
- if (_inDispatch == 0)
- {
- EventListenerVector* listenerList = nullptr;
- // 根据listenerID获取相应vector
- auto iter = _listeners.find(listener->getListenerID());
- if (iter == _listeners.end())
- {
- listenerList = new EventListenerVector();
- _listeners.insert(std::make_pair(listener->getListenerID(), listenerList));
- }
- else
- {
- listenerList = iter->second;
- }
- listenerList->push_back(listener);
- if (listener->getFixedPriority() == 0)
- {
- // 如果优先级根据Node而定
- setDirty(listener->getListenerID(), DirtyFlag::SCENE_GRAPH_PRIORITY);
- }
- else
- {
- // 如果优先级根据Fixed而定
- setDirty(listener->getListenerID(), DirtyFlag::FIXED_PRITORY);
- }
- }
- else
- {
- // 如果正在路由事件,则直接加入_toAddedListeners
- _toAddedListeners.push_back(listener);
- }
- }
- 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->setSceneGraphPriority(node);
- listener->setFixedPriority(0);
- listener->setRegistered(true);
- listener->retain();
- // 存储listener,
- addEventListener(listener);
- // 关联node与listener
- associateNodeAndEventListener(node, listener);
- if (node->isRunning())
- {
- resumeTarget(node);
- }
- }
- 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->setSceneGraphPriority(nullptr);
- listener->setFixedPriority(fixedPriority);
- listener->setRegistered(true);
- listener->setPaused(false);
- listener->retain();
- addEventListener(listener);
- }
- void EventDispatcher::removeEventListener(EventListener* listener)
- {
- if (listener == nullptr)
- return;
- bool isFound = false;
- auto removeListenerInVector = [&](std::vector<EventListener*>* listeners){
- if (listeners == nullptr)
- return;
- for (auto iter = listeners->begin(); iter != listeners->end(); ++iter)
- {
- auto l = *iter;
- if (l == listener)
- {
- CC_SAFE_RETAIN(l);
- l->setRegistered(false);
- if (l->getSceneGraphPriority() != nullptr)
- {
- // 撤销node与listener的关联
- dissociateNodeAndEventListener(l->getSceneGraphPriority(), l);
- }
- if (_inDispatch == 0)
- {
- listeners->erase(iter);
- CC_SAFE_RELEASE(l);
- }
- isFound = true;
- break;
- }
- }
- };
- for (auto iter = _listeners.begin(); iter != _listeners.end();)
- {
- auto listeners = iter->second;
- auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
- auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
- removeListenerInVector(sceneGraphPriorityListeners);
- if (!isFound)
- {
- removeListenerInVector(fixedPriorityListeners);
- }
- if (iter->second->empty())
- {
- _priorityDirtyFlagMap.erase(listener->getListenerID());
- auto list = iter->second;
- iter = _listeners.erase(iter);
- CC_SAFE_DELETE(list);
- }
- else
- {
- ++iter;
- }
- if (isFound)
- break;
- }
- if (isFound)
- {
- CC_SAFE_RELEASE(listener);
- }
- else
- {
- // 若没有找到,则在_toAddedListeners中找
- for (auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end(); ++iter)
- {
- if (*iter == listener)
- {
- _toAddedListeners.erase(iter);
- break;
- }
- }
- }
- }
- void EventDispatcher::setPriority(EventListener* listener, int fixedPriority)
- {
- if (listener == nullptr)
- return;
- for (auto iter = _listeners.begin(); iter != _listeners.end(); ++iter)
- {
- auto fixedPriorityListeners = iter->second->getFixedPriorityListeners();
- if (fixedPriorityListeners)
- {
- auto found = std::find(fixedPriorityListeners->begin(), fixedPriorityListeners->end(), listener);
- if (found != fixedPriorityListeners->end())
- {
- CCASSERT(listener->getSceneGraphPriority() == nullptr, "Can't set fixed priority with scene graph based listener.");
- if (listener->getFixedPriority() != fixedPriority)
- {
- listener->setFixedPriority(fixedPriority);
- setDirty(listener->getListenerID(), DirtyFlag::FIXED_PRITORY);
- }
- return;
- }
- }
- }
- }
- void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners, std::function<bool(EventListener*)> onEvent)
- {
- bool shouldStopPropagation = false;
- auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
- auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
- long i = 0;
- // priority < 0
- if (fixedPriorityListeners)
- {
- for (; !fixedPriorityListeners->empty() && i < listeners->getGt0Index(); ++i)
- {
- auto l = fixedPriorityListeners->at(i);
- if (!l->isPaused() && l->isRegistered() && onEvent(l))
- {
- shouldStopPropagation = true;
- break;
- }
- }
- }
- if (sceneGraphPriorityListeners)
- {
- if (!shouldStopPropagation)
- {
- // priority == 0, scene graph priority
- for (auto& l : *sceneGraphPriorityListeners)
- {
- if (!l->isPaused() && l->isRegistered() && onEvent(l))
- {
- shouldStopPropagation = true;
- break;
- }
- }
- }
- }
- if (fixedPriorityListeners)
- {
- if (!shouldStopPropagation)
- {
- // priority > 0
- for (; i < static_cast<long>(fixedPriorityListeners->size()); ++i)
- {
- auto l = fixedPriorityListeners->at(i);
- if (!l->isPaused() && l->isRegistered() && onEvent(fixedPriorityListeners->at(i)))
- {
- shouldStopPropagation = true;
- break;
- }
- }
- }
- }
- }
- 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 = _listeners.find(listenerID);
- if (iter != _listeners.end())
- {
- auto listeners = iter->second;
- auto onEvent = [&event](EventListener* listener) -> bool{
- event->setCurrentTarget(listener->getSceneGraphPriority());
- listener->_onEvent(event);
- return event->isStopped();
- };
- dispatchEventToListeners(listeners, onEvent);
- }
- updateListeners(event);
- }
- void EventDispatcher::dispatchTouchEvent(EventTouch* event)
- {
- auto touchOneByOneID = static_cast<EventListener::ListenerID>(EventListener::Type::TOUCH_ONE_BY_ONE);
- auto touchAllAtOnceID = static_cast<EventListener::ListenerID>(EventListener::Type::TOUCH_ALL_AT_ONCE);
- sortEventListeners(touchOneByOneID);
- sortEventListeners(touchAllAtOnceID);
- auto oneByOnelisteners = getListeners(touchOneByOneID);
- auto allAtOncelisteners = getListeners(touchAllAtOnceID);
- // 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 false;
- }
- return false;
- };
- dispatchEventToListeners(allAtOncelisteners, onTouchesEvent);
- if (event->isStopped())
- {
- return;
- }
- }
- updateListeners(event);
- }
- void EventDispatcher::updateListeners(Event* event)
- {
- auto onUpdateListeners = [this](EventListener::ListenerID listenerID)
- {
- auto listenersIter = _listeners.find(listenerID);
- if (listenersIter == _listeners.end())
- return;
- auto listeners = listenersIter->second;
- auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
- auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
- if (sceneGraphPriorityListeners)
- {
- for (auto iter = sceneGraphPriorityListeners->begin(); iter != sceneGraphPriorityListeners->end();)
- {
- auto l = *iter;
- if (!l->isRegistered())
- {
- iter = sceneGraphPriorityListeners->erase(iter);
- l->release();
- }
- else
- {
- ++iter;
- }
- }
- }
- if (fixedPriorityListeners)
- {
- for (auto iter = fixedPriorityListeners->begin(); iter != fixedPriorityListeners->end();)
- {
- auto l = *iter;
- if (!l->isRegistered())
- {
- iter = fixedPriorityListeners->erase(iter);
- l->release();
- }
- else
- {
- ++iter;
- }
- }
- }
- if (sceneGraphPriorityListeners && sceneGraphPriorityListeners->empty())
- {
- listeners->clearSceneGraphListeners();
- }
- if (fixedPriorityListeners && fixedPriorityListeners->empty())
- {
- listeners->clearFixedListeners();
- }
- if (listenersIter->second->empty())
- {
- _priorityDirtyFlagMap.erase(listenersIter->first);
- delete listenersIter->second;
- listenersIter = _listeners.erase(listenersIter);
- }
- else
- {
- ++listenersIter;
- }
- };
- if (event->getType() == Event::Type::TOUCH)
- {
- onUpdateListeners(static_cast<EventListener::ListenerID>(EventListener::Type::TOUCH_ONE_BY_ONE));
- onUpdateListeners(static_cast<EventListener::ListenerID>(EventListener::Type::TOUCH_ALL_AT_ONCE));
- }
- else
- {
- onUpdateListeners(getListenerID(event));
- }
- if (!_toAddedListeners.empty())
- {
- EventListenerVector* listeners = nullptr;
- for (auto& listener : _toAddedListeners)
- {
- EventListener::ListenerID listenerID = listener->getListenerID();
- auto itr = _listeners.find(listenerID);
- if (itr == _listeners.end())
- {
- listeners = new EventListenerVector();
- _listeners.insert(std::make_pair(listenerID, listeners));
- }
- else
- {
- listeners = itr->second;
- }
- listeners->push_back(listener);
- if (listener->getFixedPriority() == 0)
- {
- setDirty(listenerID, DirtyFlag::SCENE_GRAPH_PRIORITY);
- }
- else
- {
- setDirty(listenerID, DirtyFlag::FIXED_PRITORY);
- }
- }
- _toAddedListeners.clear();
- }
- }
- void EventDispatcher::updateDirtyFlagForSceneGraph()
- {
- if (!_dirtyNodes.empty())
- {
- for (auto& node : _dirtyNodes)
- {
- auto iter = _nodeListenersMap.find(node);
- if (iter != _nodeListenersMap.end())
- {
- for (auto& l : *iter->second)
- {
- setDirty(l->getListenerID(), DirtyFlag::SCENE_GRAPH_PRIORITY);
- }
- }
- }
- _dirtyNodes.clear();
- }
- }
- void EventDispatcher::sortEventListeners(EventListener::ListenerID listenerID)
- {
- DirtyFlag dirtyFlag = DirtyFlag::NONE;
- auto dirtyIter = _priorityDirtyFlagMap.find(listenerID);
- if (dirtyIter != _priorityDirtyFlagMap.end())
- {
- dirtyFlag = dirtyIter->second;
- }
- if (dirtyFlag != DirtyFlag::NONE)
- {
- if ((int)dirtyFlag & (int)DirtyFlag::FIXED_PRITORY)
- {
- sortEventListenersOfFixedPriority(listenerID);
- }
- if ((int)dirtyFlag & (int)DirtyFlag::SCENE_GRAPH_PRIORITY)
- {
- sortEventListenersOfSceneGraphPriority(listenerID);
- }
- dirtyIter->second = DirtyFlag::NONE;
- }
- }
- void EventDispatcher::sortEventListenersOfSceneGraphPriority(EventListener::ListenerID listenerID)
- {
- auto listeners = getListeners(listenerID);
- if (listeners == nullptr)
- return;
- Node* rootNode = (Node*)Director::getInstance()->getRunningScene();
- // Reset priority index
- _nodePriorityIndex = 0;
- _nodePriorityMap.clear();
- visitTarget(rootNode);
- // After sort: priority < 0, > 0
- auto sceneGraphlisteners = listeners->getSceneGraphPriorityListeners();
- std::sort(sceneGraphlisteners->begin(), sceneGraphlisteners->end(), [this](const EventListener* l1, const EventListener* l2) {
- return _nodePriorityMap[l1->getSceneGraphPriority()] > _nodePriorityMap[l2->getSceneGraphPriority()];
- });
- #if DUMP_LISTENER_ITEM_PRIORITY_INFO
- log("-----------------------------------");
- for (auto& l : *sceneGraphlisteners)
- {
- log("listener priority: node ([%s]%p), priority (%d)", typeid(*l->_node).name(), l->_node, _nodePriorityMap[l->_node]);
- }
- #endif
- }
- void EventDispatcher::sortEventListenersOfFixedPriority(EventListener::ListenerID listenerID)
- {
- auto listeners = getListeners(listenerID);
- if (listeners == nullptr)
- return;
- // After sort: priority < 0, > 0
- auto fixedlisteners = listeners->getFixedPriorityListeners();
- std::sort(fixedlisteners->begin(), fixedlisteners->end(), [](const EventListener* l1, const EventListener* l2) {
- return l1->getFixedPriority() < l2->getFixedPriority();
- });
- // FIXME: Should use binary search
- long index = 0;
- for (auto& listener : *fixedlisteners)
- {
- if (listener->getFixedPriority() >= 0)
- break;
- ++index;
- }
- listeners->setGt0Index(index);
- #if DUMP_LISTENER_ITEM_PRIORITY_INFO
- log("-----------------------------------");
- for (auto& l : *fixedlisteners)
- {
- log("listener priority: node (%p), fixed (%d)", l->_node, l->_fixedPriority);
- }
- #endif
- }
- EventDispatcher::EventListenerVector* EventDispatcher::getListeners(EventListener::ListenerID listenerID)
- {
- auto iter = _listeners.find(listenerID);
- if (iter != _listeners.end())
- {
- return iter->second;
- }
- return nullptr;
- }
- void EventDispatcher::removeEventListenersForListenerID(EventListener::ListenerID listenerID)
- {
- auto listenerItemIter = _listeners.find(listenerID);
- if (listenerItemIter != _listeners.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->getSceneGraphPriority() != nullptr)
- {
- dissociateNodeAndEventListener(l->getSceneGraphPriority(), l);
- }
- if (_inDispatch == 0)
- {
- iter = listenerVector->erase(iter);
- CC_SAFE_RELEASE(l);
- }
- else
- {
- ++iter;
- }
- }
- };
- removeAllListenersInVector(sceneGraphPriorityListeners);
- removeAllListenersInVector(fixedPriorityListeners);
- if (!_inDispatch)
- {
- listeners->clear();
- delete listeners;
- _listeners.erase(listenerItemIter);
- _priorityDirtyFlagMap.erase(listenerID);
- }
- }
- for (auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end();)
- {
- if ((*iter)->getListenerID() == listenerID)
- {
- iter = _toAddedListeners.erase(iter);
- }
- else
- {
- ++iter;
- }
- }
- }
- void EventDispatcher::removeEventListeners(EventListener::Type listenerType)
- {
- CCASSERT(listenerType != EventListener::Type::CUSTOM, "Not support custom event listener type, please use EventDispatcher::removeCustomEventListeners instead.");
- removeEventListenersForListenerID(static_cast<EventListener::ListenerID>(listenerType));
- }
- void EventDispatcher::removeCustomEventListeners(const std::string& customEventName)
- {
- removeEventListenersForListenerID(std::hash<std::string>()(customEventName));
- }
- void EventDispatcher::removeAllEventListeners()
- {
- std::vector<int> types(_listeners.size());
- for (auto iter = _listeners.begin(); iter != _listeners.end(); ++iter)
- {
- types.push_back(iter->first);
- }
- for (auto& type : types)
- {
- removeEventListenersForListenerID(type);
- }
- if (!_inDispatch)
- {
- _listeners.clear();
- }
- }
- void EventDispatcher::setEnabled(bool isEnabled)
- {
- _isEnabled = isEnabled;
- }
- bool EventDispatcher::isEnabled() const
- {
- return _isEnabled;
- }
- void EventDispatcher::setDirtyForNode(Node* node)
- {
- // Mark the node dirty only when there was an eventlistener associates with it.
- if (_nodeListenersMap.find(node) != _nodeListenersMap.end())
- {
- _dirtyNodes.insert(node);
- }
- }
- void EventDispatcher::setDirty(EventListener::ListenerID listenerID, DirtyFlag flag)
- {
- auto iter = _priorityDirtyFlagMap.find(listenerID);
- if (iter == _priorityDirtyFlagMap.end())
- {
- _priorityDirtyFlagMap.insert(std::make_pair(listenerID, flag));
- }
- else
- {
- int ret = (int)flag | (int)iter->second;
- iter->second = (DirtyFlag)ret;
- }
- }
- NS_CC_END
- </pre><br>
- <br>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- </pre></pre></pre></pre></pre>
0 0
- cocos2dx-3.0 : EventDispatcher
- cocos2dx-3.0 : EventDispatcher
- Cocos2dx - EventDispatcher事件分发器学习
- cocos2dx源码分析:事件派发器EventDispatcher
- coco2dx 3.0 EventDispatcher事件派发
- EventDispatcher Mechanism
- 关于EventDispatcher的讨论
- Flex EventDispatcher类
- eventDispatcher 简单使用
- cocos2dx3.5 EventDispatcher
- EventDispatcher事件分发机制
- symfony2 EventDispatcher组件使用
- UE4发报机-EventDispatcher绑定事件
- 虚幻4 Event、CustomEvent、EventDispatcher
- Cocos2d-x 事件处理EventDispatcher
- 事件分发(EventDispatcher)模式
- EventDispatcher的比喻(转自AS3CN)
- unity中事件分发系统 EventDispatcher
- ZtreeAsyncMasterFile(zTree大数据量分批次异步加载)
- Android自动化测试(UiAutomator)简要介绍 完整版本
- hdu 1251 字典树
- JVM常量池和八种基本数据及字符串
- java深浅拷贝
- cocos2dx-3.0 : EventDispatcher
- jquery checkbox checked 第一次有效果 第二次以后就不好用了
- 《java短串的生成》
- gem 源切换(尤其是在中国,官网源有可能会有很大的问题)
- 解决MySQL中文乱码问题
- jsp与jsp页面传值数值。
- MFC编程,图形的重绘方法总结
- 深入探讨PageRank
- javascript必知必会之prototype