cocos3——11.事件分发

前端之家收集整理的这篇文章主要介绍了cocos3——11.事件分发前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
【纹理】
TextureCache::addImage
texture = new (std::nothrow) Texture2D(); // ref = 1,没有autorelease


TextureCache::removeUnusedTextures
把引用计数是1的纹理释放掉
TextureCache::removeAllTextures
释放所有缓存的纹理


【事件】
分发顺序:优先级<0,场景图顺序(从前往后)(优先级=0),优先级>0


注册订阅者:
用场景图优先级方式添加,要绑定node,默认优先级为0
void addEventListenerWithSceneGraPHPriority(EventListener* listener,Node* node);
按固定优先级方式添加,不能设置优先级为0(因为0在上面用,有特殊意义)
void addEventListenerWithFixedPriority(EventListener* listener,int fixedPriority);


添加的时候是放到一个map去:
std::unordered_map<EventListener::ListenerID,EventListenerVector*> _listenerMap;

而侦听id根据不同的事件类型获取的,每种事件对应一个字符串,而用户自定义事件则是事件的名字:

static EventListener::ListenerID __getListenerID(Event* event)
{
    EventListener::ListenerID ret;
    switch (event->getType())
    {
        case Event::Type::ACCELERATION:
            ret = EventListenerAcceleration::LISTENER_ID;
            break;
        case Event::Type::CUSTOM:
            {
                auto customEvent = static_cast<EventCustom*>(event);
                ret = customEvent->getEventName();
            }
            break;
        case Event::Type::KEYBOARD:
            ret = EventListenerKeyboard::LISTENER_ID;
            break;
        case Event::Type::MOUSE:
            ret = EventListenerMouse::LISTENER_ID;
            break;
        case Event::Type::FOCUS:
            ret = EventListenerFocus::LISTENER_ID;
            break;
        case Event::Type::TOUCH:
            // Touch listener is very special,it contains two kinds of listeners,EventListenerTouchOneByOne and EventListenerTouchAllAtOnce.
            // return UNKNOWN instead.
            CCASSERT(false,"Don't call this method if the event is for touch.");
            break;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
        case Event::Type::GAME_CONTROLLER:
            ret = EventListenerController::LISTENER_ID;
            break;
#endif
        default:
            CCASSERT(false,"Invalid type!");
            break;
    }
    
    return ret;
}


暂停、恢复与节点相关的侦听
void resumeEventListenersForTarget(Node* target,bool recursive = false);
void pauseEventListenersForTarget(Node* target,bool recursive = false);


开关订阅
inline void setEnabled(bool enabled)
inline bool isEnabled()


设置优先级
void setPriority(EventListener* listener,int fixedPriority);


分发事件:
void dispatchEvent(Event* event);
void dispatchCustomEvent(const std::string &eventName,void *optionalUserData = nullptr);

void EventDispatcher::dispatchEvent(Event* event)
{
    if (!_isEnabled)
        return;
    
    updateDirtyFlagForSceneGraph();
    
    
    DispatchGuard guard(_inDispatch);
    
    if (event->getType() == Event::Type::TOUCH)
    {
        dispatchTouchEvent(static_cast<EventTouch*>(event));
        return;
    }
    
    auto listenerID = __getListenerID(event);
    
    sortEventListeners(listenerID);
    
    auto iter = _listenerMap.find(listenerID);
    if (iter != _listenerMap.end())
    {
        auto listeners = iter->second;
        
        auto onEvent = [&event](EventListener* listener) -> bool{
            event->setCurrentTarget(listener->getAssociatedNode());
            listener->_onEvent(event);
            return event->isStopped();
        };
        
        dispatchEventToListeners(listeners,onEvent);
    }
    
    updateListeners(event);
}

分发的过程:先对标记为dirty的侦听者进行排序,然后根据事件的侦听id找到对应的侦听者集合,然后遍历处理。而处理的结果event->isStopped会影响该事件是否继续传递给其他侦听者。

void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners,const std::function<bool(EventListener*)>& onEvent)
{
    bool shouldStopPropagation = false;
    auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
    auto sceneGraPHPriorityListeners = listeners->getSceneGraPHPriorityListeners();
    
    ssize_t i = 0;
    // priority < 0
    if (fixedPriorityListeners)
    {
        CCASSERT(listeners->getGt0Index() <= static_cast<ssize_t>(fixedPriorityListeners->size()),"Out of range exception!");
        
        if (!fixedPriorityListeners->empty())
        {
            for (; i < listeners->getGt0Index(); ++i)
            {
                auto l = fixedPriorityListeners->at(i);
                if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
                {
                    shouldStopPropagation = true;
                    break;
                }
            }
        }
    }
    
    if (sceneGraPHPriorityListeners)
    {
        if (!shouldStopPropagation)
        {
            // priority == 0,scene graph priority
            for (auto& l : *sceneGraPHPriorityListeners)
            {
                if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
                {
                    shouldStopPropagation = true;
                    break;
                }
            }
        }
    }

    if (fixedPriorityListeners)
    {
        if (!shouldStopPropagation)
        {
            // priority > 0
            ssize_t size = fixedPriorityListeners->size();
            for (; i < size; ++i)
            {
                auto l = fixedPriorityListeners->at(i);
                
                if (l->isEnabled() && !l->isPaused() && l->isRegistered() && onEvent(l))
                {
                    shouldStopPropagation = true;
                    break;
                }
            }
        }
    }
}

猜你在找的Cocos2d-x相关文章