void EventDispatcher::sortEventListenersOfSceneGraphPriority(const EventListener::ListenerID& listenerID, Node* rootNode) { 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::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::removeEventListenersForListenerID(const 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)->release(); iter = _toAddedListeners.erase(iter); } else { ++iter; } } }
void EventDispatcher::cleanToRemovedListeners() { for (auto& l : _toRemovedListeners) { auto listenersIter = _listenerMap.find(l->getListenerID()); if (listenersIter == _listenerMap.end()) { releaseListener(l); continue; } bool find = false; auto listeners = listenersIter->second; auto fixedPriorityListeners = listeners->getFixedPriorityListeners(); auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners(); if (sceneGraphPriorityListeners) { auto machedIter = std::find(sceneGraphPriorityListeners->begin(), sceneGraphPriorityListeners->end(), l); if (machedIter != sceneGraphPriorityListeners->end()) { find = true; releaseListener(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(); } } else CC_SAFE_RELEASE(l); } _toRemovedListeners.clear(); }
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->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; } } }; 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()); auto list = iter->second; iter = _listenerMap.erase(iter); CC_SAFE_DELETE(list); } else { ++iter; } if (isFound) break; } if (isFound) { releaseListener(listener); } else { for(auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end(); ++iter) { if (*iter == listener) { listener->setRegistered(false); releaseListener(listener); _toAddedListeners.erase(iter); break; } } } }
void EventDispatcher::removeEventListenersForListenerID(const EventListener::ListenerID& listenerID) { auto listenerItemIter = _listenerMap.find(listenerID); if (listenerItemIter != _listenerMap.end()) { auto listeners = listenerItemIter->second; auto fixedPriorityListeners = listeners->getFixedPriorityListeners(); auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners(); auto removeAllListenersInVector = [&](std::vector<EventListener*>* listenerVector){ if (listenerVector == nullptr) return; for (auto iter = listenerVector->begin(); iter != listenerVector->end();) { auto l = *iter; l->setRegistered(false); if (l->getAssociatedNode() != nullptr) { dissociateNodeAndEventListener(l->getAssociatedNode(), l); l->setAssociatedNode(nullptr); // 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();) { if ((*iter)->getListenerID() == listenerID) { (*iter)->setRegistered(false); releaseListener(*iter); iter = _toAddedListeners.erase(iter); } else { ++iter; } } }
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) { auto listenersIter = _listenerMap.find(listenerID); if (listenersIter == _listenerMap.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); // 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; } } } 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();) { if (iter->second->empty()) { _priorityDirtyFlagMap.erase(iter->first); delete iter->second; iter = _listenerMap.erase(iter); } else { ++iter; } } if (!_toAddedListeners.empty()) { for (auto& listener : _toAddedListeners) { forceAddEventListener(listener); } _toAddedListeners.clear(); } if (!_toRemovedListeners.empty()) { cleanToRemovedListeners(); } }
void EventDispatcher::updateListeners(Event* event) { auto onUpdateListeners = [this](const 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; _listeners.erase(listenersIter); } }; if (event->getType() == Event::Type::TOUCH) { onUpdateListeners(EventListenerTouchOneByOne::LISTENER_ID); onUpdateListeners(EventListenerTouchAllAtOnce::LISTENER_ID); } else { onUpdateListeners(__getListenerID(event)); } if (!_toAddedListeners.empty()) { for (auto& listener : _toAddedListeners) { forceAddEventListener(listener); } _toAddedListeners.clear(); } }
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) { 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 { for(auto iter = _toAddedListeners.begin(); iter != _toAddedListeners.end(); ++iter) { if (*iter == listener) { listener->release(); _toAddedListeners.erase(iter); break; } } } }