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

View File

@ -148,22 +148,22 @@ private:
void addEventListener(EventListener* listener);
/** Gets event the listener list for the event listener type. */
EventListenerVector* getListeners(EventListener::ListenerID listenerID);
EventListenerVector* getListeners(const EventListener::ListenerID& listenerID);
/** Update dirty flag */
void updateDirtyFlagForSceneGraph();
/** Removes all listeners with the same event listener ID */
void removeEventListenersForListenerID(EventListener::ListenerID listenerID);
void removeEventListenersForListenerID(const EventListener::ListenerID& listenerID);
/** Sort event listener */
void sortEventListeners(EventListener::ListenerID listenerID);
void sortEventListeners(const EventListener::ListenerID& listenerID);
/** 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 */
void sortEventListenersOfFixedPriority(EventListener::ListenerID listenerID);
void sortEventListenersOfFixedPriority(const EventListener::ListenerID& listenerID);
/** Updates all listeners
* 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 */
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 */
void visitTarget(Node* node);

View File

@ -57,7 +57,7 @@ public:
CUSTOM
};
typedef std::size_t ListenerID;
typedef std::string ListenerID;
protected:
/** Constructor */
@ -83,7 +83,7 @@ protected:
inline bool isRegistered() const { return _isRegistered; };
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 int getFixedPriority() const { return _fixedPriority; };

View File

@ -27,6 +27,8 @@
NS_CC_BEGIN
const std::string EventListenerAcceleration::LISTENER_ID = "__cc_acceleration";
EventListenerAcceleration::EventListenerAcceleration()
{
@ -59,7 +61,7 @@ bool EventListenerAcceleration::init(std::function<void(Acceleration*, Event* ev
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;
return true;

View File

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

View File

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

View File

@ -29,6 +29,8 @@
NS_CC_BEGIN
const std::string EventListenerKeyboard::LISTENER_ID = "__cc_keyboard";
bool EventListenerKeyboard::checkAvailable()
{
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;
}

View File

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

View File

@ -27,6 +27,8 @@
NS_CC_BEGIN
const std::string EventListenerMouse::LISTENER_ID = "__cc_mouse";
bool EventListenerMouse::checkAvailable()
{
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;
}

View File

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

View File

@ -30,6 +30,8 @@
NS_CC_BEGIN
const std::string EventListenerTouchOneByOne::LISTENER_ID = "__cc_touch_one_by_one";
EventListenerTouchOneByOne::EventListenerTouchOneByOne()
: onTouchBegan(nullptr)
, onTouchMoved(nullptr)
@ -46,7 +48,7 @@ EventListenerTouchOneByOne::~EventListenerTouchOneByOne()
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;
}
@ -107,6 +109,9 @@ EventListenerTouchOneByOne* EventListenerTouchOneByOne::clone()
}
/////////
const std::string EventListenerTouchAllAtOnce::LISTENER_ID = "__cc_touch_all_at_once";
EventListenerTouchAllAtOnce::EventListenerTouchAllAtOnce()
: onTouchesBegan(nullptr)
, onTouchesMoved(nullptr)
@ -122,7 +127,7 @@ EventListenerTouchAllAtOnce::~EventListenerTouchAllAtOnce()
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;
}

View File

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

View File

@ -195,7 +195,7 @@ bool EventListenerPhysicsContact::init()
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)