加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

cocos2d-x 3.7 源码分析 EventDispatcher

发布时间:2020-12-14 16:48:55 所属栏目:百科 来源:网络整理
导读:#ifndef __CC_TOUCH_H__#define __CC_TOUCH_H__#include "base/CCRef.h"#include "math/CCGeometry.h"NS_CC_BEGIN/** @class Touch * @brief Encapsulates the Touch information,such as touch point,id and so on,and provides the methods that commonly
#ifndef __CC_TOUCH_H__
#define __CC_TOUCH_H__

#include "base/CCRef.h"
#include "math/CCGeometry.h"

NS_CC_BEGIN



/** @class Touch
 * @brief Encapsulates the Touch information,such as touch point,id and so on,and provides the methods that commonly used.
 */
class CC_DLL Touch : public Ref
{
public:
    /** 
     * Dispatch mode,how the touches are dispathced.
     * @js NA
     */
    enum class DispatchMode
    {
        ALL_AT_ONCE,/** All at once. */
        ONE_BY_ONE,/** One by one. */
    };

    // 构造函数.cocos2dx源码中 void GLView::handleTouchesBegin(int num,intptr_t ids[],float xs[],float ys[])调用过。
    Touch() 
    : _id(0),_startPointCaptured(false)
    {
    
    }
    
    /** Set the touch infomation. It always used to monitor touch event.
     *
     * @param id A given id
     * @param x A given x coordinate.
     * @param y A given y coordinate.
     */
    void setTouchInfo(int id,float x,float y)
    {
        _id = id;
        _prevPoint = _point;
        _point.x   = x;
        _point.y   = y;
        
        if (!_startPointCaptured)   // 首次设置touchInfo,startPoint、prevPoint 与 point相等。
        {
            _startPoint = _point;
            _startPointCaptured = true;
            _prevPoint = _point;
        }
    }
    
    // in openGL coordinates.  (开始坐标,前一个坐标,当前坐标)
    Vec2 getStartLocation() const;
    Vec2 getPreviousLocation() const;
    Vec2 getLocation() const;


    // in screen coordinates.  (开始坐标,前一个坐标,当前坐标)
    Vec2 getStartLocationInView() const;
    Vec2 getPreviousLocationInView() const;
    Vec2 getLocationInView() const;
    
    
    
    // 当前坐标和前一个坐标之间的差值。
    Vec2 getDelta() const;
    
    
    /** Get touch id.
     * @js getId
     * @lua getId
     *
     * @return The id of touch.
     */
    int getID() const
    {
        return _id;
    }

private:
    int _id;                    // id
    bool _startPointCaptured;   // 是否捕获过开始点
    Vec2 _startPoint;           // 开始点
    Vec2 _point;                // 当前点
    Vec2 _prevPoint;            // 上一次点坐标
};



NS_CC_END

#endif
#include "base/CCTouch.h"
#include "base/CCDirector.h"

NS_CC_BEGIN

// returns the current touch location in screen coordinates
Vec2 Touch::getLocationInView() const 
{ 
    return _point; 
}

// returns the previous touch location in screen coordinates
Vec2 Touch::getPreviousLocationInView() const 
{ 
    return _prevPoint; 
}

// returns the start touch location in screen coordinates
Vec2 Touch::getStartLocationInView() const 
{ 
    return _startPoint; 
}

// returns the current touch location in OpenGL coordinates
Vec2 Touch::getLocation() const
{ 
    return Director::getInstance()->convertToGL(_point); 
}

// returns the previous touch location in OpenGL coordinates
Vec2 Touch::getPreviousLocation() const
{ 
    return Director::getInstance()->convertToGL(_prevPoint);  
}

// returns the start touch location in OpenGL coordinates
Vec2 Touch::getStartLocation() const
{ 
    return Director::getInstance()->convertToGL(_startPoint);  
}

// returns the delta position between the current location and the previous location in OpenGL coordinates
Vec2 Touch::getDelta() const
{     
    return getLocation() - getPreviousLocation();
}

NS_CC_END

Touch类相对比较简单。

待解决问题:

1.Touch对象在CCGLview的创建,以及整个流程。

2.Director::getInstance()->convertToGL(_point); 坐标转换问题。

#ifndef __CCEVENT_H__
#define __CCEVENT_H__

#include "base/CCRef.h"
#include "platform/CCPlatformMacros.h"


NS_CC_BEGIN

class Node;


// 所有事件的基类
class CC_DLL Event : public Ref
{
public:
    // 内部枚举类Type(使用方法,Event::Type::TOUCH)
    enum class Type
    {
        TOUCH,KEYBOARD,ACCELERATION,MOUSE,FOCUS,GAME_CONTROLLER,CUSTOM
    };
    
public:
    Event(Type type);
    virtual ~Event();

    // 类型
	inline Type getType() const { return _type; };
    
    // 停止传播事件
    inline void stopPropagation() { _isStopped = true; };
    
    // 事件是否停止
    inline bool isStopped() const { return _isStopped; };
    
    // 与node关联的事件才有用,fixedPriority 返回0.(It onlys be available when the event listener is associated with node. It returns 0 when the listener is associated with fixed priority.)
    inline Node* getCurrentTarget() { return _currentTarget; };
    
protected:
    inline void setCurrentTarget(Node* target) { _currentTarget = target; };
    

	Type _type;             // 描述当前对象的事件类型。
    bool _isStopped;        // 描述当前事件是否已经停止。
    Node* _currentTarget;   // 是侦听事件的Node类型的对象。
    
    friend class EventDispatcher;
};

NS_CC_END

#endif

#include "base/CCEvent.h"

NS_CC_BEGIN

Event::Event(Type type)
: _type(type),_isStopped(false),_currentTarget(nullptr)
{
}

Event::~Event()
{
}


NS_CC_END
Event类是事件类的基类,有3个重要属性:

1.target

2.type

3.isStopped

#ifndef __cocos2d_libs__TouchEvent__
#define __cocos2d_libs__TouchEvent__

#include "base/CCEvent.h"
#include <vector>


NS_CC_BEGIN

class Touch;

#define TOUCH_PERF_DEBUG 1

class CC_DLL EventTouch : public Event
{
public:
    static const int MAX_TOUCHES = 15;  // 事件的最大Touch个数。
    
    // 内部枚举类EventCode。在dispatcher event时会用到。
    enum class EventCode
    {
        BEGAN,MOVED,ENDED,CANCELLED
    };

    EventTouch();

    inline EventCode getEventCode() const { return _eventCode; };
    
    // 当前触摸屏幕所有点的列表
    inline const std::vector<Touch*>& getTouches() const { return _touches; };

    // 测试相关方法
#if TOUCH_PERF_DEBUG
    void setEventCode(EventCode eventCode) { _eventCode = eventCode; };
    void setTouches(const std::vector<Touch*>& touches) { _touches = touches; };
#endif
    
private:
    EventCode _eventCode;           // 事件code(began,moved,ended,cancelled)
    std::vector<Touch*> _touches;   // touch数组 获取当前触摸屏幕所有点的列表

    friend class GLView;
};


NS_CC_END


#endif
#include "base/CCEventTouch.h"
#include "base/CCTouch.h"

NS_CC_BEGIN

EventTouch::EventTouch()
: Event(Type::TOUCH)
{
    _touches.reserve(MAX_TOUCHES);
}

NS_CC_END
EventTouch类继承自Event,加上Event的3个属性,EventTouch共有5个属性:

1.target

2.type

3.isStopped

4.touches:当前触摸屏幕所有点的列表

5.eventCode:该属性在dispatcher中会用到,后面分析。


#ifndef __cocos2d_libs__CCCustomEvent__
#define __cocos2d_libs__CCCustomEvent__

#include <string>
#include "base/CCEvent.h"


NS_CC_BEGIN

class CC_DLL EventCustom : public Event
{
public:
    EventCustom(const std::string& eventName);
    
    inline void setUserData(void* data) { _userData = data; };
    inline void* getUserData() const { return _userData; };
    
    inline const std::string& getEventName() const { return _eventName; };
protected:
    void* _userData;        // User data
    std::string _eventName;
};

NS_CC_END

#endif

#include "base/CCEventCustom.h"
#include "base/CCEvent.h"

NS_CC_BEGIN

EventCustom::EventCustom(const std::string& eventName)
: Event(Type::CUSTOM),_userData(nullptr),_eventName(eventName)
{
}

NS_CC_END

EventCustom类继承自Event,加上Event的3个属性,EventCustom共有5个属性:

1.target

2.type

3.isStopped

4.eventName

5.userData

使用EventCustom的地方还是很多的,这里只粗略介绍下。

#ifndef __CCEVENTLISTENER_H__
#define __CCEVENTLISTENER_H__

#include <functional>
#include <string>
#include <memory>

#include "platform/CCPlatformMacros.h"
#include "base/CCRef.h"


NS_CC_BEGIN

class Event;
class Node;

/** @class EventListener
 *  @brief The base class of event listener.
 *  If you need custom listener which with different callback,you need to inherit this class.
 *  For instance,you could refer to EventListenerAcceleration,EventListenerKeyboard,EventListenerTouchOneByOne,EventListenerCustom.
 */
class CC_DLL EventListener : public Ref
{
public:
    /** Type Event type.*/  // 这个类型与Event的类型有一小点不同,就是将触摸事件类型分成了 One by One (一个接一个) 与  All At Once (同时一起)两种。
    enum class Type
    {
        UNKNOWN,TOUCH_ONE_BY_ONE,TOUCH_ALL_AT_ONCE,CUSTOM
    };

    typedef std::string ListenerID;

 
public:
    EventListener();
    bool init(Type t,const ListenerID& listenerID,const std::function<void(Event*)>& callback);
    virtual ~EventListener();

    
    // 纯虚函数监测监听器是否可用
    virtual bool checkAvailable() = 0;
    
    // 纯虚函数,因为clone的方式不同,又需要这个功能接口,所以在设置为纯虚函数,使子类必需实现。
    virtual EventListener* clone() = 0;

    // 当EventListener enabled并且not paused时,EventListener才能接受事件。
    inline void setEnabled(bool enabled) { _isEnabled = enabled; };
    inline bool isEnabled() const { return _isEnabled; };

protected:
    /** Gets the type of this listener
     *  @note It's different from `EventType`,e.g. TouchEvent has two kinds of event listeners - EventListenerOneByOne,EventListenerAllAtOnce
     */
    inline Type getType() const { return _type; };
  
    // eventType && listenerID ===> listeners.  EventListenerTouchOneByOne::LISTENER_ID = "__cc_touch_one_by_one"; EventListenerTouchAllAtOnce::LISTENER_ID = "__cc_touch_all_at_once"; (When event is being dispatched,listener ID is used as key for searching listeners according to event type.)
    inline const ListenerID& getListenerID() const { return _listenerID; };
    
    // 注册
    inline void setRegistered(bool registered) { _isRegistered = registered; };
    inline bool isRegistered() const { return _isRegistered; };
    
    /************************************************
     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 `false`,while `EventDispatcher::pauseAllEventListenersForTarget(node)` will set it to `true`.
     @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.
     
     sceneGraphPriorityListener:
     fixedPriorityListener:不使用_paused属性。
     
     paused状态在node 的“onEnter”和“onExit”中改变
     ************************************************/
    inline void setPaused(bool paused) { _paused = paused; };
    inline bool isPaused() const { return _paused; };
    
    // 获取与listener相关联的node。fixed priority listeners为nullptr。
    inline Node* getAssociatedNode() const { return _node; };
    inline void setAssociatedNode(Node* node) { _node = node; };
   

    // 用于fixed priority listeners,可以设为不为0的值。
    inline void setFixedPriority(int fixedPriority) { _fixedPriority = fixedPriority; };
    inline int getFixedPriority() const { return _fixedPriority; };

    
protected:
    Type _type;                             // Event listener type
    ListenerID _listenerID;                 // Event listener ID
    std::function<void(Event*)> _onEvent;   // Event callback function
    
    bool _isRegistered;                     // Whether the listener has been added to dispatcher.
    bool _isEnabled;                        // Whether the listener is enabled
    bool _paused;                           // Whether the listener is paused
    
    Node* _node;                            // scene graph based priority
    
    int  _fixedPriority;                    // The higher the number,the higher the priority,0 is for scene graph base priority.
    
    friend class EventDispatcher;
};

NS_CC_END

#endif

#include "base/CCEventListener.h"

NS_CC_BEGIN

EventListener::EventListener()
{}
    
EventListener::~EventListener() 
{
	CCLOGINFO("In the destructor of EventListener. %p",this);
}

bool EventListener::init(Type t,const std::function<void(Event*)>& callback)
{
    _onEvent = callback;
    _type = t;
    _listenerID = listenerID;
    _isRegistered = false;
    _paused = true;
    _isEnabled = true;
    
    return true;
}

bool EventListener::checkAvailable()
{ 
	return (_onEvent != nullptr);
}

NS_CC_END
EventListener是事件监听器的基类,有8个属性:

1.type

2.listenerID

3.onEvent

4.register

5.paused

6.enabled

7.node

8.fixedPriority

#ifndef __cocos2d_libs__CCTouchEventListener__
#define __cocos2d_libs__CCTouchEventListener__

#include "base/CCEventListener.h"
#include <vector>



NS_CC_BEGIN

class Touch;

// 单点触摸监听器
class CC_DLL EventListenerTouchOneByOne : public EventListener
{
public:
    static const std::string LISTENER_ID;
    
    // 创建单点触摸事件监听器
    static EventListenerTouchOneByOne* create();
    EventListenerTouchOneByOne();
    bool init();
    virtual ~EventListenerTouchOneByOne();
    
    // 是否吞噬掉触摸点,如果true,触摸将不会向下层传播。
    bool isSwallowTouches();
    void setSwallowTouches(bool needSwallow);
    
    /// Overrides 重写夫类的纯虚函数。
    virtual EventListenerTouchOneByOne* clone() override;
    virtual bool checkAvailable() override;
    
public:

//    typedef std::function<bool(Touch*,Event*)> ccTouchBeganCallback;
//    typedef std::function<void(Touch*,Event*)> ccTouchCallback;

    // public方法:创建监听器时,需手动设置 onTouch方法(onTouchBegan,onTouchMoved,onTouchEnded,onTouchCancelled)。
    std::function<bool(Touch*,Event*)> onTouchBegan;
    std::function<void(Touch*,Event*)> onTouchMoved;
    std::function<void(Touch*,Event*)> onTouchEnded;
    std::function<void(Touch*,Event*)> onTouchCancelled;
    
private:
    std::vector<Touch*> _claimedTouches;    // 触摸点列表。(onTouchBegan 返回true)&&(listener已经注册)过的Touch对象才会被添加。
    bool _needSwallow;                      // 是否需要吞噬触摸点
    
    friend class EventDispatcher;
};

// 多点触摸监听器
class CC_DLL EventListenerTouchAllAtOnce : public EventListener
{
public:
    static const std::string LISTENER_ID;
    
    static EventListenerTouchAllAtOnce* create();
    EventListenerTouchAllAtOnce();
    bool init();
    virtual ~EventListenerTouchAllAtOnce();
    
    /// Overrides
    virtual EventListenerTouchAllAtOnce* clone() override;
    virtual bool checkAvailable() override;
public:

    typedef std::function<void(const std::vector<Touch*>&,Event*)> ccTouchesCallback;

    ccTouchesCallback onTouchesBegan;
    ccTouchesCallback onTouchesMoved;
    ccTouchesCallback onTouchesEnded;
    ccTouchesCallback onTouchesCancelled;
    
    
private:
    
    friend class EventDispatcher;
};

NS_CC_END

#endif

#include "base/CCEventListenerTouch.h"
#include "base/CCEventDispatcher.h"
#include "base/CCEventTouch.h"
#include "base/CCTouch.h"

#include <algorithm>

NS_CC_BEGIN

const std::string EventListenerTouchOneByOne::LISTENER_ID = "__cc_touch_one_by_one";

EventListenerTouchOneByOne* EventListenerTouchOneByOne::create()
{
    auto ret = new (std::nothrow) EventListenerTouchOneByOne();
    if (ret && ret->init())
    {
        ret->autorelease();
    }
    else
    {
        CC_SAFE_DELETE(ret);
    }
    return ret;
}

EventListenerTouchOneByOne::EventListenerTouchOneByOne()
: onTouchBegan(nullptr),onTouchMoved(nullptr),onTouchEnded(nullptr),onTouchCancelled(nullptr),_needSwallow(false)
{
}

bool EventListenerTouchOneByOne::init()
{
    if (EventListener::init(Type::TOUCH_ONE_BY_ONE,LISTENER_ID,nullptr))
    {
        return true;
    }
    
    return false;
}

EventListenerTouchOneByOne::~EventListenerTouchOneByOne()
{
    CCLOGINFO("In the destructor of EventListenerTouchOneByOne,%p",this);
}


void EventListenerTouchOneByOne::setSwallowTouches(bool needSwallow)
{
    _needSwallow = needSwallow;
}

bool EventListenerTouchOneByOne::isSwallowTouches()
{
    return _needSwallow;
}

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.
    // onTouchBegin 必须需要。
    if (onTouchBegan == nullptr)
    {
        CCASSERT(false,"Invalid EventListenerTouchOneByOne!");
        return false;
    }
    
    return true;
}

EventListenerTouchOneByOne* EventListenerTouchOneByOne::clone()
{
    auto ret = new (std::nothrow) 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;
}

/////////

const std::string EventListenerTouchAllAtOnce::LISTENER_ID = "__cc_touch_all_at_once";

EventListenerTouchAllAtOnce::EventListenerTouchAllAtOnce()
: onTouchesBegan(nullptr),onTouchesMoved(nullptr),onTouchesEnded(nullptr),onTouchesCancelled(nullptr)
{
}

EventListenerTouchAllAtOnce::~EventListenerTouchAllAtOnce()
{
    CCLOGINFO("In the destructor of EventListenerTouchAllAtOnce,this);
}

bool EventListenerTouchAllAtOnce::init()
{
    if (EventListener::init(Type::TOUCH_ALL_AT_ONCE,nullptr))
    {
        return true;
    }
    
    return false;
}

EventListenerTouchAllAtOnce* EventListenerTouchAllAtOnce::create()
{
    auto ret = new (std::nothrow) EventListenerTouchAllAtOnce();
    if (ret && ret->init())
    {
        ret->autorelease();
    }
    else
    {
        CC_SAFE_DELETE(ret);
    }
    return ret;
}

bool EventListenerTouchAllAtOnce::checkAvailable()
{
    // onTouchesBegin、onTouchesMoved、onTouchesEnded、onTouchesCancelled 只需要任意一个不为空就行了
    if (onTouchesBegan == nullptr && onTouchesMoved == nullptr&& onTouchesEnded == nullptr && onTouchesCancelled == nullptr)
    {
        CCASSERT(false,"Invalid EventListenerTouchAllAtOnce!");
        return false;
    }
    
    return true;
}

EventListenerTouchAllAtOnce* EventListenerTouchAllAtOnce::clone()
{
    auto ret = new (std::nothrow) EventListenerTouchAllAtOnce();
    if (ret && ret->init())
    {
        ret->autorelease();
        
        ret->onTouchesBegan = onTouchesBegan;
        ret->onTouchesMoved = onTouchesMoved;
        ret->onTouchesEnded = onTouchesEnded;
        ret->onTouchesCancelled = onTouchesCancelled;
    }
    else
    {
        CC_SAFE_DELETE(ret);
    }
    return ret;
}

NS_CC_END
EventListenerTouch是EventListener的子类,具有EventListener的所有属性,加上自身4个属性,共14个属性:

1.onTouchBegan

2.onTouchMove

3.onTouchEnded

4.onTouchCanceled

5.claimedTouches

6.needSwallow

7.type

8.listenerID

9.onEvent

10.paused

11.enabled

12.registered

13.node

14.fixedPriority


#ifndef __cocos2d_libs__CCCustomEventListener__
#define __cocos2d_libs__CCCustomEventListener__

#include "base/CCEventListener.h"

NS_CC_BEGIN

class EventCustom;


/****************************************************************************
 用法:
    // 1.dispatcher
    auto dispatcher = Director::getInstance()->getEventDispatcher();
 
    // 2.addListener
    auto listener = EventListenerCustom::create("your_event_type",[](EventCustom* event){ do_some_thing(); });
    dispatcher->addEventListenerWithSceneGraphPriority(listener,one_node);
 
    // 3.dispatcherEvent,触发事件。
    EventCustom event("your_event_type");
    dispatcher->dispatchEvent(&event);
 
 ****************************************************************************/
// EventCustom
class CC_DLL EventListenerCustom : public EventListener
{
public:
    // 当特定的事件被分发,对应callback将会被调用
    static EventListenerCustom* create(const std::string& eventName,const std::function<void(EventCustom*)>& callback);
    EventListenerCustom();
    bool init(const ListenerID& listenerId,const std::function<void(EventCustom*)>& callback);
    
    
    /// Overrides
    virtual bool checkAvailable() override;
    virtual EventListenerCustom* clone() override;
protected:
    std::function<void(EventCustom*)> _onCustomEvent;
    
    friend class LuaEventListenerCustom;
};

NS_CC_END

#endif

#include "base/CCEventListenerCustom.h"
#include "base/CCEventCustom.h"

NS_CC_BEGIN

EventListenerCustom::EventListenerCustom()
: _onCustomEvent(nullptr)
{
}

EventListenerCustom* EventListenerCustom::create(const std::string& eventName,const std::function<void(EventCustom*)>& callback)
{
    EventListenerCustom* ret = new (std::nothrow) EventListenerCustom();
    if (ret && ret->init(eventName,callback))
    {
        ret->autorelease();
    }
    else
    {
        CC_SAFE_DELETE(ret);
    }
    return ret;
}

bool EventListenerCustom::init(const ListenerID& listenerId,const std::function<void(EventCustom*)>& callback)
{
    bool ret = false;
    
    // callback ==> listener.
    // EventListenerCustom的onCustomEvent 与 EventListener的onEvent相关联。
    _onCustomEvent = callback;
    auto listener = [this](Event* event){
        if (_onCustomEvent != nullptr)
        {
            _onCustomEvent(static_cast<EventCustom*>(event));
        }
    };
    
    // event参数的传入
    // EventListener::init(Type t,ListenerID listenerID,std::function<void(Event*)>& callback)
    if (EventListener::init(EventListener::Type::CUSTOM,listenerId,listener))
    {
        ret = true;
    }
    return ret;
}

EventListenerCustom* EventListenerCustom::clone()
{
    EventListenerCustom* ret = new (std::nothrow) EventListenerCustom();
    if (ret && ret->init(_listenerID,_onCustomEvent))
    {
        ret->autorelease();
    }
    else
    {
        CC_SAFE_DELETE(ret);
    }
    return ret;
}

bool EventListenerCustom::checkAvailable()
{
    bool ret = false;
    if (EventListener::checkAvailable() && _onCustomEvent != nullptr)
    {
        ret = true;
    }
    return ret;
}

NS_CC_END
EventListenerCustom是EventListener的子类,共有9个属性:

1.onCustomEvent

2.onEvent

3.type

4.listenerID

5.registered

6.paused

7.enabled

8.node

9.fixedPriority

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读