从零开始のcocos2dx生活(六)EventDispatcher
EventDispatcher可能是所有的里面比较不容易理解也不容易看的
我说自己的理解可能会误导到你们…【索了你们看不下去><
我写了几乎所有的代码的注释,有的是废话跳过就好
主要的代码是在dispatchEvent中,然后再进入不同的函数中
dispatchTouchEvent
dispatchTouchEventToListeners
dispatchEventToListeners
都是很重要的逻辑代码,可以多看几遍,加深理解
然后直接看代码吧
//触摸不使用这个方法获取
static EventListener::ListenerID __getListenerID(Event* event)
{
EventListener::ListenerID ret;
switch (event->getType())
{
case Event::Type::ACCELERATION:
ret = EventListenerAcceleration::LISTENER_ID;
break;
case Event::Type::CUSTOM:
{
auto customEvent = static_cast<EventCustom*>(event);
ret = customEvent->getEventName();
}
break;
case Event::Type::KEYBOARD:
ret = EventListenerKeyboard::LISTENER_ID;
break;
case Event::Type::MOUSE:
ret = EventListenerMouse::LISTENER_ID;
break;
case Event::Type::FOCUS:
ret = EventListenerFocus::LISTENER_ID;
break;
case Event::Type::TOUCH:
// Touch listener is very special, it contains two kinds of listeners, EventListenerTouchOneByOne and EventListenerTouchAllAtOnce.
// return UNKNOWN instead.
CCASSERT(false, "Don't call this method if the event is for touch.");
break;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_LINUX || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
case Event::Type::GAME_CONTROLLER:
ret = EventListenerController::LISTENER_ID;
break;
#endif
default:
CCASSERT(false, "Invalid type!");
break;
}
return ret;
}
EventDispatcher::EventListenerVector::EventListenerVector() :
_fixedListeners(nullptr),
_sceneGraphListeners(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 CC_NODE_DEBUG_VERIFY_EVENT_LISTENERS
CCASSERT(_sceneGraphListeners == nullptr ||
std::count(_sceneGraphListeners->begin(), _sceneGraphListeners->end(), listener) == 0,
"Listener should not be added twice!");
CCASSERT(_fixedListeners == nullptr ||
std::count(_fixedListeners->begin(), _fixedListeners->end(), listener) == 0,
"Listener should not be added twice!");
#endif
if (listener->getFixedPriority() == 0)
{
if (_sceneGraphListeners == nullptr)
{
_sceneGraphListeners = new (std::nothrow) 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()
{
//这里的delete只是删除了_sceneGraphListeners指针指向的目标,不是指针本身,之后又把它置空了
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(false)
, _nodePriorityIndex(0)
{
_toAddedListeners.reserve(50);
_toRemovedListeners.reserve(50);
// fixed #4129: Mark the following listener IDs for internal use.
// Therefore, internal listeners would not be cleaned when removeAllEventListeners is invoked.
_internalCustomListenerIDs.insert(EVENT_COME_TO_FOREGROUND);
_internalCustomListenerIDs.insert(EVENT_COME_TO_BACKGROUND);
_internalCustomListenerIDs.insert(EVENT_RENDERER_RECREATED);
}
EventDispatcher::~EventDispatcher()
{
// Clear internal custom listener IDs from set,
// so removeAllEventListeners would clean internal custom listeners.
_internalCustomListenerIDs.clear();
removeAllEventListeners();
}
void EventDispatcher::visitTarget(Node* node, bool isRootNode)
{
//给所有的字节点排序
node->sortAllChildren();
int i = 0;
auto& children = node->getChildren();
auto childrenCount = children.size();
//中序遍历并添加相对的父节点到_globalZOrderNodeMap中
if(childrenCount > 0)
{
Node* child = nullptr;
//遍历zorder<0的节点
// visit children zOrder < 0
for( ; i < childrenCount; i++ )
{
child = children.at(i);
if ( child && child->getLocalZOrder() < 0 )
visitTarget(child, false);
else
break;
}
//将相对的父节点加入到_globalZOrderNodeMap中
if (_nodeListenersMap.find(node) != _nodeListenersMap.end())
{
_globalZOrderNodeMap[node->getGlobalZOrder()].push_back(node);
}
//遍历zorder>0的节点
for( ; i < childrenCount; i++ )
{
child = children.at(i);
if (child)
visitTarget(child, false);
}
}
//如果没有子节点,将自己加入到_globalZOrderNodeMap中
else
{
if (_nodeListenersMap.find(node) != _nodeListenersMap.end())
{
_globalZOrderNodeMap[node->getGlobalZOrder()].push_back(node);
}
}
//形参isRootNode如果是true
if (isRootNode)
{
std::vector<float> globalZOrders;
globalZOrders.reserve(_globalZOrderNodeMap.size());
//获取所有的优先级等级
for (const auto& e : _globalZOrderNodeMap)
{
globalZOrders.push_back(e.first);
}
//稳定排序,排序完成后,相同的数相对位置不发生改变
std::stable_sort(globalZOrders.begin(), globalZOrders.end(), [](const float a, const float b){
return a < b;
});
//遍历所有的zorder
for (const auto& globalZ : globalZOrders)
{
//遍历所有zorder对应的node
for (const auto& n : _globalZOrderNodeMap[globalZ])
{
//设置每个节点的优先级,存储在_nodePriorityMap
_nodePriorityMap[n] = ++_nodePriorityIndex;
}
}
//这个全局变量只是一个中间值,用来存储globalZOrder和Node的关系,用完之后需要重置
_globalZOrderNodeMap.clear();
}
}
//暂停target对应的listener
void EventDispatcher::pauseEventListenersForTarget(Node* target, bool recursive/* = false */)
{
//找到它,暂停它
auto listenerIter = _nodeListenersMap.find(target);
if (listenerIter != _nodeListenersMap.end())
{
auto listeners = listenerIter->second;
for (auto& l : *listeners)
{
l->setPaused(true);
}
}
//如果在_toAddedListeners中,还未添加,那也暂停它
for (auto& listener : _toAddedListeners)
{
if (listener->getAssociatedNode() == target)
{
listener->setPaused(true);
}
}
//子节点根据形参也暂停或者不暂停
if (recursive)
{
const auto& children = target->getChildren();
for (const auto& child : children)
{
pauseEventListenersForTarget(child, true);
}
}
}
//恢复target的listener
void EventDispatcher::resumeEventListenersForTarget(Node* target, bool recursive/* = false */)
{
auto listenerIter = _nodeListenersMap.find(target);
if (listenerIter != _nodeListenersMap.end())
{
auto listeners = listenerIter->second;
for (auto& l : *listeners)
{
l->setPaused(false);
}
}
//如果在_toAddedListeners中,还未添加,那也恢复它
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);
}
}
}
//根据target移除对应的listener
void EventDispatcher::removeEventListenersForTarget(Node* target, bool recursive/* = false */)
{
// Ensure the node is removed from these immediately also.
// Don't want any dangling pointers or the possibility of dealing with deleted objects..
//从节点-优先级map中移除,并且也从脏节点容器中移除,确保不会再被访问
_nodePriorityMap.erase(target);
_dirtyNodes.erase(target);
//找到节点-监听器map中的target,将它对应的监听器数组全部移除
auto listenerIter = _nodeListenersMap.find(target);
if (listenerIter != _nodeListenersMap.end())
{
auto listeners = listenerIter->second;
auto listenersCopy = *listeners;
for (auto& l : listenersCopy)
{
removeEventListener(l);
}
}
// Bug fix: ensure there are no references to the node in the list of listeners to be added.
// If we find any listeners associated with the destroyed node in this list then remove them.
// This is to catch the scenario where the node gets destroyed before it's listener
// is added into the event dispatcher fully. This could happen if a node registers a listener
// and gets destroyed while we are dispatching an event (touch etc.)
//从要添加的监听器列表中移除,也是为了确保不会再访问这个移除的节点
for (auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end(); )
{
EventListener * listener = *iter;
if (listener->getAssociatedNode() == target)
{
listener->setAssociatedNode(nullptr); // Ensure no dangling ptr to the target node.
listener->setRegistered(false);
releaseListener(listener);
iter = _toAddedListeners.erase(iter); //返回删除iter后一个元素
}
else
{
++iter;
}
}
//是否对子节点遍历移除
if (recursive)
{
const auto& children = target->getChildren();
for (const auto& child : children)
{
removeEventListenersForTarget(child, true);
}
}
}
//将节点和监听器链接起来
void EventDispatcher::associateNodeAndEventListener(Node* node, EventListener* listener)
{
std::vector<EventListener*>* listeners = nullptr;
//查找nodeListenerMap中是否已经有了要链接的node
auto found = _nodeListenersMap.find(node);
//如果找到了,就获取它对应的listener数组
if (found != _nodeListenersMap.end())
{
listeners = found->second;
}
//没找到就创建一个存放监听器的数组,并将node和监听器空数组加入_nodeListenersMap中,
else
{
listeners = new (std::nothrow) std::vector<EventListener*>();
_nodeListenersMap.emplace(node, listeners);
}
//将想要添加的监听器加入到与节点关联的监听器数组中
listeners->push_back(listener);
}
//解除节点和监听器的关联
void EventDispatcher::dissociateNodeAndEventListener(Node* node, EventListener* listener)
{
std::vector<EventListener*>* listeners = nullptr;
//查找是否已经存储了形参node
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移除这个节点key,并且删除listener
{
_nodeListenersMap.erase(found);
delete listeners;
}
}
}
void EventDispatcher::addEventListener(EventListener* listener)
{
//如果没有被调用,直接添加
if (_inDispatch == 0)
{
forceAddEventListener(listener);
}
//正在被调用就将listener添加到待添加队列中,延时添加
else
{
_toAddedListeners.push_back(listener);
}
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
if (sEngine)
{
sEngine->retainScriptObject(this, listener);
}
#endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
//这里的listener是指针,如果不ratain会被释放
listener->retain();
}
//实际执行添加监听器操作的函数 添加到_listenerMap 添加到_nodeListenersMap
void EventDispatcher::forceAddEventListener(EventListener* listener)
{
EventListenerVector* listeners = nullptr;
EventListener::ListenerID listenerID = listener->getListenerID();
//从存储listenerMap中查找要添加监听器的ID
auto itr = _listenerMap.find(listenerID);
//如果没有找到,就新建一个监听器数组,将行新的listenerID和新建的监听器数组加入到listenerMap中
if (itr == _listenerMap.end())
{
listeners = new (std::nothrow) EventListenerVector();
_listenerMap.emplace(listenerID, listeners);
}
//找到了就获取对应的监听器数组
else
{
listeners = itr->second;
}
//往监听器数组中添加新的监听器
listeners->push_back(listener);
//如果优先级是0,则添加脏标记为 场景图优先级
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())
{
listener->setPaused(true);
}
}
//否则添加脏标记为 自定义优先级
else
{
setDirty(listenerID, DirtyFlag::FIXED_PRIORITY);
}
}
//添加场景图优先级的监听器
void EventDispatcher::addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node)
{
CCASSERT(listener && node, "Invalid parameters.");
CCASSERT(!listener->isRegistered(), "The listener has been registered.");
if (!listener->checkAvailable())
return;
//设置节点和监听器关联、优先级为0、已注册
listener->setAssociatedNode(node);
listener->setFixedPriority(0);
listener->setRegistered(true);
//添加监听器到
addEventListener(listener);
}
#if CC_NODE_DEBUG_VERIFY_EVENT_LISTENERS && COCOS2D_DEBUG > 0
void EventDispatcher::debugCheckNodeHasNoEventListenersOnDestruction(Node* node)
{
// Check the listeners map
for (const auto & keyValuePair : _listenerMap)
{
const EventListenerVector * eventListenerVector = keyValuePair.second;
if (eventListenerVector)
{
if (eventListenerVector->getSceneGraphPriorityListeners())
{
for (EventListener * listener : *eventListenerVector->getSceneGraphPriorityListeners())
{
CCASSERT(!listener ||
listener->getAssociatedNode() != node,
"Node should have no event listeners registered for it upon destruction!");
}
}
}
}
// Check the node listeners map
for (const auto & keyValuePair : _nodeListenersMap)
{
CCASSERT(keyValuePair.first != node, "Node should have no event listeners registered for it upon destruction!");
if (keyValuePair.second)
{
for (EventListener * listener : *keyValuePair.second)
{
CCASSERT(listener->getAssociatedNode() != node,
"Node should have no event listeners registered for it upon destruction!");
}
}
}
// Check the node priority map
for (const auto & keyValuePair : _nodePriorityMap)
{
CCASSERT(keyValuePair.first != node,
"Node should have no event listeners registered for it upon destruction!");
}
// Check the to be added list
for (EventListener * listener : _toAddedListeners)
{
CCASSERT(listener->getAssociatedNode() != node,
"Node should have no event listeners registered for it upon destruction!");
}
// Check the dirty nodes set
for (Node * dirtyNode : _dirtyNodes)
{
CCASSERT(dirtyNode != node,
"Node should have no event listeners registered for it upon destruction!");
}
}
#endif // #if CC_NODE_DEBUG_VERIFY_EVENT_LISTENERS && COCOS2D_DEBUG > 0
//添加自定义优先级的监听器
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);
}
//添加自定义监听器,默认优先级为1
EventListenerCustom* EventDispatcher::addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback)
{
EventListenerCustom *listener = EventListenerCustom::create(eventName, callback);
addEventListenerWithFixedPriority(listener, 1);
return listener;
}
//
void EventDispatcher::removeEventListener(EventListener* listener)
{
if (listener == nullptr)
return;
if (std::find(_toRemovedListeners.begin(), _toRemovedListeners.end(), listener) != _toRemovedListeners.end())
// just return if listener is in _toRemovedListeners to avoid remove listeners more than once
// 如果监听器是在_toRemovedListeners中,会在update时删除,这里直接返回,避免了重复删除
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);///< ratain住,不然会被释放掉
l->setRegistered(false); //取消注册
if (l->getAssociatedNode() != nullptr) ///<如果有关联的节点
{
dissociateNodeAndEventListener(l->getAssociatedNode(), l); ///<取消节点监听器的关联
l->setAssociatedNode(nullptr); // nullptr out the node pointer so we don't have any dangling pointers to destroyed nodes.
///<将监听器关联的节点属性置空
}
//如果没有在调用直接移除
if (_inDispatch == 0)
{
iter = listeners->erase(iter);
releaseListener(l);
}
//否则加到待删除数组中,延时删除
else
{
_toRemovedListeners.push_back(l);
}
//标记为已经移除
isFound = true;
break;
}
}
};
//遍历listenerMap
for (auto iter = _listenerMap.begin(); iter != _listenerMap.end();)
{
auto listeners = iter->second; ///<获取监听器数组
auto fixedPriorityListeners = listeners->getFixedPriorityListeners(); ///<获取自定义优先级监听器数组
auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();///<获取场景图优先级的监听器数组
removeListenerInVector(sceneGraphPriorityListeners); ///<从场景图优先级数组中移除
//如果找到了(移除成功)
if (isFound)
{
// fixed #4160: Dirty flag need to be updated after listeners were removed.
//设置场景图优先级脏标记
setDirty(listener->getListenerID(), DirtyFlag::SCENE_GRAPH_PRIORITY);
}
//没有在场景图优先级数组中找到要删除的
else
{
//从自定义优先级监听器数组中查找
removeListenerInVector(fixedPriorityListeners);
//如果找到了就设置自定义优先级的脏标记
if (isFound)
{
setDirty(listener->getListenerID(), DirtyFlag::FIXED_PRIORITY);
}
}
#if CC_NODE_DEBUG_VERIFY_EVENT_LISTENERS
CCASSERT(_inDispatch != 0 ||
!sceneGraphPriorityListeners ||
std::count(sceneGraphPriorityListeners->begin(), sceneGraphPriorityListeners->end(), listener) == 0,
"Listener should be in no lists after this is done if we're not currently in dispatch mode.");
CCASSERT(_inDispatch != 0 ||
!fixedPriorityListeners ||
std::count(fixedPriorityListeners->begin(), fixedPriorityListeners->end(), listener) == 0,
"Listener should be in no lists after this is done if we're not currently in dispatch mode.");
#endif
//如果删除指定监听器之后,监听器数组是空的了
if (iter->second->empty())
{
//从优先级脏标记表中移除这个监听器
_priorityDirtyFlagMap.erase(listener->getListenerID());
//从监听器表中移除当前监听器ID和对应的监听器数组
auto list = iter->second;
iter = _listenerMap.erase(iter);
CC_SAFE_DELETE(list);
}
//不是空的就往后遍历,如果是空的了,而且被删除了,就不用往后遍历了,迭代的当前的就是将要遍历到的
else
{
++iter;
}
//如果已经找到了,就直接break,不用再找了
if (isFound)
break;
}
//如果找到了,再release要移除的监听器
if (isFound)
{
releaseListener(listener);
}
//如果没有找到,就遍历查找_toAddedListeners,如果有就暂停、release、移除
//如果这里面也没有找到,也就是说已经没有这个监听器了
else
{
for(auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end(); ++iter)
{
if (*iter == listener)
{
listener->setRegistered(false);
releaseListener(listener);
_toAddedListeners.erase(iter);
break;
}
}
}
}
//设置优先级
void EventDispatcher::setPriority(EventListener* listener, int fixedPriority)
{
if (listener == nullptr)
return;
//遍历监听器表
for (auto& iter : _listenerMap)
{
//获取当前监听器表中的 自定义优先级 监听器数组
auto fixedPriorityListeners = iter.second->getFixedPriorityListeners();
if (fixedPriorityListeners)
{
//查找 自定义优先级 监听器数组中是否存在这个形参的监听器
auto found = std::find(fixedPriorityListeners->begin(), fixedPriorityListeners->end(), listener);
//如果找到了
if (found != fixedPriorityListeners->end())
{
CCASSERT(listener->getAssociatedNode() == nullptr, "Can't set fixed priority with scene graph based listener.");
//并且优先级和现在想要设置的不同
if (listener->getFixedPriority() != fixedPriority)
{
//重新设置优先级
listener->setFixedPriority(fixedPriority);
//再设置自定义优先级脏标记
setDirty(listener->getListenerID(), DirtyFlag::FIXED_PRIORITY);
}
return;
}
}
//为什么不遍历场景图优先级,是因为场景图优先级的优先级只能为0
}
}
//分发事件
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;
//优先级小于0的监听器数组
// priority < 0
if (fixedPriorityListeners)
{
CCASSERT(listeners->getGt0Index() <= static_cast<ssize_t>(fixedPriorityListeners->size()), "Out of range exception!");
//如果不是空的
if (!fixedPriorityListeners->empty())
{
//遍历小于0的监听器,getGt0Index是获取小于0的监听器数量,在对小于0监听器排序的时候会设置
for (; i < listeners->getGt0Index(); ++i)
{
//遍历获取每一个优先级小于0的监听器
auto l = fixedPriorityListeners->at(i);
//启用了、没暂停、注册了、调用匿名函数成功了
if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
{
//标记分发成功
shouldStopPropagation = true;
break;
}
}
}
}
//如果获取到了场景图优先级数组
if (sceneGraphPriorityListeners)
{
//判断有没有分发成功
if (!shouldStopPropagation)
{
//遍历场景图优先级数组
// priority == 0, scene graph priority
for (auto& l : *sceneGraphPriorityListeners)
{
//启用了、没暂停、注册了、调用匿名函数成功了
if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
{
shouldStopPropagation = true;
break;
}
}
}
}
//接着上面小于零的监听器数组继续遍历
if (fixedPriorityListeners)
{
//判断是否已经分发
if (!shouldStopPropagation)
{
// priority > 0
//遍历剩下的自定义优先级数组
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;
}
}
}
}
}
//分发触摸事件到监听器
void EventDispatcher::dispatchTouchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent)
{
//标记已经分发
bool shouldStopPropagation = false;
//获取当前监听器数组的不同优先级监听器数组
auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
ssize_t i = 0;
//和分发事件一样
// priority < 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;
}
}
}
}
//获取当前运行的场景
auto scene = Director::getInstance()->getRunningScene();
if (scene && sceneGraphPriorityListeners)
{
if (!shouldStopPropagation)
{
// priority == 0, scene graph priority
// first, get all enabled, unPaused and registered listeners
//首先获取所有开启、不暂停、已注册的场景图优先级监听器数组,存在sceneListeners中
std::vector<EventListener*> sceneListeners;
for (auto& l : *sceneGraphPriorityListeners)
{
if (l->isEnabled() && !l->isPaused() && l->isRegistered())
{
sceneListeners.push_back(l);
}
}
// second, for all camera call all listeners
// get a copy of cameras, prevent it's been modified in listener callback
// if camera's depth is greater, process it earlier
auto cameras = scene->getCameras();
for (auto rit = cameras.rbegin(), ritRend = cameras.rend(); rit != ritRend; ++rit)
{
Camera* camera = *rit;
if (camera->isVisible() == false)
{
continue;
}
Camera::_visitingCamera = camera;
auto cameraFlag = (unsigned short)camera->getCameraFlag();
for (auto& l : sceneListeners)
{
if (nullptr == l->getAssociatedNode() || 0 == (l->getAssociatedNode()->getCameraMask() & cameraFlag))
{
continue;
}
if (onEvent(l))
{
shouldStopPropagation = true;
break;
}
}
if (shouldStopPropagation)
{
break;
}
}
Camera::_visitingCamera = nullptr;
}
}
if (fixedPriorityListeners)
{
if (!shouldStopPropagation)
{
// priority > 0
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;
}
}
}
}
}
void EventDispatcher::dispatchEvent(Event* event)
{
if (!_isEnabled)
return;
updateDirtyFlagForSceneGraph();
DispatchGuard guard(_inDispatch);
//如果是触摸事件,单独分发
if (event->getType() == Event::Type::TOUCH)
{
dispatchTouchEvent(static_cast<EventTouch*>(event));
return;
}
//获取监听器ID
auto listenerID = __getListenerID(event);
//排序
sortEventListeners(listenerID);
auto pfnDispatchEventToListeners = &EventDispatcher::dispatchEventToListeners;
if (event->getType() == Event::Type::MOUSE) {
pfnDispatchEventToListeners = &EventDispatcher::dispatchTouchEventToListeners;
}
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();
};
(this->*pfnDispatchEventToListeners)(listeners, onEvent);
}
updateListeners(event);
}
void EventDispatcher::dispatchCustomEvent(const std::string &eventName, void *optionalUserData)
{
EventCustom ev(eventName);
ev.setUserData(optionalUserData);
dispatchEvent(&ev);
}
bool EventDispatcher::hasEventListener(const EventListener::ListenerID& listenerID) const
{
return getListeners(listenerID) != nullptr;
}
//分发触摸事件
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);
//为什么不直接对originalToucher操作?
const std::vector<Touch*>& originalTouches = event->getTouches(); //获取原始的触摸数据
std::vector<Touch*> mutableTouches(originalTouches.size()); //创建新的拷贝的数组
std::copy(originalTouches.begin(), originalTouches.end(), mutableTouches.begin()); //拷贝
//
// process the target handlers 1st
// 处理单点触摸
if (oneByOneListeners)
{
//获取拷贝的触摸点数据的第一个
auto mutableTouchesIter = mutableTouches.begin();
//遍历触摸的原始数据
for (auto& touches : originalTouches)
{
//吞没设为false,不同层次的也可以接收到触摸
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;
//设置当前target
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)
{
//执行回调函数,并返回执行的结果
//可以在callback里面返回true or false,用来控制是否继续调用剩下的触摸步骤
isClaimed = listener->onTouchBegan(touches, event);
//执行成功了并且已经注册了
if (isClaimed && listener->_isRegistered)
{
//加入到已响应触摸数组中
listener->_claimedTouches.push_back(touches);
}
}
}
//否则先判断是否有已响应的监听器、并查找是否已经响应过了
else if (listener->_claimedTouches.size() > 0
&& ((removedIter = std::find(listener->_claimedTouches.begin(), listener->_claimedTouches.end(), touches)) != listener->_claimedTouches.end()))
{
//标记为已响应
isClaimed = true;
//判断响应阶段类型
switch (eventCode)
{
//移动阶段
case EventTouch::EventCode::MOVED:
if (listener->onTouchMoved)
{
listener->onTouchMoved(touches, event);
}
break;
//结束阶段
case EventTouch::EventCode::ENDED:
if (listener->onTouchEnded)
{
listener->onTouchEnded(touches, event);
}
if (listener->_isRegistered)
{
listener->_claimedTouches.erase(removedIter);
}
break;
//取消阶段
case EventTouch::EventCode::CANCELLED:
if (listener->onTouchCancelled)
{
listener->onTouchCancelled(touches, 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(touches->getID() == (*mutableTouchesIter)->getID(),
"touches ID should be equal to mutableTouchesIter's ID.");
//如果已经分发了、注册了、需要吞没
if (isClaimed && listener->_isRegistered && listener->_needSwallow)
{
//如果单点和多点都存在,就移除当前的触摸数据,吞没设为true
if (isNeedsMutableSet)
{
mutableTouchesIter = mutableTouches.erase(mutableTouchesIter);
isSwallowed = true;
}
return true;
}
return false;
};
//分发单点触摸事件
dispatchTouchEventToListeners(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;
};
//分发多点触摸事件
dispatchTouchEventToListeners(allAtOnceListeners, onTouchesEvent);
//如果是暂停了就返回
if (event->isStopped())
{
return;
}
}
//刷洗监听器数组
updateListeners(event);
}
//刷新监听器数组
//1、删除已移除的监听器
//2、添加未添加的监听器
void EventDispatcher::updateListeners(Event* event)
{
CCASSERT(_inDispatch > 0, "If program goes here, there should be event in dispatch.");
if (_inDispatch > 1)
return;
//定义刷新监听器的匿名函数
auto onUpdateListeners = [this](const EventListener::ListenerID& listenerID)
{
//在监听器表中找到listenerID对应的键值对
auto listenersIter = _listenerMap.find(listenerID);
if (listenersIter == _listenerMap.end())
return;
//获取listenerID对应的监听器数组
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;
//如果没有注册
//1、从listenerID对应的监听器数组中的场景图优先级数组中移除
//2、从toRemovedListeners中移除
//3、release释放
if (!l->isRegistered())
{
iter = sceneGraphPriorityListeners->erase(iter);
// if item in toRemove list, remove it from the list
auto matchIter = std::find(_toRemovedListeners.begin(), _toRemovedListeners.end(), l);
if (matchIter != _toRemovedListeners.end())
_toRemovedListeners.erase(matchIter);
releaseListener(l);
}
//否则遍历下一个
else
{
++iter;
}
}
}
//和场景图优先级监听器数组一样
if (fixedPriorityListeners)
{
for (auto iter = fixedPriorityListeners->begin(); iter != fixedPriorityListeners->end();)
{
auto l = *iter;
if (!l->isRegistered())
{
iter = fixedPriorityListeners->erase(iter);
// if item in toRemove list, remove it from the list
auto matchIter = std::find(_toRemovedListeners.begin(), _toRemovedListeners.end(), l);
if (matchIter != _toRemovedListeners.end())
_toRemovedListeners.erase(matchIter);
releaseListener(l);
}
else
{
++iter;
}
}
}
//如果删除完之后这两个优先级数组存在并且已经是空的了,就将数组clear(置空)
if (sceneGraphPriorityListeners && sceneGraphPriorityListeners->empty())
{
listeners->clearSceneGraphListeners();
}
if (fixedPriorityListeners && fixedPriorityListeners->empty())
{
listeners->clearFixedListeners();
}
};
//如果事件的类型是触摸类型
if (event->getType() == Event::Type::TOUCH)
{
//分类别 单点和多点监听事件监听器
onUpdateListeners(EventListenerTouchOneByOne::LISTENER_ID);
onUpdateListeners(EventListenerTouchAllAtOnce::LISTENER_ID);
}
//除触摸类型外的事件监听器类型
else
{
onUpdateListeners(__getListenerID(event));
}
CCASSERT(_inDispatch == 1, "_inDispatch should be 1 here.");
//遍历监听器数组
for (auto iter = _listenerMap.begin(); iter != _listenerMap.end();)
{
//如果没有listenerID对应的监听器数组是空的
if (iter->second->empty())
{
_priorityDirtyFlagMap.erase(iter->first);//从ID优先级map中删除这个iter的ID
delete iter->second; //删除ID对应的监听器数组,只删除指向内容,指针不删除
iter = _listenerMap.erase(iter);//从listener中移除这个iter
//删除之后不用往后递增是因为删除之后,iter已经指向下一个了
}
//如果不是空的,就遍历下一个
else
{
++iter;
}
}
//如果_toAddedListeners不是空的
if (!_toAddedListeners.empty())
{
//遍历、逐个添加
for (auto& listener : _toAddedListeners)
{
forceAddEventListener(listener);
}
//添加完清空
_toAddedListeners.clear();
}
//因为上面将未注册的监听器从_toRemovedListeners删除了,是因为在removeEventListenersForListenerID中把移除的监听器的isRegistered设为了false,如果这时_toRemovedListeners不是空,清理就行了,正常来说应该是空的了。
if (!_toRemovedListeners.empty())
{
cleanToRemovedListeners();
}
}
//刷新脏节点标记
void EventDispatcher::updateDirtyFlagForSceneGraph()
{
if (!_dirtyNodes.empty())
{
//遍历脏节点容器
for (auto& node : _dirtyNodes)
{
//从_nodeListenersMap中找到对应的键值对
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(const EventListener::ListenerID& listenerID)
{
//初始化优先级脏标记
DirtyFlag dirtyFlag = DirtyFlag::NONE;
//从listenerID-优先级 map获取参数中的优先级
auto dirtyIter = _priorityDirtyFlagMap.find(listenerID);
//如果找到了
if (dirtyIter != _priorityDirtyFlagMap.end())
{
//获取对应的优先级脏标记
dirtyFlag = dirtyIter->second;
}
//优先级不是默认优先级
if (dirtyFlag != DirtyFlag::NONE)
{
// Clear the dirty flag first, if `rootNode` is nullptr, then set its dirty flag of scene graph priority
//先清理旧的脏标记
dirtyIter->second = DirtyFlag::NONE;
//如果是自定义的优先级
if ((int)dirtyFlag & (int)DirtyFlag::FIXED_PRIORITY)
{
//排序,统计
sortEventListenersOfFixedPriority(listenerID);
}
//如果是场景图的优先级
if ((int)dirtyFlag & (int)DirtyFlag::SCENE_GRAPH_PRIORITY)
{
//获取当前场景
auto rootNode = Director::getInstance()->getRunningScene();
//获取到了
if (rootNode)
{
//排序场景图
sortEventListenersOfSceneGraphPriority(listenerID, rootNode);
}
else
{
//刷新监听器的脏标记
dirtyIter->second = DirtyFlag::SCENE_GRAPH_PRIORITY;
}
}
}
}
//对场景图优先级的监听器排序
void EventDispatcher::sortEventListenersOfSceneGraphPriority(const EventListener::ListenerID& listenerID, Node* rootNode)
{
//获取listenerID对应的监听器数组
auto listeners = getListeners(listenerID);
if (listeners == nullptr)
return;
//获取监听器数组中的场景图优先级数组
auto sceneGraphListeners = listeners->getSceneGraphPriorityListeners();
if (sceneGraphListeners == nullptr)
return;
//初始化节点优先级个数
// Reset priority index
_nodePriorityIndex = 0;
_nodePriorityMap.clear();
//遍历节点
visitTarget(rootNode, true);
// After sort: priority < 0, > 0
std::stable_sort(sceneGraphListeners->begin(), sceneGraphListeners->end(), [this](const EventListener* l1, const EventListener* l2) {
return _nodePriorityMap[l1->getAssociatedNode()] > _nodePriorityMap[l2->getAssociatedNode()];
});
#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(const EventListener::ListenerID& listenerID)
{
auto listeners = getListeners(listenerID);
if (listeners == nullptr)
return;
auto fixedListeners = listeners->getFixedPriorityListeners();
if (fixedListeners == nullptr)
return;
// After sort: priority < 0, > 0
//排序
std::stable_sort(fixedListeners->begin(), fixedListeners->end(), [](const EventListener* l1, const EventListener* l2) {
return l1->getFixedPriority() < l2->getFixedPriority();
});
// FIXME: Should use binary search
int index = 0;
//统计优先级小于0的监听器个数
for (auto& listener : *fixedListeners)
{
if (listener->getFixedPriority() >= 0)
break;
++index;
}
//设置优先级小于0的监听器个数
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
}
//获取listenerID对应的监听器数组
EventDispatcher::EventListenerVector* EventDispatcher::getListeners(const EventListener::ListenerID& listenerID) const
{
auto iter = _listenerMap.find(listenerID);
if (iter != _listenerMap.end())
{
return iter->second;
}
return nullptr;
}
//通过listenerID移除对应的监听器数组
void EventDispatcher::removeEventListenersForListenerID(const EventListener::ListenerID& listenerID)
{
//先获取listenerID对应的监听器数组
auto listenerItemIter = _listenerMap.find(listenerID);
//如果找到了
if (listenerItemIter != _listenerMap.end())
{
auto listeners = listenerItemIter->second; //获取listenerID对应的监听器数组
//获取不同优先级的监听器数组
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); // nullptr out the node pointer so we don't have any dangling pointers to destroyed nodes.
}
if (_inDispatch == 0)
{
iter = listenerVector->erase(iter);
releaseListener(l);
}
else
{
++iter;
}
}
};
//分别移除不同优先级的监听器
removeAllListenersInVector(sceneGraphPriorityListeners);
removeAllListenersInVector(fixedPriorityListeners);
// Remove the dirty flag according the 'listenerID'.
// No need to check whether the dispatcher is dispatching event.
_priorityDirtyFlagMap.erase(listenerID);
//如果没有在调用
if (!_inDispatch)
{
//清理监听器数组
listeners->clear();
//删除指向的对象
delete listeners;
//移除当前监听器数组
_listenerMap.erase(listenerItemIter);
}
}
//遍历待添加数组
for (auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end();)
{
//如果找到了和要移除的监听器ID相同的
if ((*iter)->getListenerID() == listenerID)
{
(*iter)->setRegistered(false); //注册设为false
releaseListener(*iter); //release监听器
iter = _toAddedListeners.erase(iter); //从待添加数组中移除
}
else
//这里++是为了往后递归,上面为什么不往后递归是因为移除之后,数组后面的元素就往前挪了
{
++iter;
}
}
}
//按不同的监听器类型移除,即listenerID
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);
}
//移除所有的监听器
void EventDispatcher::removeAllEventListeners()
{
bool cleanMap = true;
std::vector<EventListener::ListenerID> types;
types.reserve(_listenerMap.size());
//遍历监听器map
for (const auto& e : _listenerMap)
{
//查找自定义监听器中是否相同的ID
if (_internalCustomListenerIDs.find(e.first) != _internalCustomListenerIDs.end())
{
cleanMap = false;
}
//加入到types中
else
{
types.push_back(e.first);
}
}
//循环listenerMap中存在的listenerID
for (const auto& type : types)
{
//逐个移除
removeEventListenersForListenerID(type);
}
//没有在调度,并且没有相同ID的自定义监听器
if (!_inDispatch && cleanMap)
{
//清理监听器Map
_listenerMap.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 is an eventlistener associated with it.
//当有节点和关联的监听器时才会标记
if (_nodeListenersMap.find(node) != _nodeListenersMap.end())
{
//添加进脏节点数组
_dirtyNodes.insert(node);
}
// Also set the dirty flag for node's children
const auto& children = node->getChildren();
for (const auto& child : children)
{
setDirtyForNode(child);
}
}
void EventDispatcher::setDirty(const EventListener::ListenerID& listenerID, DirtyFlag flag)
{
auto iter = _priorityDirtyFlagMap.find(listenerID);
if (iter == _priorityDirtyFlagMap.end())
{
_priorityDirtyFlagMap.emplace(listenerID, flag);
}
else
{
int ret = (int)flag | (int)iter->second;
iter->second = (DirtyFlag) ret;
}
}
//清理待移除监听器数组
void EventDispatcher::cleanToRemovedListeners()
{
//遍历待移除监听器数组
for (auto& l : _toRemovedListeners)
{
//查找待移除监听器数组中监听器ID在listener中对应的元素
auto listenersIter = _listenerMap.find(l->getListenerID());
//如果没找到
if (listenersIter == _listenerMap.end())
{
//释放
releaseListener(l);
continue;
}
bool find = false; //标记为 未找到
auto listeners = listenersIter->second; //获取监听器ID对应的监听器数组
//获取不同优先级的监听器数组
auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
if (sceneGraphPriorityListeners)
{
//查找监听器l
auto machedIter = std::find(sceneGraphPriorityListeners->begin(), sceneGraphPriorityListeners->end(), l);
//如果找到了
if (machedIter != sceneGraphPriorityListeners->end())
{
find = true; //标记为 找到了
releaseListener(l); //释放l
sceneGraphPriorityListeners->erase(machedIter); //从场景图优先级数组中也删除
}
}
//过程同上
if (fixedPriorityListeners)
{
auto machedIter = std::find(fixedPriorityListeners->begin(), fixedPriorityListeners->end(), l);
if (machedIter != fixedPriorityListeners->end())
{
find = true;
releaseListener(l);
fixedPriorityListeners->erase(machedIter);
}
}
//如果删掉了并且两个优先级的监听器数组都是空的,就清理一下(指针指向置空)
if (find)
{
if (sceneGraphPriorityListeners && sceneGraphPriorityListeners->empty())
{
listeners->clearSceneGraphListeners();
}
if (fixedPriorityListeners && fixedPriorityListeners->empty())
{
listeners->clearFixedListeners();
}
}
//没找到 release监听器l
else
CC_SAFE_RELEASE(l);
}
//清理待移除数组
_toRemovedListeners.clear();
}
//release接口
void EventDispatcher::releaseListener(EventListener* listener)
{
#if CC_ENABLE_GC_FOR_NATIVE_OBJECTS
auto sEngine = ScriptEngineManager::getInstance()->getScriptEngine();
if (listener && sEngine)
{
sEngine->releaseScriptObject(this, listener);
}
#endif // CC_ENABLE_GC_FOR_NATIVE_OBJECTS
CC_SAFE_RELEASE(listener);
}
NS_CC_END
从零开始のcocos2dx生活(六)EventDispatcher的更多相关文章
- 从零开始のcocos2dx生活(七)ParticleSystem
CCParticleSystem是用来设置粒子效果的类 1.粒子分为两种模式:重力模式 和 半径模式 重力模式独占属性: gravity 重力方向,Vec2类型,可以分别指定不同方向的重力大小 spe ...
- 从零开始のcocos2dx生活(二)Node
节点 Node 文章目录 节点 Node 前言 变量初始化 创建一个节点对象 获取节点依赖的计数器 获取节点的描述(获取节点的Tag) 节点的局部层顺序值(LocalZOrder) 设置节点的Loca ...
- 从零开始のcocos2dx生活(十一)TableView
目录 简述 主要变量 主要方法 setVerticalFillOrder reloadData cellAtIndex updateCellAtIndex insertCellAtIndex remo ...
- 从零开始のcocos2dx生活(十)ScrollView
目录 简介 基础变量 ScrollViewDelegate Direction _dragging _container _touchMoved _bounceable _touchLength 方法 ...
- 从零开始のcocos2dx生活(九)CCBReader
NodeLoaderLibrary是用来存储节点加载器类型的类,通过registerDefaultNodeLoaders()可以注册所有默认类型的加载器 在CocosBuilder的使用手册中: 1. ...
- 从零开始のcocos2dx生活(八)ParticleSystemQuad
https://learnopengl-cn.github.io/01%20Getting%20started/04%20Hello%20Triangle/#_1 写的真的非常好-最近没时间拜读,只看 ...
- 从零开始のcocos2dx生活(一)内存管理
cocos中所有的对象都是继承自Ref基类,Ref的职责就是对对象进行引用计数管理 内存管理中最重要的是三个方法retain().release().autorelease() 在cocos中创建对象 ...
- 从零开始のcocos2dx生活(五)ActionEase
文章目录 sineEaseIn sineEaseOut sineEaseInOut expoEaseIn expoEaseOut expoEaseInOut easeIn easeOut easeIn ...
- 从零开始のcocos2dx生活(四)ActionManager
文章目录 初始化构造函数 析构函数 删除哈希元素 分配存放动作对象的空间 通过索引移除动作 暂停动作 恢复动作 暂停所有的动作 恢复所有的动作 添加动作 移除所有的动作 移除target中的所有动作 ...
随机推荐
- Gym - 101480K_K - Kernel Knights (DFS)
题意:有两队骑士各n人,每位骑士会挑战对方队伍的某一个位骑士. (可能相同) 要求找以一个区间s: 集合S中的骑士不会互相挑战. 每个集合外的骑士必定会被集合S内的某个骑士挑战. 题解:讲真被题目绕懵 ...
- C++构造函数和文件组织
构造你的函数 在 main() 上方声明函数,并在 main 下方定义函数 在 main() 上方同时声明并定义函数. 随着 C++ 程序变得越来越复杂,你可能需要将代码分成多个文件.分开保存函数定义 ...
- 实时计算轻松上手,阿里云DataWorks Stream Studio正式发布
Stream Studio是DataWorks旗下重磅推出的全新子产品.已于2019年4月18日正式对外开放使用.Stream Studi是一站式流计算开发平台,基于阿里巴巴实时计算引擎Flink构建 ...
- hdu 3832 Earth Hour(最短路变形)
Earth Hour Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 125536/65536 K (Java/Others)Total ...
- @noi.ac - 441@ 你天天努力
目录 @description@ @solution@ @accepted code@ @details@ @description@ 你天天努力,还是比不上小牛,因为小牛在家中套路.于是你决定去拜访 ...
- wamp环境搭建(Apache2.4.34+PHP7.2.7+MySQL5.5.60)
1 添加环境变量 1.1 添加Apache bin目录 1.2 添加PHP目录 2 配置Apache 2.1 修改conf/httpd.conf 将第38行SRVROOT值修改为当前Apache文件夹 ...
- 2018-8-10-WPF-使用-VisualStudio-2017-项目文件
title author date CreateTime categories WPF 使用 VisualStudio 2017 项目文件 lindexi 2018-08-10 19:16:53 +0 ...
- 洛谷 1131 [ZJOI2007] 时态同步
题目描述 小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数字1,2,3….进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路板的任何两个节点 ...
- H3C 帧中继协议栈
- PHP用正则批量替换Img中src内容,用正则表达式获取图片路径实现缩略图功能
PHP用正则批量替换Img中src内容,用正则表达式获取图片路径实现缩略图功能 网上很多正则表达式只能获取或者替换一个img的src内容,或者只能替换固定的字符串,要动态替换多个图片内容的试了几个小时 ...