zoukankan      html  css  js  c++  java
  • ‎Cocos2d-x 学习笔记(15.3) EventDispatcher DirtyFlag 脏标记

    1. 定义

    用枚举定义脏标记的4种类型。

        enum class DirtyFlag
        {
            NONE = 0,
            FIXED_PRIORITY = 1 << 0,
            SCENE_GRAPH_PRIORITY = 1 << 1,
            ALL = FIXED_PRIORITY | SCENE_GRAPH_PRIORITY
        };

    这里用两位二进制值表示4种类型:

    • 00 两容器都不脏,
    • 01 仅自定义优先级监听器容器脏了,
    • 10 仅场景图监听器容器脏了,
    • 11 都脏了。

    2. setDirty

    参数为监听器ID、要置的脏值。

    利用容器_priorityDirtyFlagMap存储脏标记信息,key:监听器ID,value:脏值。

    对脏值修改时,进行按位或操作。

    3. setDirtyForNode

    该方法是把参数node和其所有子节点加入_dirtyNodes容器中。在事件分发方法开始时,会对这些node关联的所有监听器的ID置脏标记SCENE_GRAPH_PRIORITY。

    4. 用处

    4.1 事件中

    在添加监听器到监听器容器时,根据监听器是否是场景图监听器,给受到影响的容器的listenerID置不同的脏标记。

        if (listener->getFixedPriority() == 0)
        {
            setDirty(listenerID, DirtyFlag::SCENE_GRAPH_PRIORITY);
            //...
        }
        else
        {
            setDirty(listenerID, DirtyFlag::FIXED_PRIORITY);
        }    

    从容器删除监听器时,对受影响的容器ID置不同的脏标记。

         removeListenerInVector(sceneGraphPriorityListeners);
            if (isFound)
            {
                setDirty(listener->getListenerID(), DirtyFlag::SCENE_GRAPH_PRIORITY);
            }
            else
            {
                removeListenerInVector(fixedPriorityListeners);
                if (isFound)
                {
                    setDirty(listener->getListenerID(), DirtyFlag::FIXED_PRIORITY);
                }
            }

    setPriority给指定的监听器设置指定的优先级时,需要对该ID的容器设置FIXED_PRIORITY脏标记。

                    if (listener->getFixedPriority() != fixedPriority)
                    {
                        listener->setFixedPriority(fixedPriority);
                        setDirty(listener->getListenerID(), DirtyFlag::FIXED_PRIORITY);
                    }

     使用sortEventListeners对指定的ID容器进行排序时,若ID的脏标记为NONE,则不需要排序。

        DirtyFlag dirtyFlag = DirtyFlag::NONE;
        
        auto dirtyIter = _priorityDirtyFlagMap.find(listenerID);
        if (dirtyIter != _priorityDirtyFlagMap.end())
        {
            dirtyFlag = dirtyIter->second;
        }
        
        if (dirtyFlag != DirtyFlag::NONE)
        {
            //排序操作
        }

    在事件分发函数开始时,调用updateDirtyFlagForSceneGraph(),对_dirtyNodes中的node关联的所有监听器的ID置脏标记SCENE_GRAPH_PRIORITY。

    只有使用resumeEventListenersForTarget方法,恢复指定node的所有监听器时,会把该node加入_dirtyNodes。

    4.2 Node中

    sortAllChildren setGlobalZOrder setLocalZOrder三个方法都会对参数node执行setDirtyForNode,因为这些node的优先级可能发生变化,分发事件前需要重新对他们排序,从而对监听器容器重新排序。

    5. 总结

    脏标记是为了判断是否有必要对监听器容器排序而设置。在事件分发时,当发现监听器容器之前有添加删除操作时,需要对监听器容器进行排序,把事件依次分发到排序后的容器里的监听器,由监听器进行事件处理。

    node的监听器被暂停恢复后,暂停过的这些监听器容器也需要重新排序。

    node优先级可能改变时,调用setDirtyForNode。

  • 相关阅读:
    2d向量类 —— js版
    多边形碰撞demo —— 小车撞墙壁
    真累啊——近一年的工作心得
    重力感应相关api
    坐标旋转
    判断web app是否从主屏启动
    “简单就是力量”、“重构”和“架构设计”
    多边形碰撞算法
    《是男人就下一百层》游戏小demo
    优秀的接口的评价标准
  • 原文地址:https://www.cnblogs.com/deepcho/p/cocos2dx-eventdispatcher-dirtyflag.html
Copyright © 2011-2022 走看看