cocos2dx-3.0 : EventDispatcher

.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
























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值