Cocos2dx - EventDispatcher事件分发器学习

admin 2018-3-27 190

addEventListenerWithSceneGraphPriority添加依据节点层级分发的事件,注册的事件都是被封装为EventListener数据包,并存放在一个容器中,此种添加事件的方式,就是决定了新添加的EventListener在容器中的位置.EventListener包括绑定节点,优先级此种方式为0,是否注册即是否添加到容器中,Id,type,_paused(默认true,该事件是否被分发)等,添加事件时如果正在从容器中获取事件分发,则延时是添加到容器,否则会影响正在分发的事件.EventListener所要添加到的容器是一个map<ListenerID,EventListenerVector*> _listenrerMap;ListenerID是一个string类型的变量,这个表示创建的是哪种类型的事件:EventListenerTouchOneByOne,EventListenerTouchAllAtOnce,EventListenerMouse等这个值在创建EventListener会自动赋值;EventListenerVector中存放了所有的ListenerID类型的EventListener事件,此时一个事件已经添加到分发事件列表中了,但是分发器还要维护一个脏标记列表map<EventListenerID,DirtyFlag>_priorityDirtyFlagMap修改EventListener会导致EventListener变脏,一个以节点为key的map<Node*,std::vector<EventListener*>>_nodeListenerMap和一个std::vector<Node*>_dirtyNode脏节点列表,修改与节点绑定的EventListener会导致Node变脏;如果绑定的node被添加到了渲染树上则恢复与该node绑定的所有的EventListener即_paused = false,导致Node变脏;

 

addEventListenerWithFixedPriority添加依据优先级分发的事件,该方式添加的事件的默认为不暂停即_paused = false;并且无绑定Node,但是有_fixedPriority属性表示EvenListener的分发优先级;

 

dispatchEvent事件分发,把_dirtyNode中的脏节点,跟新到_priorityDirtyFlagMap脏标记列表中,并清空;对分发标记_inDispatch引用计数加一;判断触发事件类型:Touch or other,Touch单独有dispatchTouchEvent分发,other此时分发;Other分发过程:根据触发事件类型获取EventListenerID,因为Touch事件有两种ID其他只有一种ID;对现有的EventListener事件排序,根据_priorityDirtyFlayMap找到对应的EventListenerID的DirtyFlag,DirtyFlag有四种1.NONE表示无类型,2.FIXED_PRIORITY表示注册的是以优先级的事件,3.SCENE_GRAPH_PRIORITY表示注册的是以Node的事件,4.ALL表示2和3都被注册了。第一种情况不排序,第二种情况是获取所有EventListenerID的EventListener,对其进行排序并对EventListener中_fixedPriority小于等于0的设置int标识,第三种情况获取所有EventListenerID的EventListener,遍历渲染树,获取到map<int,std::vector<Node*>> _globalZOrderNodeMap,int表示Node的节点的GolbalZOrder属性,因为渲染树并不是唯一决定层级的因素,对_globalZOrder排序,然后遍历所有的元素中的所有Node,合成一个priority放入map<Node*, int>_nodePriorityMap中,根据_nodePriorityMap对所有的EventListener排序,第四种,是先后进行第二种和第三种排序。

分发事件先分发priority值小于0的,然后是等于0的(绑定Node的priority为0),最后为大于0的;Touch的分发主要是多了判断EventListener类型因为他有两种,最后是更新updateListeners,主要是添加在分发过程中添加到等待容器的事件,释放未注册的EventListener。

(注意:addEventListenerWithFixedPriority以此方式添加的事件需要手动的释放,addEventListenerWithSceneGraphPriority以此种方式添加的事件在Node析构的时候会自动释放,但是此种方式效率上要低一些,因为要遍历渲染树及多次排序);

  通过静态方法创建不同类型的事件static EventListenerTouchOneByOne* create(),staticEventListenerTouchAllAtOnce* create(); static EventListenerMouse* create();等

 Director导演类是启动EventDispatcher事件分发器的地方并保存了事件分发器的实例,可以通过Director::getInstance()->getEventDispatcher()来获取事件分发类的实例,然把创建的事件通过不同的方式添加到事件分发器中。


最新回复 (0)
返回