Merge pull request #4578 from dumganhar/event-dispatcher-fix

closed #3463: ListenerID is std::string now. To avoid hash collision when using lots of EventCustoms.
This commit is contained in:
minggo 2013-12-20 04:03:37 -08:00
commit 15c6295361
13 changed files with 90 additions and 50 deletions

View File

@ -26,6 +26,10 @@
#include "CCEventTouch.h" #include "CCEventTouch.h"
#include "CCEventCustom.h" #include "CCEventCustom.h"
#include "CCEventListenerTouch.h" #include "CCEventListenerTouch.h"
#include "CCEventListenerAcceleration.h"
#include "CCEventListenerMouse.h"
#include "CCEventListenerKeyboard.h"
#include "CCNode.h" #include "CCNode.h"
#include "CCDirector.h" #include "CCDirector.h"
@ -59,31 +63,30 @@ private:
NS_CC_BEGIN NS_CC_BEGIN
static EventListener::ListenerID getListenerID(Event* event) static EventListener::ListenerID __getListenerID(Event* event)
{ {
EventListener::ListenerID ret; EventListener::ListenerID ret;
switch (event->getType()) switch (event->getType())
{ {
case Event::Type::ACCELERATION: case Event::Type::ACCELERATION:
ret = static_cast<EventListener::ListenerID>(EventListener::Type::ACCELERATION); ret = EventListenerAcceleration::LISTENER_ID;
break; break;
case Event::Type::CUSTOM: case Event::Type::CUSTOM:
{ {
auto customEvent = static_cast<EventCustom*>(event); auto customEvent = static_cast<EventCustom*>(event);
auto listenerID = std::hash<std::string>()(customEvent->getEventName()); ret = customEvent->getEventName();
ret = static_cast<EventListener::ListenerID>(listenerID);
} }
break; break;
case Event::Type::KEYBOARD: case Event::Type::KEYBOARD:
ret = static_cast<EventListener::ListenerID>(EventListener::Type::KEYBOARD); ret = EventListenerKeyboard::LISTENER_ID;
break; break;
case Event::Type::MOUSE: case Event::Type::MOUSE:
ret = static_cast<EventListener::ListenerID>(EventListener::Type::MOUSE); ret = EventListenerMouse::LISTENER_ID;
break; break;
case Event::Type::TOUCH: case Event::Type::TOUCH:
// Touch listener is very special, it contains two kinds of listeners, EventListenerTouchOneByOne and EventListenerTouchAllAtOnce. // Touch listener is very special, it contains two kinds of listeners, EventListenerTouchOneByOne and EventListenerTouchAllAtOnce.
// return UNKNOW instead. // return UNKNOWN instead.
ret = static_cast<EventListener::ListenerID>(EventListener::Type::UNKNOWN); CCASSERT(false, "Don't call this method if the event is for touch.");
break; break;
default: default:
CCASSERT(false, "Invalid type!"); CCASSERT(false, "Invalid type!");
@ -557,7 +560,7 @@ void EventDispatcher::dispatchEvent(Event* event)
return; return;
} }
auto listenerID = getListenerID(event); auto listenerID = __getListenerID(event);
sortEventListeners(listenerID); sortEventListeners(listenerID);
@ -580,14 +583,11 @@ void EventDispatcher::dispatchEvent(Event* event)
void EventDispatcher::dispatchTouchEvent(EventTouch* event) void EventDispatcher::dispatchTouchEvent(EventTouch* event)
{ {
auto touchOneByOneID = static_cast<EventListener::ListenerID>(EventListener::Type::TOUCH_ONE_BY_ONE); sortEventListeners(EventListenerTouchOneByOne::LISTENER_ID);
auto touchAllAtOnceID = static_cast<EventListener::ListenerID>(EventListener::Type::TOUCH_ALL_AT_ONCE); sortEventListeners(EventListenerTouchAllAtOnce::LISTENER_ID);
sortEventListeners(touchOneByOneID); auto oneByOnelisteners = getListeners(EventListenerTouchOneByOne::LISTENER_ID);
sortEventListeners(touchAllAtOnceID); auto allAtOncelisteners = getListeners(EventListenerTouchAllAtOnce::LISTENER_ID);
auto oneByOnelisteners = getListeners(touchOneByOneID);
auto allAtOncelisteners = getListeners(touchAllAtOnceID);
// If there aren't any touch listeners, return directly. // If there aren't any touch listeners, return directly.
if (nullptr == oneByOnelisteners && nullptr == allAtOncelisteners) if (nullptr == oneByOnelisteners && nullptr == allAtOncelisteners)
@ -776,7 +776,7 @@ void EventDispatcher::dispatchTouchEvent(EventTouch* event)
void EventDispatcher::updateListeners(Event* event) void EventDispatcher::updateListeners(Event* event)
{ {
auto onUpdateListeners = [this](EventListener::ListenerID listenerID) auto onUpdateListeners = [this](const EventListener::ListenerID& listenerID)
{ {
auto listenersIter = _listeners.find(listenerID); auto listenersIter = _listeners.find(listenerID);
if (listenersIter == _listeners.end()) if (listenersIter == _listeners.end())
@ -844,12 +844,12 @@ void EventDispatcher::updateListeners(Event* event)
if (event->getType() == Event::Type::TOUCH) if (event->getType() == Event::Type::TOUCH)
{ {
onUpdateListeners(static_cast<EventListener::ListenerID>(EventListener::Type::TOUCH_ONE_BY_ONE)); onUpdateListeners(EventListenerTouchOneByOne::LISTENER_ID);
onUpdateListeners(static_cast<EventListener::ListenerID>(EventListener::Type::TOUCH_ALL_AT_ONCE)); onUpdateListeners(EventListenerTouchAllAtOnce::LISTENER_ID);
} }
else else
{ {
onUpdateListeners(getListenerID(event)); onUpdateListeners(__getListenerID(event));
} }
@ -907,7 +907,7 @@ void EventDispatcher::updateDirtyFlagForSceneGraph()
} }
} }
void EventDispatcher::sortEventListeners(EventListener::ListenerID listenerID) void EventDispatcher::sortEventListeners(const EventListener::ListenerID& listenerID)
{ {
DirtyFlag dirtyFlag = DirtyFlag::NONE; DirtyFlag dirtyFlag = DirtyFlag::NONE;
@ -933,7 +933,7 @@ void EventDispatcher::sortEventListeners(EventListener::ListenerID listenerID)
} }
} }
void EventDispatcher::sortEventListenersOfSceneGraphPriority(EventListener::ListenerID listenerID) void EventDispatcher::sortEventListenersOfSceneGraphPriority(const EventListener::ListenerID& listenerID)
{ {
auto listeners = getListeners(listenerID); auto listeners = getListeners(listenerID);
@ -962,7 +962,7 @@ void EventDispatcher::sortEventListenersOfSceneGraphPriority(EventListener::List
#endif #endif
} }
void EventDispatcher::sortEventListenersOfFixedPriority(EventListener::ListenerID listenerID) void EventDispatcher::sortEventListenersOfFixedPriority(const EventListener::ListenerID& listenerID)
{ {
auto listeners = getListeners(listenerID); auto listeners = getListeners(listenerID);
@ -996,7 +996,7 @@ void EventDispatcher::sortEventListenersOfFixedPriority(EventListener::ListenerI
} }
EventDispatcher::EventListenerVector* EventDispatcher::getListeners(EventListener::ListenerID listenerID) EventDispatcher::EventListenerVector* EventDispatcher::getListeners(const EventListener::ListenerID& listenerID)
{ {
auto iter = _listeners.find(listenerID); auto iter = _listeners.find(listenerID);
if (iter != _listeners.end()) if (iter != _listeners.end())
@ -1007,7 +1007,7 @@ EventDispatcher::EventListenerVector* EventDispatcher::getListeners(EventListene
return nullptr; return nullptr;
} }
void EventDispatcher::removeEventListenersForListenerID(EventListener::ListenerID listenerID) void EventDispatcher::removeEventListenersForListenerID(const EventListener::ListenerID& listenerID)
{ {
auto listenerItemIter = _listeners.find(listenerID); auto listenerItemIter = _listeners.find(listenerID);
if (listenerItemIter != _listeners.end()) if (listenerItemIter != _listeners.end())
@ -1068,26 +1068,47 @@ void EventDispatcher::removeEventListenersForListenerID(EventListener::ListenerI
void EventDispatcher::removeEventListeners(EventListener::Type listenerType) void EventDispatcher::removeEventListeners(EventListener::Type listenerType)
{ {
CCASSERT(listenerType != EventListener::Type::CUSTOM, "Not support custom event listener type, please use EventDispatcher::removeCustomEventListeners instead."); if (listenerType == EventListener::Type::TOUCH_ONE_BY_ONE)
{
removeEventListenersForListenerID(static_cast<EventListener::ListenerID>(listenerType)); 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) void EventDispatcher::removeCustomEventListeners(const std::string& customEventName)
{ {
removeEventListenersForListenerID(std::hash<std::string>()(customEventName)); removeEventListenersForListenerID(customEventName);
} }
void EventDispatcher::removeAllEventListeners() void EventDispatcher::removeAllEventListeners()
{ {
std::vector<EventListener::ListenerID> types(_listeners.size()); std::vector<EventListener::ListenerID> types(_listeners.size());
for (auto iter = _listeners.begin(); iter != _listeners.end(); ++iter) for (const auto& e : _listeners)
{ {
types.push_back(iter->first); types.push_back(e.first);
} }
for (auto& type : types) for (const auto& type : types)
{ {
removeEventListenersForListenerID(type); removeEventListenersForListenerID(type);
} }
@ -1118,7 +1139,7 @@ void EventDispatcher::setDirtyForNode(Node* node)
} }
} }
void EventDispatcher::setDirty(EventListener::ListenerID listenerID, DirtyFlag flag) void EventDispatcher::setDirty(const EventListener::ListenerID& listenerID, DirtyFlag flag)
{ {
auto iter = _priorityDirtyFlagMap.find(listenerID); auto iter = _priorityDirtyFlagMap.find(listenerID);
if (iter == _priorityDirtyFlagMap.end()) if (iter == _priorityDirtyFlagMap.end())

View File

@ -148,22 +148,22 @@ private:
void addEventListener(EventListener* listener); void addEventListener(EventListener* listener);
/** Gets event the listener list for the event listener type. */ /** Gets event the listener list for the event listener type. */
EventListenerVector* getListeners(EventListener::ListenerID listenerID); EventListenerVector* getListeners(const EventListener::ListenerID& listenerID);
/** Update dirty flag */ /** Update dirty flag */
void updateDirtyFlagForSceneGraph(); void updateDirtyFlagForSceneGraph();
/** Removes all listeners with the same event listener ID */ /** Removes all listeners with the same event listener ID */
void removeEventListenersForListenerID(EventListener::ListenerID listenerID); void removeEventListenersForListenerID(const EventListener::ListenerID& listenerID);
/** Sort event listener */ /** Sort event listener */
void sortEventListeners(EventListener::ListenerID listenerID); void sortEventListeners(const EventListener::ListenerID& listenerID);
/** Sorts the listeners of specified type by scene graph priority */ /** Sorts the listeners of specified type by scene graph priority */
void sortEventListenersOfSceneGraphPriority(EventListener::ListenerID listenerID); void sortEventListenersOfSceneGraphPriority(const EventListener::ListenerID& listenerID);
/** Sorts the listeners of specified type by fixed priority */ /** Sorts the listeners of specified type by fixed priority */
void sortEventListenersOfFixedPriority(EventListener::ListenerID listenerID); void sortEventListenersOfFixedPriority(const EventListener::ListenerID& listenerID);
/** Updates all listeners /** Updates all listeners
* 1) Removes all listener items that have been marked as 'removed' when dispatching event. * 1) Removes all listener items that have been marked as 'removed' when dispatching event.
@ -193,7 +193,7 @@ private:
}; };
/** Sets the dirty flag for a specified listener ID */ /** Sets the dirty flag for a specified listener ID */
void setDirty(EventListener::ListenerID listenerID, DirtyFlag flag); void setDirty(const EventListener::ListenerID& listenerID, DirtyFlag flag);
/** Walks though scene graph to get the draw order for each node, it's called before sorting event listener with scene graph priority */ /** Walks though scene graph to get the draw order for each node, it's called before sorting event listener with scene graph priority */
void visitTarget(Node* node); void visitTarget(Node* node);

View File

@ -57,7 +57,7 @@ public:
CUSTOM CUSTOM
}; };
typedef std::size_t ListenerID; typedef std::string ListenerID;
protected: protected:
/** Constructor */ /** Constructor */
@ -83,7 +83,7 @@ protected:
inline bool isRegistered() const { return _isRegistered; }; inline bool isRegistered() const { return _isRegistered; };
inline Type getType() const { return _type; }; inline Type getType() const { return _type; };
inline ListenerID getListenerID() const { return _listenerID; }; inline const ListenerID& getListenerID() const { return _listenerID; };
inline void setFixedPriority(int fixedPriority) { _fixedPriority = fixedPriority; }; inline void setFixedPriority(int fixedPriority) { _fixedPriority = fixedPriority; };
inline int getFixedPriority() const { return _fixedPriority; }; inline int getFixedPriority() const { return _fixedPriority; };

View File

@ -27,6 +27,8 @@
NS_CC_BEGIN NS_CC_BEGIN
const std::string EventListenerAcceleration::LISTENER_ID = "__cc_acceleration";
EventListenerAcceleration::EventListenerAcceleration() EventListenerAcceleration::EventListenerAcceleration()
{ {
@ -59,7 +61,7 @@ bool EventListenerAcceleration::init(std::function<void(Acceleration*, Event* ev
this->onAccelerationEvent(&accEvent->_acc, event); this->onAccelerationEvent(&accEvent->_acc, event);
}; };
if (EventListener::init(Type::ACCELERATION, static_cast<ListenerID>(Type::ACCELERATION), listener)) if (EventListener::init(Type::ACCELERATION, LISTENER_ID, listener))
{ {
onAccelerationEvent = callback; onAccelerationEvent = callback;
return true; return true;

View File

@ -33,6 +33,8 @@ NS_CC_BEGIN
class EventListenerAcceleration : public EventListener class EventListenerAcceleration : public EventListener
{ {
public: public:
static const std::string LISTENER_ID;
static EventListenerAcceleration* create(std::function<void(Acceleration*, Event*)> callback); static EventListenerAcceleration* create(std::function<void(Acceleration*, Event*)> callback);
virtual ~EventListenerAcceleration(); virtual ~EventListenerAcceleration();

View File

@ -35,7 +35,7 @@ EventListenerCustom::EventListenerCustom()
EventListenerCustom* EventListenerCustom::create(const std::string& eventName, std::function<void(EventCustom*)> callback) EventListenerCustom* EventListenerCustom::create(const std::string& eventName, std::function<void(EventCustom*)> callback)
{ {
EventListenerCustom* ret = new EventListenerCustom(); EventListenerCustom* ret = new EventListenerCustom();
if (ret && ret->init(std::hash<std::string>()(eventName), callback)) if (ret && ret->init(eventName, callback))
{ {
ret->autorelease(); ret->autorelease();
} }

View File

@ -29,6 +29,8 @@
NS_CC_BEGIN NS_CC_BEGIN
const std::string EventListenerKeyboard::LISTENER_ID = "__cc_keyboard";
bool EventListenerKeyboard::checkAvailable() bool EventListenerKeyboard::checkAvailable()
{ {
if (onKeyPressed == nullptr && onKeyReleased == nullptr) if (onKeyPressed == nullptr && onKeyReleased == nullptr)
@ -92,7 +94,7 @@ bool EventListenerKeyboard::init()
} }
}; };
if (EventListener::init(Type::KEYBOARD, static_cast<ListenerID>(Type::KEYBOARD), listener)) if (EventListener::init(Type::KEYBOARD, LISTENER_ID, listener))
{ {
return true; return true;
} }

View File

@ -36,6 +36,8 @@ class Event;
class EventListenerKeyboard : public EventListener class EventListenerKeyboard : public EventListener
{ {
public: public:
static const std::string LISTENER_ID;
static EventListenerKeyboard* create(); static EventListenerKeyboard* create();
/// Overrides /// Overrides

View File

@ -27,6 +27,8 @@
NS_CC_BEGIN NS_CC_BEGIN
const std::string EventListenerMouse::LISTENER_ID = "__cc_mouse";
bool EventListenerMouse::checkAvailable() bool EventListenerMouse::checkAvailable()
{ {
return true; return true;
@ -99,7 +101,7 @@ bool EventListenerMouse::init()
} }
}; };
if (EventListener::init(Type::MOUSE, static_cast<ListenerID>(Type::MOUSE), listener)) if (EventListener::init(Type::MOUSE, LISTENER_ID, listener))
{ {
return true; return true;
} }

View File

@ -36,6 +36,8 @@ class Event;
class EventListenerMouse : public EventListener class EventListenerMouse : public EventListener
{ {
public: public:
static const std::string LISTENER_ID;
static EventListenerMouse* create(); static EventListenerMouse* create();
/// Overrides /// Overrides

View File

@ -30,6 +30,8 @@
NS_CC_BEGIN NS_CC_BEGIN
const std::string EventListenerTouchOneByOne::LISTENER_ID = "__cc_touch_one_by_one";
EventListenerTouchOneByOne::EventListenerTouchOneByOne() EventListenerTouchOneByOne::EventListenerTouchOneByOne()
: onTouchBegan(nullptr) : onTouchBegan(nullptr)
, onTouchMoved(nullptr) , onTouchMoved(nullptr)
@ -46,7 +48,7 @@ EventListenerTouchOneByOne::~EventListenerTouchOneByOne()
bool EventListenerTouchOneByOne::init() bool EventListenerTouchOneByOne::init()
{ {
if (EventListener::init(Type::TOUCH_ONE_BY_ONE, static_cast<ListenerID>(Type::TOUCH_ONE_BY_ONE), nullptr)) if (EventListener::init(Type::TOUCH_ONE_BY_ONE, LISTENER_ID, nullptr))
{ {
return true; return true;
} }
@ -107,6 +109,9 @@ EventListenerTouchOneByOne* EventListenerTouchOneByOne::clone()
} }
///////// /////////
const std::string EventListenerTouchAllAtOnce::LISTENER_ID = "__cc_touch_all_at_once";
EventListenerTouchAllAtOnce::EventListenerTouchAllAtOnce() EventListenerTouchAllAtOnce::EventListenerTouchAllAtOnce()
: onTouchesBegan(nullptr) : onTouchesBegan(nullptr)
, onTouchesMoved(nullptr) , onTouchesMoved(nullptr)
@ -122,7 +127,7 @@ EventListenerTouchAllAtOnce::~EventListenerTouchAllAtOnce()
bool EventListenerTouchAllAtOnce::init() bool EventListenerTouchAllAtOnce::init()
{ {
if (EventListener::init(Type::TOUCH_ALL_AT_ONCE, static_cast<ListenerID>(Type::TOUCH_ALL_AT_ONCE), nullptr)) if (EventListener::init(Type::TOUCH_ALL_AT_ONCE, LISTENER_ID, nullptr))
{ {
return true; return true;
} }

View File

@ -36,6 +36,8 @@ NS_CC_BEGIN
class EventListenerTouchOneByOne : public EventListener class EventListenerTouchOneByOne : public EventListener
{ {
public: public:
static const std::string LISTENER_ID;
static EventListenerTouchOneByOne* create(); static EventListenerTouchOneByOne* create();
virtual ~EventListenerTouchOneByOne(); virtual ~EventListenerTouchOneByOne();
@ -67,7 +69,7 @@ private:
class EventListenerTouchAllAtOnce : public EventListener class EventListenerTouchAllAtOnce : public EventListener
{ {
public: public:
static const ListenerID ID = static_cast<ListenerID>(Type::TOUCH_ALL_AT_ONCE); static const std::string LISTENER_ID;
static EventListenerTouchAllAtOnce* create(); static EventListenerTouchAllAtOnce* create();
virtual ~EventListenerTouchAllAtOnce(); virtual ~EventListenerTouchAllAtOnce();

View File

@ -195,7 +195,7 @@ bool EventListenerPhysicsContact::init()
onEvent(event); onEvent(event);
}; };
return EventListenerCustom::init(std::hash<std::string>()(PHYSICSCONTACT_EVENT_NAME), func); return EventListenerCustom::init(PHYSICSCONTACT_EVENT_NAME, func);
} }
void EventListenerPhysicsContact::onEvent(EventCustom* event) void EventListenerPhysicsContact::onEvent(EventCustom* event)