源码版本来自3.x,转载请注明
cocos2d-x 源码分析总目录
http://blog.csdn.net/u011225840/article/details/31743129
1.继承结构
1.1 结构
不详吐槽太多,也不贴图了,贴图要审核好久好久好久好久。
从小到大,先来看下Event的结构。
1.Event--------EventTouch,EventCustom,EventMouse,EventKeyboard,EventFocus,EventAcceleration
其中,EventTouch 和 EventCustom是比较特殊的两个Event。EventTouch是3.x版本的触摸机制相关的Event,而EventCustom则是3.x自定义事件机制的基础,该机制取代了2.x版本中的NotificationCenter。
2.EventListener-------------EventListenerTouchOneByOne,EventListenerTouchAllAtOnce,EventListenerCustom,EventListenerFocus,EventListenerMouse....对应
相比于Event,Listener多了一个,因为对应的Touch被拆分成了两个Listener,一个是OneByone,一个是TouchAllAtOnce。前者是onTouchBegan等函数的Listener,后者是onTouchesBegan等函数的Listener。
1.2.EventDispatcher,EventListener,Event三者的关系
Event相当于data,EventListener包含了data与fuction的一种映射关系,而EventDispatcher相当于一个Manager,管理着EventListener,决定着Event的调用顺序。
Event中包含了type,target等信息;EventListener包含了ListenerID,相关联的Node,对应的callBack;EventDispatcher里含有各种map,vector来管理不同的Listener。具体的,可以看源码分析。
2.源码分析
本次源码分析的量比较大,大家要有心理准备哟~
2.1Event相关
2.1.1 Event
enum class Type
{
TOUCH,
KEYBOARD,
ACCELERATION,
MOUSE,
FOCUS,
CUSTOM
};
Type _type; ///< Event type
bool _isStopped; ///< whether the event has been stopped.
Node* _currentTarget;
Event主要包含了三个重要的变量,type,是一个enum变量,里面定义了类型;isStopped定义该event是否已经停止,当一个event发生停止时,与其相关的Listener都要停止callback的调用;currentTarget是与该Event相关联的node。
2.1.2 EventTouch
EventTouch是cocos2d-x引擎中非常非常重要的事件。对应于四种touch操作,该类内部定义了四种EventCode
enum class EventCode
{
BEGAN,
MOVED,
ENDED,
CANCELLED
};
不同的EventCode可以告诉Listener来调用不同的callback。
除此之外,EventTouch中含有std::vector<Touch*> _touches 来记录该事件相关的touch,值得注意的是,本版本默认含有的触摸点最大是5个。
2.1.3 EventCustom
EventCustom的出现取代了统治2.x版本多年的NotificationCenter,来看下EventCustom的两个重要成员变量。
void* _userData; ///< User data
std::string _eventName;
有没有似曾相识的感觉,还是一样的key,还是一样的userData(有点不一样。原来是CCObject*)。
其他的Event因为重要性以及使用度的原因,这里不再赘述,如果以后笔者对他们有新的认识,将会在这里进行添加。
2.2 EventListener相关
2.2.1 EventListener
std::function<void(Event*)> _onEvent; /// Event callback function
Type _type; /// Event listener type
ListenerID _listenerID; /// Event listener ID
bool _isRegistered; /// Whether the listener has been added to dispatcher.
int _fixedPriority; // The higher the number, the higher the priority, 0 is for scene graph base priority.
Node* _node; // scene graph based priority
bool _paused; // Whether the listener is paused
bool _isEnabled; // Whether the listener is enabled
重要的成员变量:
1.onEvent,是绑定于该Listener的callback function,该func的声明使用了c++11的新特性。
2.type与Event类似,增加一个Unknown的属性。
3.isRegistered变量非常重要,如果他没有被注册,则他的事件不会触发。
4.优先级代表了响应一个事件时的顺序,该值越低,越先响应。
5.node 代表了与该listener相关的node,用于 scene graph类的事件响应,具体的在Dispatcher里面有进行介绍。
6.最后说下ListenerID,这是该类型事件的标识符。除了EventCustomListener的ListerID是与name相关的,其余的ListenerID都是固定的,用于标识该类EventListener。
/** Enables or disables the listener
* @note Only listeners with `enabled` state will be able to receive events.
* When an listener was initialized, it's enabled by default.
* An event listener can receive events when it is enabled and is not paused.
* paused state is always false when it is a fixed priority listener.
*/
inline void setEnabled(bool enabled) { _isEnabled = enabled; };
/** Sets paused state for the listener
* The paused state is only used for scene graph priority listeners.
* `EventDispatcher::resumeAllEventListenersForTarget(node)` will set the paused state to `true`,
* while `EventDispatcher::pauseAllEventListenersForTarget(node)` will set it to `false`.
* @note 1) Fixed priority listeners will never get paused. If a fixed priority doesn't want to receive events,
* call `setEnabled(false)` instead.
* 2) In `Node`'s onEnter and onExit, the `paused state` of the listeners which associated with that node will be automatically updated.
*/
inline void setPaused(bool paused) { _paused = paused; };
上面两段话,解释了什么时候一个Listener是可以接收事件,什么时候是不可以的。
1.一个Listener想接收事件必须是enabled true 并且 paused false。
2.值得注意的是,pause的变量专门是为了scenGraph类的事件存在的(后续有说明),而且一个Node的onEnter和onExit 事件会影响到与Node相关的该类事件的pause状态。
2.2.2 EventListenerOneByOne
/// Overrides
virtual EventListenerTouchOneByOne* clone() override;
virtual bool checkAvailable() override;
//
public:
std::function<bool(Touch*, Event*)> onTouchBegan;
std::function<void(Touch*, Event*)> onTouchMoved;
std::function<void(Touch*, Event*)> onTouchEnded;
std::function<void(Touch*, Event*)> onTouchCancelled;
上面的是OneByOne重载父类的方法,以及自己本身需要被绑定4个callBack 函数。
EventListenerTouchOneByOne* EventListenerTouchOneByOne::clone()
{
//深拷贝
auto ret = new EventListenerTouchOneByOne();
if (ret && ret->init())
{
ret->autorelease();
ret->onTouchBegan = onTouchBegan;
ret->onTouchMoved = onTouchMoved;
ret->onTouchEnded = onTouchEnded;
ret->onTouchCancelled = onTouchCancelled;
ret->_claimedTouches = _claimedTouches;
ret->_needSwallow = _needSwallow;
}
else
{
CC_SAFE_DELETE(ret);
}
return ret;
}
bool EventListenerTouchOneByOne::checkAvailable()
{
// EventDispatcher will use the return value of 'onTouchBegan' to determine whether to pass following 'move', 'end'
// message to 'EventListenerTouchOneByOne' or not. So 'onTouchBegan' needs to be set.
//OneByOne只需要onTouchBegan不为空,则可以认为其是可用的。
if (onTouchBegan == nullptr)
{
CCASSERT(false, "Invalid EventListenerTouchOneByOne!");
return false;
}
return true;
}
什么是可用性,当在dispatcher进行事件分发时,如果一个Listener是不可用的,则不会将该事件分