#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@H_404_4@
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@H_404_4@
#include "base/CCEvent.h" NS_CC_BEGIN Event::Event(Type type) : _type(type),_isStopped(false),_currentTarget(nullptr) { } Event::~Event() { } NS_CC_ENDEvent类是事件类的基类,有3个重要属性:
1.target
2.type
3.isStopped@H_404_4@ @H_404_4@
#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_ENDEventTouch类继承自Event,加上Event的3个属性,EventTouch共有5个属性:
1.target
2.type
3.isStopped
4.touches:当前触摸屏幕所有点的列表
5.eventCode:该属性在dispatcher中会用到,后面分析。
@H_404_4@
#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@H_404_4@
#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@H_404_4@
#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_ENDEventListener是事件监听器的基类,有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@H_404_4@
#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_ENDEventListenerTouch是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
@H_404_4@
#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@H_404_4@
#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_ENDEventListenerCustom是EventListener的子类,共有9个属性:
1.onCustomEvent
2.onEvent
3.type
4.listenerID
5.registered
6.paused
7.enabled
8.node
9.fixedPriority
原文链接:https://www.f2er.com/cocos2dx/340480.html