Cocos2d-x 学习笔记(19) Control Invocation
【Cocos2d-x 学习笔记 目录链接】
1. 简介
control为其子类提供了touch回调函数,当子类触发EventType相关事件时,会调用相关的回调函数。
control对象接收到的事件类型分9类:
enum class CC_EX_DLL EventType { TOUCH_DOWN = 1 << 0, DRAG_INSIDE = 1 << 1, DRAG_OUTSIDE = 1 << 2, DRAG_ENTER = 1 << 3, DRAG_EXIT = 1 << 4, TOUCH_UP_INSIDE = 1 << 5, TOUCH_UP_OUTSIDE = 1 << 6, TOUCH_CANCEL = 1 << 7, VALUE_CHANGED = 1 << 8 };
用二进制的不同位表示单一的事件类型,说明这些类型可以同时发生。我们用或运算对多个单一事件进行拼接,形成综合的事件。判断事件类型时,对二进制按位与运算检测,得出综合事件包含了哪些单一事件。
control所处的状态分为4种:
enum class State { NORMAL = 1 << 0, HIGH_LIGHTED = 1 << 1, DISABLED = 1 << 2, SELECTED = 1 << 3 };
std::unordered_map<int, Vector<Invocation*>*> _dispatchTable
该哈希表key为EventType的二进制int,value为容器Vector,里面存储了相同EventType的Invocation。
构造函数中未被create修改的变量:
_hasVisibleParents(false) _isOpacityModifyRGB(false) _state(State::NORMAL)
2. Invocation
Invocation直接继承Ref,为control而生,存储了control对象在某种EventType下执行的函数action。
create(Ref* target, Control::Handler action, Control::EventType controlEvent)
create方法调用了其构造函数,将三个参数赋给Invocation的_target _action _controlEvent。
3. 成员方法
- Control* create()
create方法调用了父类Layer的init方法,setContentSize为屏幕大小。之后调用init方法,_state设为NORMAL,_enabled为true,_selected _highlighted为false,定义了单点触摸监听器和4种回调函数,并将监听器加到事件分发器进行管理。
control是否启用(enabled),control是否被选中(Selected),control是否高亮(Highlighted)有对应的set get方法:
virtual void setEnabled(bool bEnabled); //_enabled 会同步修改_state为NORMAL或DISABLED virtual bool isEnabled() const; virtual void setSelected(bool bSelected); //_selected virtual bool isSelected() const; virtual void setHighlighted(bool bHighlighted); //_highlighted virtual bool isHighlighted() const;
三个set方法结束前都要执行needsLayout(),具体方法是由子类实现。
- Vector<Invocation*>& dispatchListforControlEvent(EventType controlEvent)
简要的说,该方法是通过参数EventType找到所有同EventType的Invocation。
该方法通过参数EventType,即control接收到的触摸类型,在_dispatchTable中根据EventType获取到Vector<Invocation*>*,将该Vector返回。如果没有EventType对应的Vector,则新建Vector,并在_dispatchTable新建项。
- void removeTargetWithActionForControlEvent(Ref* target, Handler action, EventType controlEvent)
简要的说,该方法删除符合参数要求的Invocation,从而删除三者之间的关联关系。
1. 先调用dispatchListforControlEvent,根据EventType获取Vector<Invocation*>。当参数target和action都为空时,对Vector执行clear清空。
2. 接下来,对Vector进行遍历,遍历到的每个Invocation通过参数target和action判断是否符合要求,如果符合要求,加入到容器vector tobeRemovedInvocations。
3. 遍历结束,从Vector中删除tobeRemovedInvocations里的每个Invocation。
- void removeTargetWithActionForControlEvents(Ref* target, Handler action, EventType controlEvents)
kControlEventTotalNumber是EventType类型的数量,Control头文件里定义为9。
1. 对controlEvents的二进制值分别通过9种EventType的二进制值按位与检测,得出“Events”包含了哪些“Event”。
2. 存在的每个EventType作为参数,调用了上面的removeTargetWithActionForControlEvent方法。
- void addTargetWithActionForControlEvent(Ref* target, Handler action, EventType controlEvent)
简要的说,该方法是新建了一个Invocation并存储。
该方法通过三个参数create一个Invocation,再调用dispatchListforControlEvent,通过参数EventType获取Vector<Invocation*>,再把Invocation加到Vector里。
- void addTargetWithActionForControlEvents(Ref* target, Handler action, EventType controlEvents)
通过按位与检测controlEvents包含的EventType, 对每种EventType和参数target action调用addTargetWithActionForControlEvent新建Invocation。
- Vec2 getTouchLocation(Touch* touch) 返回触摸点相对control的坐标。
- bool isTouchInside(Touch* touch) 判断Touch是否在control范围。
- bool hasVisibleParents()
当control的所有父节点都可见,返回true,存在不可见的父节点时返回false。
- void sendActionsForControlEvents(EventType controlEvents)
对controlEvents的每种EventType获得invocation,调用invocation->invoke(this)。