mirror of https://github.com/axmolengine/axmol.git
issue #2087: Sorts listeners only when flag is dirty. setPriority is only valid in fixed priority listener.
This commit is contained in:
parent
d38dee32a0
commit
f7fa92aea9
|
@ -825,7 +825,7 @@ void Node::visit()
|
|||
}
|
||||
// self draw
|
||||
this->draw();
|
||||
_eventPriority = ++_globalEventPriorityIndex;
|
||||
updateEventPriorityIndex();
|
||||
|
||||
for( ; i < _children->count(); i++ )
|
||||
{
|
||||
|
@ -837,7 +837,7 @@ void Node::visit()
|
|||
else
|
||||
{
|
||||
this->draw();
|
||||
_eventPriority = ++_globalEventPriorityIndex;
|
||||
updateEventPriorityIndex();
|
||||
}
|
||||
|
||||
// reset for next frame
|
||||
|
@ -1317,6 +1317,16 @@ void Node::removeAllEventListeners()
|
|||
}
|
||||
}
|
||||
|
||||
void Node::setDirtyForAllEventListeners()
|
||||
{
|
||||
auto dispatcher = EventDispatcher::getInstance();
|
||||
|
||||
for (auto& listener : _eventlisteners)
|
||||
{
|
||||
dispatcher->setDirtyForEventType(listener->type, true);
|
||||
}
|
||||
}
|
||||
|
||||
// NodeRGBA
|
||||
NodeRGBA::NodeRGBA()
|
||||
: _displayedOpacity(255)
|
||||
|
|
|
@ -1382,11 +1382,21 @@ private:
|
|||
protected:
|
||||
|
||||
/// Upates event priority for this node.
|
||||
inline void updateEventPriorityIndex() { _eventPriority = ++_globalEventPriorityIndex; };
|
||||
inline void updateEventPriorityIndex() {
|
||||
_oldEventPriority = _eventPriority;
|
||||
_eventPriority = ++_globalEventPriorityIndex;
|
||||
if (_oldEventPriority != _eventPriority)
|
||||
{
|
||||
setDirtyForAllEventListeners();
|
||||
}
|
||||
};
|
||||
|
||||
/// Removes all event listeners that associated with this node.
|
||||
void removeAllEventListeners();
|
||||
|
||||
/// Sets dirty for event listener.
|
||||
void setDirtyForAllEventListeners();
|
||||
|
||||
/// lazy allocs
|
||||
void childrenAlloc(void);
|
||||
|
||||
|
|
|
@ -67,7 +67,6 @@ EventDispatcher::EventListenerItem::~EventListenerItem()
|
|||
|
||||
EventDispatcher::EventDispatcher()
|
||||
: _inDispatch(0)
|
||||
, _listeners(nullptr)
|
||||
, _isEnabled(true)
|
||||
{
|
||||
_toAddedListeners.reserve(50);
|
||||
|
@ -95,28 +94,25 @@ void EventDispatcher::destroyInstance()
|
|||
|
||||
void EventDispatcher::addEventListenerWithItem(EventListenerItem* item)
|
||||
{
|
||||
if (!_listeners)
|
||||
{
|
||||
_listeners = new std::map<std::string, std::vector<EventListenerItem*>*>();
|
||||
}
|
||||
|
||||
if (_inDispatch == 0)
|
||||
{
|
||||
std::vector<EventListenerItem*>* listenerList = nullptr;
|
||||
|
||||
auto itr = _listeners->find(item->listener->type);
|
||||
if (itr == _listeners->end())
|
||||
auto iter = _listeners.find(item->listener->type);
|
||||
if (iter == _listeners.end())
|
||||
{
|
||||
listenerList = new std::vector<EventListenerItem*>();
|
||||
listenerList->reserve(100);
|
||||
_listeners->insert(std::make_pair(item->listener->type, listenerList));
|
||||
_listeners.insert(std::make_pair(item->listener->type, listenerList));
|
||||
}
|
||||
else
|
||||
{
|
||||
listenerList = itr->second;
|
||||
listenerList = iter->second;
|
||||
}
|
||||
|
||||
listenerList->insert(listenerList->begin(), item);
|
||||
|
||||
setDirtyForEventType(item->listener->type, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -166,17 +162,19 @@ void EventDispatcher::addEventListenerWithFixedPriority(EventListener* listener,
|
|||
|
||||
void EventDispatcher::removeEventListener(EventListener* listener)
|
||||
{
|
||||
if (_listeners == nullptr || listener == nullptr)
|
||||
if (listener == nullptr)
|
||||
return;
|
||||
|
||||
bool isFound = false;
|
||||
|
||||
for (auto iter = _listeners->begin(); iter != _listeners->end();)
|
||||
for (auto iter = _listeners.begin(); iter != _listeners.end();)
|
||||
{
|
||||
for (auto itemIter = iter->second->begin(); itemIter != iter->second->end(); ++itemIter)
|
||||
{
|
||||
if ((*itemIter)->listener == listener)
|
||||
{
|
||||
listener->retain();
|
||||
|
||||
if (_inDispatch == 0)
|
||||
{
|
||||
(*itemIter)->listener->release();
|
||||
|
@ -196,8 +194,10 @@ void EventDispatcher::removeEventListener(EventListener* listener)
|
|||
if (iter->second->empty())
|
||||
{
|
||||
auto list = iter->second;
|
||||
iter = _listeners->erase(iter);
|
||||
iter = _listeners.erase(iter);
|
||||
CC_SAFE_DELETE(list);
|
||||
|
||||
_priorityDirtyFlagMap.erase(listener->type);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -208,52 +208,30 @@ void EventDispatcher::removeEventListener(EventListener* listener)
|
|||
break;
|
||||
}
|
||||
|
||||
if (_listeners->empty())
|
||||
if (isFound)
|
||||
{
|
||||
CC_SAFE_DELETE(_listeners);
|
||||
listener->release();
|
||||
}
|
||||
}
|
||||
|
||||
void EventDispatcher::setPriorityWithSceneGraph(EventListener* listener, Node* node)
|
||||
void EventDispatcher::setPriority(EventListener* listener, int fixedPriority)
|
||||
{
|
||||
if (_listeners == nullptr || listener == nullptr || node == nullptr)
|
||||
if (listener == nullptr)
|
||||
return;
|
||||
|
||||
for (auto iter = _listeners->begin(); iter != _listeners->end(); ++iter)
|
||||
|
||||
for (auto iter = _listeners.begin(); iter != _listeners.end(); ++iter)
|
||||
{
|
||||
for (auto itemIter = iter->second->begin(); itemIter != iter->second->end(); ++itemIter)
|
||||
{
|
||||
auto item = *itemIter;
|
||||
if (item->listener == listener)
|
||||
{
|
||||
item->fixedPriority = 0;
|
||||
CCASSERT(item->node, "Can't set fixed priority with scene graph based listener.");
|
||||
|
||||
CC_SAFE_RETAIN(node);
|
||||
CC_SAFE_RELEASE(item->node);
|
||||
item->node = node;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventDispatcher::setPriorityWithFixedValue(EventListener* listener, int fixedPriority)
|
||||
{
|
||||
if (_listeners == nullptr || listener == nullptr)
|
||||
return;
|
||||
|
||||
for (auto iter = _listeners->begin(); iter != _listeners->end(); ++iter)
|
||||
{
|
||||
for (auto itemIter = iter->second->begin(); itemIter != iter->second->end(); ++itemIter)
|
||||
{
|
||||
auto item = *itemIter;
|
||||
if (item->listener == listener)
|
||||
{
|
||||
item->fixedPriority = fixedPriority;
|
||||
if (item->node != nullptr)
|
||||
if (item->fixedPriority != fixedPriority)
|
||||
{
|
||||
item->node->dissociateEventListener(listener);
|
||||
CC_SAFE_RELEASE_NULL(item->node);
|
||||
item->fixedPriority = fixedPriority;
|
||||
setDirtyForEventType(listener->type, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -263,12 +241,24 @@ void EventDispatcher::setPriorityWithFixedValue(EventListener* listener, int fix
|
|||
|
||||
void EventDispatcher::dispatchEvent(Event* event, bool forceSortListeners)
|
||||
{
|
||||
if (_listeners == nullptr || !_isEnabled)
|
||||
if (!_isEnabled)
|
||||
return;
|
||||
|
||||
if (forceSortListeners)
|
||||
|
||||
bool isDirty = false;
|
||||
auto dirtyIter = _priorityDirtyFlagMap.find(event->_type);
|
||||
if (dirtyIter != _priorityDirtyFlagMap.end())
|
||||
{
|
||||
isDirty = dirtyIter->second;
|
||||
}
|
||||
|
||||
if (forceSortListeners || isDirty)
|
||||
{
|
||||
sortAllEventListenerItemsForType(event->_type);
|
||||
// Sets the dirty flag to false
|
||||
if (isDirty)
|
||||
{
|
||||
dirtyIter->second = false;
|
||||
}
|
||||
}
|
||||
|
||||
DispatchGuard guard(_inDispatch);
|
||||
|
@ -279,22 +269,19 @@ void EventDispatcher::dispatchEvent(Event* event, bool forceSortListeners)
|
|||
return;
|
||||
}
|
||||
|
||||
if (_listeners)
|
||||
auto iter = _listeners.find(event->getType());
|
||||
if (iter != _listeners.end())
|
||||
{
|
||||
auto iter = _listeners->find(event->getType());
|
||||
if (iter != _listeners->end())
|
||||
auto listenerList = iter->second;
|
||||
for (auto& item : *listenerList)
|
||||
{
|
||||
auto listenerList = iter->second;
|
||||
for (auto& item : *listenerList)
|
||||
{
|
||||
CCASSERT(item, "listener item is invalid.");
|
||||
CCASSERT(item, "listener item is invalid.");
|
||||
|
||||
event->setCurrentTarget(item->node);
|
||||
item->listener->onEvent(event);
|
||||
event->setCurrentTarget(item->node);
|
||||
item->listener->onEvent(event);
|
||||
|
||||
if (event->isStopped())
|
||||
break;
|
||||
}
|
||||
if (event->isStopped())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -500,11 +487,8 @@ void EventDispatcher::dispatchTouchEvent(TouchEvent* event)
|
|||
|
||||
void EventDispatcher::updateListenerItems()
|
||||
{
|
||||
if (!_listeners)
|
||||
return;
|
||||
|
||||
auto listenerItemIter = _listeners->begin();
|
||||
while (listenerItemIter != _listeners->end())
|
||||
auto listenerItemIter = _listeners.begin();
|
||||
while (listenerItemIter != _listeners.end())
|
||||
{
|
||||
for (auto iter = listenerItemIter->second->begin(); iter != listenerItemIter->second->end();)
|
||||
{
|
||||
|
@ -521,8 +505,9 @@ void EventDispatcher::updateListenerItems()
|
|||
|
||||
if (listenerItemIter->second->empty())
|
||||
{
|
||||
_priorityDirtyFlagMap.erase(listenerItemIter->first);
|
||||
delete listenerItemIter->second;
|
||||
listenerItemIter = _listeners->erase(listenerItemIter);
|
||||
listenerItemIter = _listeners.erase(listenerItemIter);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -536,12 +521,12 @@ void EventDispatcher::updateListenerItems()
|
|||
|
||||
for (auto& item : _toAddedListeners)
|
||||
{
|
||||
auto itr = _listeners->find(item->listener->type);
|
||||
if (itr == _listeners->end())
|
||||
auto itr = _listeners.find(item->listener->type);
|
||||
if (itr == _listeners.end())
|
||||
{
|
||||
listenerList = new std::vector<EventListenerItem*>();
|
||||
listenerList->reserve(100);
|
||||
_listeners->insert(std::make_pair(item->listener->type, listenerList));
|
||||
_listeners.insert(std::make_pair(item->listener->type, listenerList));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -549,20 +534,16 @@ void EventDispatcher::updateListenerItems()
|
|||
}
|
||||
|
||||
listenerList->push_back(item);
|
||||
|
||||
setDirtyForEventType(item->listener->type, true);
|
||||
}
|
||||
_toAddedListeners.clear();
|
||||
}
|
||||
|
||||
if (_listeners->empty())
|
||||
{
|
||||
delete _listeners;
|
||||
_listeners = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void EventDispatcher::sortAllEventListenerItemsForType(const std::string &eventType)
|
||||
{
|
||||
if (_listeners == nullptr)
|
||||
if (eventType.empty())
|
||||
return;
|
||||
|
||||
auto listenerList = getListenerItemsForType(eventType);
|
||||
|
@ -610,13 +591,10 @@ void EventDispatcher::sortAllEventListenerItemsForType(const std::string &eventT
|
|||
|
||||
std::vector<EventDispatcher::EventListenerItem*>* EventDispatcher::getListenerItemsForType(const std::string &eventType)
|
||||
{
|
||||
if (_listeners != nullptr)
|
||||
auto iter = _listeners.find(eventType);
|
||||
if (iter != _listeners.end())
|
||||
{
|
||||
auto iter = _listeners->find(eventType);
|
||||
if (iter != _listeners->end())
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -624,11 +602,11 @@ std::vector<EventDispatcher::EventListenerItem*>* EventDispatcher::getListenerIt
|
|||
|
||||
void EventDispatcher::removeListenersForEventType(const std::string& eventType)
|
||||
{
|
||||
if (_listeners == nullptr)
|
||||
if (eventType.empty())
|
||||
return;
|
||||
|
||||
auto listenerItemIter = _listeners->find(eventType);
|
||||
if (listenerItemIter != _listeners->end())
|
||||
auto listenerItemIter = _listeners.find(eventType);
|
||||
if (listenerItemIter != _listeners.end())
|
||||
{
|
||||
for (auto iter = listenerItemIter->second->begin(); iter != listenerItemIter->second->end(); ++iter)
|
||||
{
|
||||
|
@ -647,17 +625,15 @@ void EventDispatcher::removeListenersForEventType(const std::string& eventType)
|
|||
{
|
||||
listenerItemIter->second->clear();
|
||||
delete listenerItemIter->second;
|
||||
_listeners->erase(listenerItemIter);
|
||||
_listeners.erase(listenerItemIter);
|
||||
_priorityDirtyFlagMap.erase(eventType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventDispatcher::removeAllListeners()
|
||||
{
|
||||
if (_listeners == nullptr)
|
||||
return;
|
||||
|
||||
for (auto listenerItemIter = _listeners->begin(); listenerItemIter != _listeners->end(); ++listenerItemIter)
|
||||
for (auto listenerItemIter = _listeners.begin(); listenerItemIter != _listeners.end(); ++listenerItemIter)
|
||||
{
|
||||
for (auto iter = listenerItemIter->second->begin(); iter != listenerItemIter->second->end(); ++iter)
|
||||
{
|
||||
|
@ -676,13 +652,14 @@ void EventDispatcher::removeAllListeners()
|
|||
{
|
||||
listenerItemIter->second->clear();
|
||||
delete listenerItemIter->second;
|
||||
|
||||
_priorityDirtyFlagMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (!_inDispatch)
|
||||
{
|
||||
delete _listeners;
|
||||
_listeners = nullptr;
|
||||
_listeners.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -697,4 +674,29 @@ bool EventDispatcher::isEnabled() const
|
|||
return _isEnabled;
|
||||
}
|
||||
|
||||
void EventDispatcher::setDirtyForEventType(const std::string& eventType, bool isDirty)
|
||||
{
|
||||
auto iter = _priorityDirtyFlagMap.find(eventType);
|
||||
if (iter == _priorityDirtyFlagMap.end())
|
||||
{
|
||||
_priorityDirtyFlagMap.insert(std::make_pair(eventType, isDirty));
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->second = isDirty;
|
||||
}
|
||||
}
|
||||
|
||||
bool EventDispatcher::isDirtyForEventType(const std::string& eventType)
|
||||
{
|
||||
bool isDirty = false;
|
||||
auto iter = _priorityDirtyFlagMap.find(eventType);
|
||||
if (iter != _priorityDirtyFlagMap.end())
|
||||
{
|
||||
isDirty = iter->second;
|
||||
}
|
||||
|
||||
return isDirty;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -84,12 +84,9 @@ public:
|
|||
|
||||
/** Removes all listeners */
|
||||
void removeAllListeners();
|
||||
|
||||
/** Sets listener's priority with node's draw order. */
|
||||
void setPriorityWithSceneGraph(EventListener* listener, Node* node);
|
||||
|
||||
/** Sets listener's priority with fixed value. */
|
||||
void setPriorityWithFixedValue(EventListener* listener, int fixedPriority);
|
||||
void setPriority(EventListener* listener, int fixedPriority);
|
||||
|
||||
/** Whether to enable dispatching events */
|
||||
void setEnabled(bool isEnabled);
|
||||
|
@ -101,8 +98,12 @@ public:
|
|||
* Also removes all EventListeners marked for deletion from the
|
||||
* event dispatcher list.
|
||||
*/
|
||||
void dispatchEvent(Event* event, bool forceSortListeners = true);
|
||||
void dispatchEvent(Event* event, bool forceSortListeners = false);
|
||||
|
||||
void setDirtyForEventType(const std::string& eventType, bool isDirty);
|
||||
|
||||
bool isDirtyForEventType(const std::string& eventType);
|
||||
|
||||
public:
|
||||
/** Destructor of EventDispatcher */
|
||||
~EventDispatcher();
|
||||
|
@ -141,7 +142,11 @@ private:
|
|||
/**
|
||||
* Listeners map.
|
||||
*/
|
||||
std::map<std::string, std::vector<EventListenerItem*>*>* _listeners;
|
||||
std::map<std::string, std::vector<EventListenerItem*>*> _listeners;
|
||||
|
||||
/// Priority dirty flag
|
||||
std::map<std::string, bool> _priorityDirtyFlagMap;
|
||||
|
||||
std::vector<EventListenerItem*> _toAddedListeners;
|
||||
|
||||
int _inDispatch; ///< Whether it's in dispatching event
|
||||
|
|
|
@ -87,6 +87,7 @@ protected:
|
|||
bool _isRegistered; /// Whether the listener has been added to dispatcher.
|
||||
|
||||
friend class EventDispatcher;
|
||||
friend class Node;
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -213,7 +213,7 @@ public:
|
|||
auto listener = TouchEventListener::create(Touch::DispatchMode::ONE_BY_ONE);
|
||||
listener->setSwallowTouches(true);
|
||||
|
||||
listener->onTouchBegan = [&](Touch* touch, Event* event){
|
||||
listener->onTouchBegan = [=](Touch* touch, Event* event){
|
||||
|
||||
Point locationInNode = this->convertToNodeSpace(touch->getLocation());
|
||||
Size s = this->getContentSize();
|
||||
|
@ -227,11 +227,11 @@ public:
|
|||
return false;
|
||||
};
|
||||
|
||||
listener->onTouchMoved = [&](Touch* touch, Event* event){
|
||||
listener->onTouchMoved = [=](Touch* touch, Event* event){
|
||||
//this->setPosition(this->getPosition() + touch->getDelta());
|
||||
};
|
||||
|
||||
listener->onTouchEnded = [&](Touch* touch, Event* event){
|
||||
listener->onTouchEnded = [=](Touch* touch, Event* event){
|
||||
this->setColor(Color3B::WHITE);
|
||||
};
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ void TouchesPerformTest3::onEnter()
|
|||
{
|
||||
CC_PROFILER_START(TOUCH_PROFILER_NAME);
|
||||
|
||||
dispatcher->dispatchEvent(&event, true);
|
||||
dispatcher->dispatchEvent(&event, false);
|
||||
|
||||
CC_PROFILER_STOP(TOUCH_PROFILER_NAME);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue