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 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::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(); } }